Package freenet.node.simulator

Source Code of freenet.node.simulator.LongTermManySingleBlocksTest$InsertBatch$BatchInsert

package freenet.node.simulator;

import static java.util.concurrent.TimeUnit.HOURS;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.TimeZone;

import freenet.client.ClientMetadata;
import freenet.client.FetchContext;
import freenet.client.FetchException;
import freenet.client.FetchException.FetchExceptionMode;
import freenet.client.FetchWaiter;
import freenet.client.HighLevelSimpleClient;
import freenet.client.InsertBlock;
import freenet.client.InsertException;
import freenet.client.InsertException.InsertExceptionMode;
import freenet.crypt.RandomSource;
import freenet.keys.FreenetURI;
import freenet.node.Node;
import freenet.node.NodeStarter;
import freenet.node.RequestClient;
import freenet.node.Version;
import freenet.support.Logger;
import freenet.support.Logger.LogLevel;
import freenet.support.PooledExecutor;
import freenet.support.api.RandomAccessBucket;
import freenet.support.io.Closer;
import freenet.support.io.FileUtil;

/**
* Insert 32x single blocks. Pull them individually, with 0 retries, after 2^n-1
* days, for n in 0...8.
* @author Matthew Toseland <toad@amphibian.dyndns.org> (0xE43DA450)
*/
public class LongTermManySingleBlocksTest extends LongTermTest {
 
  public static class InsertBatch {

    private final HighLevelSimpleClient client;
    private int runningInserts;
    private ArrayList<BatchInsert> inserts = new ArrayList<BatchInsert>();
   
    public InsertBatch(HighLevelSimpleClient client) {
      this.client = client;
      // TODO Auto-generated constructor stub
    }

    public void startInsert(InsertBlock block) {
      BatchInsert bi = new BatchInsert(block);
      synchronized(this) {
        inserts.add(bi);
      }
      bi.start();
    }
   
    class BatchInsert implements Runnable {

      private final InsertBlock block;
      //private boolean finished = false;
      //private boolean started = false;
      private long insertTime;
      private InsertException failed;
      private FreenetURI uri;
     
      public BatchInsert(InsertBlock block) {
        this.block = block;
      }

      public void start() {
        Thread t = new Thread(this);
        t.setDaemon(true);
        t.start();
      }

      @Override
      public void run() {
        synchronized(InsertBatch.this) {
          runningInserts++;
          //started = true;
          System.out.println("Starting insert: running "+runningInserts);
        }
        long t1 = 0, t2 = 0;
        FreenetURI thisURI = null;
        InsertException f = null;
        try {
          t1 = System.currentTimeMillis();
          thisURI = client.insert(block, false, null);
          t2 = System.currentTimeMillis();
        } catch (InsertException e) {
          f = e;
        } finally {
          synchronized(InsertBatch.this) {
            runningInserts--;
            System.out.println("Completed insert: running "+runningInserts);
            //finished = true;
            if(thisURI != null) {
              uri = thisURI;
              insertTime = t2 - t1;
            } else {
              if(f != null)
                failed = f;
              else
                f = new InsertException(InsertExceptionMode.INTERNAL_ERROR);
            }
             
            InsertBatch.this.notifyAll();
          }
        }
      }
     
    }

    public synchronized void waitUntilFinished() {
      while(true) {
        if(runningInserts == 0) return;
        try {
          wait();
        } catch (InterruptedException e) {
          // Ignore
        }
      }
    }

    public synchronized FreenetURI[] getURIs() {
      FreenetURI[] uris = new FreenetURI[inserts.size()];
      for(int i=0;i<uris.length;i++)
        uris[i] = inserts.get(i).uri;
      return uris;
    }

    public synchronized long[] getTimes() {
      long[] times = new long[inserts.size()];
      for(int i=0;i<times.length;i++)
        times[i] = inserts.get(i).insertTime;
      return times;
    }

    public InsertException[] getErrors() {
      InsertException[] errors = new InsertException[inserts.size()];
      for(int i=0;i<errors.length;i++)
        errors[i] = inserts.get(i).failed;
      return errors;
    }

  }

