package com.ricebridge.xmlman.test;
import com.ricebridge.xmlman.*;
import com.ricebridge.xmlman.in.*;
import com.ricebridge.xmlman.in.test.*;
import com.ricebridge.xmlman.log.*;
import org.jostraca.util.*;
import junit.framework.*;
import junit.textui.*;
import org.xml.sax.InputSource;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
import java.util.*;
import java.io.*;
import java.sql.*;
public class ThreadTest extends TestCase {
public ThreadTest( String pName ) {
super( pName );
}
public static TestSuite suite() {
return new TestSuite( ThreadTest.class );
}
public static void main( String[] pArgs ) {
TestRunner.run( suite() );
}
static RecordSpec rs = new RecordSpec( "/t/e", new String[] {"@n","text()","a"} );
static String loadfileprefix = "/tmp/xmlman/t";
static String savefileprefix = "/tmp/xmlman/st";
static String filesuffix = ".xml";
static volatile int filehandles = 0;
public interface Operation {
public boolean perform( XmlManager pXmlManager, int pIndex, int pCycle ) throws Exception;
}
public static class NormalStringListLoad implements Operation {
public boolean perform( XmlManager pXmlManager, int pIndex, int pCycle ) {
List data = pXmlManager.load( new File( loadfileprefix+pIndex+filesuffix) );
ThreadTest.checkLoadStringList( pIndex, data );
assertEquals( pIndex, pXmlManager.getStats().getTotalRecords() );
return true;
}
}
public static class BackgroundStringListLoad implements Operation {
public boolean perform( XmlManager pXmlManager, int pIndex, int pCycle ) {
List data = pXmlManager.load( new File( loadfileprefix+pIndex+filesuffix) );
assertEquals( 0, data.size() );
while( !pXmlManager.isLoadFinished() ) {
try { Thread.sleep(10); } catch( Exception e ) {}
}
ThreadTest.checkLoadStringList( pIndex, data );
assertEquals( pIndex, pXmlManager.getStats().getTotalRecords() );
return true;
}
}
public static class NormalStringListSave implements Operation {
public boolean perform( XmlManager pXmlManager, int pIndex, int pCycle ) throws Exception {
File file = new File( savefileprefix+pCycle+"-"+pIndex+filesuffix);
writeFile( file, "" );
pXmlManager.getXmlSpec().setIndent(false);
try {
filehandles++;
pXmlManager.save( file, ThreadTest.makeStringListData(pIndex) );
}
finally {
filehandles--;
}
ThreadTest.checkSaveStringList( pIndex, file );
assertEquals( pIndex, pXmlManager.getStats().getTotalRecords() );
return true;
}
}
public static class BackgroundStringListSave implements Operation {
public boolean perform( XmlManager pXmlManager, int pIndex, int pCycle ) throws Exception {
File file = new File( savefileprefix+pCycle+"-"+pIndex+filesuffix);
writeFile( file, "" );
pXmlManager.getXmlSpec().setIndent(false);
try {
filehandles++;
pXmlManager.save( file, ThreadTest.makeStringListData(pIndex) );
assertEquals( "", readFile( file ) );
while( !pXmlManager.isSaveFinished() ) {
try { Thread.sleep(10); } catch( Exception e ) {}
}
}
finally {
filehandles--;
}
ThreadTest.checkSaveStringList( pIndex, file );
assertEquals( pIndex, pXmlManager.getStats().getTotalRecords() );
return true;
}
}
public static void makeThreadLoadFiles() throws Exception {
new File("/tmp/xmlman").mkdir();
for( int f = 0; f < 100; f++ ) {
FileOutputStream fos = new FileOutputStream("/tmp/xmlman/t"+f+".xml");
PrintWriter pw = new PrintWriter(fos);
pw.println("<?xml version='1.0'?><t>");
for( int i = 0; i < f; i++ ) {
pw.println("<e n=\""+f+"-"+i+"\">"+f+"-"+i+"t<a>"+f+"-"+i+"a</a></e>");
}
pw.println("</t>");
pw.close();
}
}
public void xtestNormalLoad() throws Exception {
XmlManager xmlManager = new XmlManager(rs);
Operation op = new NormalStringListLoad();
runTest( 1000, 100, xmlManager, ListUtil.make(op));
}
public void xtestBackgroundLoad() throws Exception {
XmlManager xmlManager = new XmlManager(rs);
xmlManager.getXmlSpec().setBackground( true );
xmlManager.getXmlSpec().setProperty("test.delay",""+20);
xmlManager.getXmlManagerStore().setStringArrayRecordListenerClass( BackgroundTest.DelayedStringArrayRecordListener.class );
Operation op = new BackgroundStringListLoad();
runTest( 1000, 100, xmlManager, ListUtil.make(op));
}
public void xtestNormalSave() throws Exception {
XmlManager xmlManager = new XmlManager(rs);
Operation op = new NormalStringListSave();
runTest( 1000, 100, xmlManager, ListUtil.make(op));
}
public void testBackgroundSave() throws Exception {
XmlManager xmlManager = new XmlManager(rs);
xmlManager.getXmlSpec().setBackground( true );
xmlManager.getXmlSpec().setProperty("test.delay",""+1000);
xmlManager.getXmlManagerStore().setStringArrayRecordProviderClass( BackgroundTest.DelayedStringArrayRecordProvider.class );
Operation op = new BackgroundStringListSave();
runTest( 1000, 100, xmlManager, ListUtil.make(op));
}
public void runTest( int pCycles, int pFiles, XmlManager pXmlManager, List pOperations ) throws Exception {
final XmlManager xmlManager = pXmlManager;
final List ops = pOperations;
final int numops = ops.size();
boolean checkFreeMem = true;
boolean checkThreads = true;
boolean checkFileHandles = true;
try {
for( int t = 0; t < pCycles; t++ ) {
System.out.println( t+","+getNumThreads()+","+handleMemory( checkFreeMem ) );
for( int f = 0; f < pFiles; f++ ) {
handleThreads( checkThreads );
handleMemory( checkFreeMem );
handleFileHandles( checkFileHandles );
final int tt = t;
final int ff = f;
Runnable r = new Runnable() {
public void run() {
boolean done = false;
Operation op = (Operation) ops.get(ff%numops);
while( !done ) {
try {
done = op.perform( xmlManager, ff, tt );
}
catch( Exception de ) {
de.printStackTrace();
System.out.println( op+":"+de );
try { Thread.sleep(500); } catch( Exception e ) {}
}
}
}
};
boolean start = false;
while( !start ) {
try {
new Thread(r).start();
start = true;
}
catch( OutOfMemoryError oome ) {
System.out.println( oome );
System.gc();
try { Thread.sleep(500); } catch( Exception e ) {}
}
}
}
}
}
catch( Throwable t ) {
System.out.println( "THREADS:"+getNumThreads() );
t.printStackTrace();
}
}
private int getNumThreads() {
Thread t = Thread.currentThread();
ThreadGroup tg = t.getThreadGroup();
ThreadGroup ptg = null;
while( null != (ptg = tg.getParent()) ) { tg = ptg; }
return tg.activeCount();
}
private int handleThreads( boolean pCheckThreads ) {
int numt = getNumThreads();
while( pCheckThreads && numt > 6000 ) {
System.out.println( "WAITING FOR THREADS:"+numt );
try { Thread.sleep(100); } catch( Exception e ) {}
numt = getNumThreads();
}
return numt;
}
private long handleMemory( boolean pCheckFreeMem ) {
Runtime r = Runtime.getRuntime();
long fm = r.freeMemory();
while( pCheckFreeMem && fm < 1024*100 ) {
try {
System.out.println( "WAITING FOR MEM:"+fm );
System.gc();
Thread.sleep(500);
fm = r.freeMemory();
} catch( Exception e ) {}
}
return r.totalMemory()-r.freeMemory();
}
private int handleFileHandles( boolean pCheckFileHandles ) {
int fh = filehandles;
while( pCheckFileHandles && fh > 128 ) {
System.out.println( "WAITING FOR FILES:"+fh );
try { Thread.sleep(100); } catch( Exception e ) {}
fh = filehandles;
}
return fh;
}
public static void checkLoadStringList( int pFileIndex, List pData ) {
assertEquals( pFileIndex, pData.size() );
String prefix = pFileIndex+"";
for( int rI = 0; rI < pData.size(); rI++ ) {
String[] r = (String[]) pData.get(rI);
assertTrue( r[0].equals(prefix+"-"+rI) );
assertTrue( r[1].equals(prefix+"-"+rI+"t") );
assertTrue( r[2].equals(prefix+"-"+rI+"a") );
}
}
public static void checkSaveStringList( int pFileIndex, File pFile ) throws Exception {
StringBuffer sb = new StringBuffer("<t>");
for( int rI = 0; rI < pFileIndex; rI++ ) {
sb.append("<e n=\""+pFileIndex+"-"+rI+"\">"+pFileIndex+"-"+rI+"t<a>"+pFileIndex+"-"+rI+"a</a></e>");
}
sb.append("</t>");
assertEquals( sb.toString(), readFile( pFile) );
}
public static List makeStringListData( int pFileIndex ) {
ArrayList data = new ArrayList( pFileIndex );
for( int rI = 0; rI < pFileIndex; rI++ ) {
data.add( new String[] {pFileIndex+"-"+rI, pFileIndex+"-"+rI+"t", pFileIndex+"-"+rI+"a"} );
}
return data;
}
public static void writeFile( File pFile, String pContent ) throws Exception {
filehandles++;
FileOutputStream fos = null;
PrintWriter pw = null;
try {
fos = new FileOutputStream( pFile );
pw = new PrintWriter( fos );
pw.print( pContent );
}
catch( Exception e ) {
throw new Exception( pFile.getAbsolutePath(), e );
}
finally {
pw.close();
fos.close();
filehandles--;
}
}
public static String readFile( File pFile ) throws Exception {
filehandles++;
FileReader fr = null;
BufferedReader br = null;
try {
fr = new FileReader( pFile );
br = new BufferedReader( fr );
StringBuffer content = new StringBuffer();
String line = null;
while( null != (line = br.readLine() ) ) {
content.append(line);
}
return content.toString();
}
catch( Exception e ) {
throw new Exception( pFile.getAbsolutePath(), e );
}
finally {
br.close();
fr.close();
filehandles--;
}
}
}