jpayne@68: package fileIO; jpayne@68: import java.io.InputStream; jpayne@68: import java.util.Arrays; jpayne@68: import java.util.concurrent.ArrayBlockingQueue; jpayne@68: jpayne@68: import shared.Timer; jpayne@68: import shared.Tools; jpayne@68: jpayne@68: jpayne@68: /** jpayne@68: * Runs a ByteFile1 in a separate thread. Can speed up disk reading, particularly of compressed files, at cost of slightly more work done. jpayne@68: * Drop-in compatible with ByteFile1. jpayne@68: * @author Brian Bushnell jpayne@68: * @date Sep 23, 2013 jpayne@68: * jpayne@68: */ jpayne@68: public final class ByteFile2 extends ByteFile { jpayne@68: jpayne@68: jpayne@68: public static void main(String[] args){ jpayne@68: ByteFile2 tf=new ByteFile2(args.length>0 ? args[0] : "stdin", true); jpayne@68: long first=0, last=100; jpayne@68: boolean speedtest=false; jpayne@68: if(args.length>1){ jpayne@68: if(args[1].equalsIgnoreCase("speedtest")){ jpayne@68: speedtest=true; jpayne@68: first=0; jpayne@68: last=Long.MAX_VALUE; jpayne@68: }else{ jpayne@68: first=Integer.parseInt(args[1]); jpayne@68: last=first+100; jpayne@68: } jpayne@68: } jpayne@68: if(args.length>2){ jpayne@68: last=Integer.parseInt(args[2]); jpayne@68: } jpayne@68: speedtest(tf, first, last, !speedtest); jpayne@68: jpayne@68: tf.close(); jpayne@68: tf.reset(); jpayne@68: tf.close(); jpayne@68: } jpayne@68: jpayne@68: private static void speedtest(ByteFile2 tf, long first, long last, boolean reprint){ jpayne@68: Timer t=new Timer(); jpayne@68: long lines=0; jpayne@68: long bytes=0; jpayne@68: for(long i=0; i=temp.length || temp[tempLoc]==null){ jpayne@68: boolean b=getBuffer(); jpayne@68: if(!b){ jpayne@68: if(verbose2){System.err.println("nextLine()->getBuffer() returned false.");} jpayne@68: return null; jpayne@68: } jpayne@68: temp=currentList; jpayne@68: tempLoc=currentLoc; jpayne@68: if(temp==null || temp==poison || temp[tempLoc]==null){ jpayne@68: return null; jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: //TODO: This is a race condition; currentList can be changed to null. A defensive copy could be created. jpayne@68: //Note that I read the above warning and added "temp" and "temploc" but I'm not sure if that fixed anything. jpayne@68: assert(temp!=null && temp!=poison); jpayne@68: assert(tempLoc(buffs+2); jpayne@68: // qEmpty=new ArrayBlockingQueue(buffs+2); jpayne@68: // for(int i=0; i(buffs+2); jpayne@68: qEmpty=new ArrayBlockingQueue(buffs+2); jpayne@68: for(int i=0; i=bufflen || bases>=buffcapacity){ jpayne@68: if(verbose2){System.err.println("Capacity exceeded.");} jpayne@68: while(list!=null){ jpayne@68: try { jpayne@68: // synchronized(this){ jpayne@68: // if(!shutdown){ jpayne@68: if(verbose2){ jpayne@68: System.err.println("A: Adding to qFull list of size "+loc); jpayne@68: System.err.println(ByteFile2.toString(list)); jpayne@68: } jpayne@68: cntr+=list.length; jpayne@68: qFull.put(list); jpayne@68: if(verbose2){System.err.println("A: qFull.size()="+qFull.size());} jpayne@68: // } jpayne@68: // } jpayne@68: list=null; jpayne@68: loc=0; jpayne@68: } catch (InterruptedException e) { jpayne@68: // TODO Auto-generated catch block jpayne@68: e.printStackTrace(); jpayne@68: } jpayne@68: } jpayne@68: //At this point, list is null jpayne@68: if(shutdown){ jpayne@68: if(verbose2){System.err.println("Break 1");} jpayne@68: break; jpayne@68: } jpayne@68: while(list==null){ jpayne@68: if(verbose2){System.err.println("Taking empty list.");} jpayne@68: try { jpayne@68: list = qEmpty.take(); jpayne@68: } catch (InterruptedException e1) { jpayne@68: // TODO Auto-generated catch block jpayne@68: e1.printStackTrace(); jpayne@68: } jpayne@68: } jpayne@68: //At this point, list is not null jpayne@68: bases=0; jpayne@68: if(list==poison){ jpayne@68: if(verbose2){System.err.println("Break 2");} jpayne@68: break; jpayne@68: } jpayne@68: //At this point, list is not null jpayne@68: } jpayne@68: } jpayne@68: if(verbose2){System.err.println("Run loop exit.");} jpayne@68: jpayne@68: while(list!=null && loc>0){ jpayne@68: try { jpayne@68: // synchronized(this){ jpayne@68: // if(!shutdown){ jpayne@68: if(verbose2){System.err.println("B: Adding list of size "+loc);} jpayne@68: qFull.put(list); jpayne@68: if(verbose2){System.err.println("B: qFull.size()="+qFull.size());} jpayne@68: // } jpayne@68: // } jpayne@68: list=null; jpayne@68: loc=0; jpayne@68: } catch (InterruptedException e) { jpayne@68: // TODO Auto-generated catch block jpayne@68: e.printStackTrace(); jpayne@68: } jpayne@68: } jpayne@68: //At this point, list is null jpayne@68: shutdown(); jpayne@68: jpayne@68: if(verbose){System.err.println("ByteFile2("+name()+").run() finished");} jpayne@68: } jpayne@68: jpayne@68: synchronized void shutdown(){ jpayne@68: if(verbose || verbose2){System.err.println("ByteFile2("+name()+").shutdown()");} jpayne@68: if(shutdown){return;} jpayne@68: shutdown=true; jpayne@68: if(verbose2){System.err.println("Adding poison.");} jpayne@68: qFull.add(poison); jpayne@68: qEmpty.add(poison); jpayne@68: if(verbose2){System.err.println("D: qFull.size()="+qFull.size());} jpayne@68: if(verbose || verbose2){System.err.println("ByteFile2("+name()+").shutdown() finished");} jpayne@68: } jpayne@68: jpayne@68: private boolean shutdown=false; jpayne@68: final ByteFile1 bf1; jpayne@68: final ArrayBlockingQueue qFull; jpayne@68: final ArrayBlockingQueue qEmpty; jpayne@68: jpayne@68: } jpayne@68: jpayne@68: @Override jpayne@68: public boolean isOpen(){ jpayne@68: final byte[][] list=currentList; jpayne@68: final int loc=currentLoc; jpayne@68: if(list!=null && locline.length){ jpayne@68: // bstart--; jpayne@68: // buffer[bstart]='\n'; jpayne@68: // for(int i=0, j=bstart-line.length; i0) : bstop+", "+bstart+", "+line.length; jpayne@68: // while(newLen>buffer.length){ jpayne@68: // //This could get big if pushback is used often, jpayne@68: // //unless special steps are taken to prevent it, like leaving extra space for pushbacks. jpayne@68: // buffer=Arrays.copyOf(buffer, buffer.length*2); jpayne@68: // } jpayne@68: // jpayne@68: // Tools.shiftRight(buffer, rShift); jpayne@68: // jpayne@68: // for(int i=0; i