  private static final int TEST_SIZE = 32 * 1024;

  private static final int DARKNET_PORT1 = 9010;
  private static final int OPENNET_PORT1 = 9011;
 
  private static final int MAX_N = 8;
 
  private static final int INSERTED_BLOCKS = 32;

  public static void main(String[] args) {
    if (args.length < 1 || args.length > 2) {
      System.err.println("Usage: java freenet.node.simulator.LongTermPushPullTest <unique identifier>");
      System.exit(1);
    }
    String uid = args[0];
   
    List<String> csvLine = new ArrayList<String>();
    System.out.println("DATE:" + dateFormat.format(today.getTime()));
    csvLine.add(dateFormat.format(today.getTime()));

    System.out.println("Version:" + Version.buildNumber());
    csvLine.add(String.valueOf(Version.buildNumber()));

    int exitCode = 0;
    Node node = null;
    Node node2 = null;
    FileInputStream fis = null;
    File file = new File("many-single-blocks-test-"+uid + ".csv");
    long t1, t2;
   
    try {
     
      // INSERT STUFF
     
      final File dir = new File("longterm-mhk-test-" + uid);
      FileUtil.removeAll(dir);
      RandomSource random = NodeStarter.globalTestInit(dir.getPath(), false, LogLevel.ERROR, "", false);
      File seednodes = new File("seednodes.fref");
      if (!seednodes.exists() || seednodes.length() == 0 || !seednodes.canRead()) {
        System.err.println("Unable to read seednodes.fref, it doesn't exist, or is empty");
        System.exit(EXIT_NO_SEEDNODES);
      }

      final File innerDir = new File(dir, Integer.toString(DARKNET_PORT1));
      innerDir.mkdir();
      fis = new FileInputStream(seednodes);
      FileUtil.writeTo(fis, new File(innerDir, "seednodes.fref"));
      fis.close();

      // Create one node
      node = NodeStarter.createTestNode(DARKNET_PORT1, OPENNET_PORT1, dir.getPath(), false, Node.DEFAULT_MAX_HTL,
              0, random, new PooledExecutor(), 1000, 4 * 1024 * 1024, true, true, true, true, true, true, true,
              12 * 1024, true, true, false, false, null);
      Logger.getChain().setThreshold(LogLevel.ERROR);

      // Start it
      node.start(true);
      t1 = System.currentTimeMillis();
      if (!TestUtil.waitForNodes(node)) {
        exitCode = EXIT_FAILED_TARGET;
        return;
      }
       
      t2 = System.currentTimeMillis();
      System.out.println("SEED-TIME:" + (t2 - t1));
      csvLine.add(String.valueOf(t2 - t1));

      HighLevelSimpleClient client = node.clientCore.makeClient((short) 0, false, false);

      int successes = 0;
     
      long startInsertsTime = System.currentTimeMillis();
     
      InsertBatch batch = new InsertBatch(client);
     
      // Inserts are sloooooow so do them in parallel.
     
      for(int i=0;i<INSERTED_BLOCKS;i++) {
       
        System.err.println("Inserting block "+i);
       
        RandomAccessBucket single = randomData(node);
       
        InsertBlock block = new InsertBlock(single, new ClientMetadata(), FreenetURI.EMPTY_CHK_URI);
       
        batch.startInsert(block);
       
      }
     
      batch.waitUntilFinished();
      FreenetURI[] uris = batch.getURIs();
      long[] times = batch.getTimes();
      InsertException[] errors = batch.getErrors();
     
      for(int i=0;i<INSERTED_BLOCKS;i++) {
        if(uris[i] != null) {
          csvLine.add(String.valueOf(times[i]));
          csvLine.add(uris[i].toASCIIString());
          System.out.println("Pushed block "+i+" : "+uris[i]+" in "+times[i]);
          successes++;
        } else {
          csvLine.add(InsertException.getShortMessage(errors[i].getMode()));
          csvLine.add("N/A");
          System.out.println("Failed to push block "+i+" : "+errors[i]);
        }
      }
     
      long endInsertsTime = System.currentTimeMillis();
     
      System.err.println("Succeeded inserts: "+successes+" of "+INSERTED_BLOCKS+" in "+(endInsertsTime-startInsertsTime)+"ms");
     
      FetchContext fctx = client.getFetchContext();
      fctx.maxNonSplitfileRetries = 0;
      fctx.maxSplitfileBlockRetries = 0;
      RequestClient requestContext = new RequestClient() {

        @Override
        public boolean persistent() {
          return false;
        }

        @Override
        public boolean realTimeFlag() {
          return false;
        }
       
      };
     
      // PARSE FILE AND FETCH OLD STUFF IF APPROPRIATE
     
      FreenetURI[] mhkURIs = new FreenetURI[3];
      fis = new FileInputStream(file);
      BufferedReader br = new BufferedReader(new InputStreamReader(fis, ENCODING));
      String line = null;
      GregorianCalendar target = (GregorianCalendar) today.clone();
      target.set(Calendar.HOUR_OF_DAY, 0);
      target.set(Calendar.MINUTE, 0);
      target.set(Calendar.MILLISECOND, 0);
      target.set(Calendar.SECOND, 0);
      GregorianCalendar[] targets = new GregorianCalendar[MAX_N+1];
      for(int i=0;i<targets.length;i++) {
        targets[i] = ((GregorianCalendar)target.clone());
        targets[i].add(Calendar.DAY_OF_MONTH, -((1<<i)-1));
        targets[i].getTime();
      }
      int[] totalFetchesByDelta = new int[MAX_N+1];
      int[] totalSuccessfulFetchesByDelta = new int[MAX_N+1];
      long[] totalFetchTimeByDelta = new long[MAX_N+1];
     
loopOverLines:
      while((line = br.readLine()) != null) {
       
        for(int i=0;i<mhkURIs.length;i++) mhkURIs[i] = null;
        //System.out.println("LINE: "+line);
        String[] split = line.split("!");
        Date date = dateFormat.parse(split[0]);
        GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
        calendar.setTime(date);
        System.out.println("Date: "+dateFormat.format(calendar.getTime()));
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.getTime();
        FreenetURI[] insertedURIs = new FreenetURI[INSERTED_BLOCKS];
        int[] insertTimes = new int[INSERTED_BLOCKS];
        if(split.length < 3) continue;
        int seedTime = Integer.parseInt(split[2]);
        System.out.println("Seed time: "+seedTime);
        if(split.length < 4) continue;
       
        int token = 3;
       
        if(split.length < token + INSERTED_BLOCKS * 2) continue;
     
        for(int i=0;i<INSERTED_BLOCKS;i++) {
          try {
            insertTimes[i] = Integer.parseInt(split[token]);
          } catch (NumberFormatException e) {
            insertTimes[i] = -1;
          }
          token++;
          try {
            insertedURIs[i] = new FreenetURI(split[token]);
          } catch (MalformedURLException e) {
            insertedURIs[i] = null;
          }
          token++;
          System.out.println("Key insert "+i+" : "+insertedURIs[i]+" in "+insertTimes[i]);
        }
        for(int i=0;i<targets.length;i++) {
          if(Math.abs(targets[i].getTimeInMillis() - calendar.getTimeInMillis()) < HOURS.toMillis(12)) {
            System.out.println("Found row for target date "+((1<<i)-1)+" days ago.");
            System.out.println("Version: "+split[1]);
            csvLine.add(Integer.toString(i));
            int pulled = 0;
            int inserted = 0;
            for(int j=0;j<INSERTED_BLOCKS;j++) {
              if(insertedURIs[j] == null) {
                csvLine.add("INSERT FAILED");
                continue;
              }
              inserted++;
              try {
                t1 = System.currentTimeMillis();
                FetchWaiter fw = new FetchWaiter(requestContext);
                client.fetch(insertedURIs[j], 32768, fw, fctx);
                fw.waitForCompletion();
                t2 = System.currentTimeMillis();
               
                System.out.println("PULL-TIME FOR BLOCK "+j+": " + (t2 - t1));
                csvLine.add(String.valueOf(t2 - t1));
                pulled++;
              } catch (FetchException e) {
                if (e.getMode() != FetchExceptionMode.ALL_DATA_NOT_FOUND
                    && e.getMode() != FetchExceptionMode.DATA_NOT_FOUND)
                  e.printStackTrace();
                csvLine.add(FetchException.getShortMessage(e.getMode()));
                System.err.println("FAILED PULL FOR BLOCK "+j+": "+e);
              }
            }
            System.out.println("Pulled "+pulled+" blocks of "+inserted+" from "+((1<<i)-1)+" days ago.");
          }
        }
       
        while(split.length > token + INSERTED_BLOCKS) {
          int delta;
          try {
            delta = Integer.parseInt(split[token]);
          } catch (NumberFormatException e) {
            System.err.println("Unable to parse token "+token+" = \""+token+"\"");
            System.err.println("This is supposed to be a delta");
            System.err.println("Skipping the rest of the line for date "+dateFormat.format(calendar.getTime()));
            continue loopOverLines;
          }
          System.out.println("Delta: "+((1<<delta)-1)+" days");
          token++;
          int totalFetchTime = 0;
          int totalSuccesses = 0;
          int totalFetches = 0;
          for(int i=0;i<INSERTED_BLOCKS;i++) {
            if(split[token].equals(""))
              continue;
            int mhkFetchTime = -1;
            totalFetches++;
            try {
              mhkFetchTime = Integer.parseInt(split[token]);
              System.out.println("Fetched block #"+i+" on "+date+" in "+mhkFetchTime+"ms");
              totalSuccesses++;
              totalFetchTime += mhkFetchTime;
            } catch (NumberFormatException e) {
              System.out.println("Failed block #"+i+" on "+date+" : "+split[token]);
            }
            token++;
          }
          totalFetchesByDelta[delta] += totalFetches;
          totalSuccessfulFetchesByDelta[delta] += totalSuccesses;
          totalFetchTimeByDelta[delta] += totalFetchTime;
          System.err.println("Succeeded: "+totalSuccesses+" of "+totalFetches+" average "+((double)totalFetchTime)/((double)totalSuccesses)+"ms for delta "+delta+" on "+dateFormat.format(date));
        }
      }
     
      System.out.println();
      System.out.println();
     
      for(int i=0;i<MAX_N+1;i++) {
        System.out.println("DELTA: "+i+" days: Total fetches: "+totalFetchesByDelta[i]+" total successes "+totalSuccessfulFetchesByDelta[i]+" = "+((totalSuccessfulFetchesByDelta[i]*100.0)/totalFetchesByDelta[i])+"% in "+(totalFetchTimeByDelta[i]*1.0)/totalSuccessfulFetchesByDelta[i]+"ms");
      }
     
      fis.close();
      fis = null;
     
    } catch (Throwable t) {
      t.printStackTrace();
      exitCode = EXIT_THREW_SOMETHING;
    } finally {
      try {
        if (node != null)
          node.park();
      } catch (Throwable tt) {
      }
      try {
        if (node2 != null)
          node2.park();
      } catch (Throwable tt) {
      }
      Closer.close(fis);
      writeToStatusLog(file, csvLine);

      System.out.println("Exiting with status "+exitCode);
      System.exit(exitCode);
    }
  } 
 
  private static RandomAccessBucket randomData(Node node) throws IOException {
      RandomAccessBucket data = node.clientCore.tempBucketFactory.makeBucket(TEST_SIZE);
    OutputStream os = data.getOutputStream();
    try {
    byte[] buf = new byte[4096];
    for (long written = 0; written < TEST_SIZE;) {
      node.fastWeakRandom.nextBytes(buf);
      int toWrite = (int) Math.min(TEST_SIZE - written, buf.length);
      os.write(buf, 0, toWrite);
      written += toWrite;
    }
    } finally {
    os.close();
    }
    return data;
  }

}
TOP

Related Classes of freenet.node.simulator.LongTermManySingleBlocksTest$InsertBatch$BatchInsert

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.