Merge branch 'feature/factor_out_groovy' into develop

This commit is contained in:
Eyck Jentzsch 2021-01-09 10:36:25 +01:00
commit 5ea0d6446a
48 changed files with 1113 additions and 840 deletions

View File

@ -31,6 +31,11 @@
<repository location="http://download.eclipse.org/nebula/releases/latest"/> <repository location="http://download.eclipse.org/nebula/releases/latest"/>
<unit id="org.eclipse.nebula.widgets.xviewer.feature.feature.group" version="1.1.0.202011020719"/> <unit id="org.eclipse.nebula.widgets.xviewer.feature.feature.group" version="1.1.0.202011020719"/>
</location> </location>
<location includeAllPlatforms="false" includeConfigurePhase="true" includeMode="planner" includeSource="true" type="InstallableUnit">
<repository location="http://download.eclipse.org/collections/10.4.0/repository"/>
<unit id="org.eclipse.collections.feature.feature.group" version="0.0.0"/>
<unit id="org.eclipse.collections.feature.source.feature.group" version="0.0.0"/>
</location>
</locations> </locations>
<targetJRE path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> <targetJRE path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<launcherArgs> <launcherArgs>

View File

@ -58,12 +58,6 @@ http://www.eclipse.org/legal/epl-v10.html
version="0.0.0" version="0.0.0"
unpack="false"/> unpack="false"/>
<plugin
id="org.codehaus.groovy"
download-size="0"
install-size="0"
version="0.0.0"/>
<plugin <plugin
id="com.minres.scviewer.database.vcd" id="com.minres.scviewer.database.vcd"
download-size="0" download-size="0"

View File

@ -8,5 +8,4 @@
<version>2.0.0-SNAPSHOT</version> <version>2.0.0-SNAPSHOT</version>
<relativePath>../..</relativePath> <relativePath>../..</relativePath>
</parent> </parent>
<version>2.0.0-SNAPSHOT</version>
</project> </project>

View File

@ -38,8 +38,6 @@ public class SQLiteDbLoader implements IWaveformDbLoader {
private List<RelationType> usedRelationsList = new ArrayList<>(); private List<RelationType> usedRelationsList = new ArrayList<>();
private IWaveformDb db;
private ScvSimProps scvSimProps; private ScvSimProps scvSimProps;
@Override @Override
@ -63,7 +61,7 @@ public class SQLiteDbLoader implements IWaveformDbLoader {
List<IWaveform> streams=new ArrayList<>(); List<IWaveform> streams=new ArrayList<>();
try { try {
for(ScvStream scvStream:handler.selectObjects()){ for(ScvStream scvStream:handler.selectObjects()){
TxStream stream = new TxStream(database, db, scvStream); TxStream stream = new TxStream(database, scvStream);
stream.setRelationTypeList(usedRelationsList); stream.setRelationTypeList(usedRelationsList);
streams.add(stream); streams.add(stream);
} }
@ -77,8 +75,8 @@ public class SQLiteDbLoader implements IWaveformDbLoader {
@Override @Override
public boolean load(IWaveformDb db, File file) throws InputFormatException { public boolean load(IWaveformDb db, File file) throws InputFormatException {
dispose();
if(file.isDirectory() || !file.exists()) return false; if(file.isDirectory() || !file.exists()) return false;
this.db=db;
try(FileInputStream fis = new FileInputStream(file)) { try(FileInputStream fis = new FileInputStream(file)) {
byte[] buffer = new byte[x.length]; byte[] buffer = new byte[x.length];
int read = fis.read(buffer, 0, x.length); int read = fis.read(buffer, 0, x.length);
@ -88,7 +86,7 @@ public class SQLiteDbLoader implements IWaveformDbLoader {
} catch(IOException e) { } catch(IOException e) {
return false; return false;
} }
database=new SQLiteDatabase(file.getAbsolutePath()); database=new SQLiteDatabase(file.getAbsolutePath(), db);
database.setData("TIMERESOLUTION", 1L); database.setData("TIMERESOLUTION", 1L);
SQLiteDatabaseSelectHandler<ScvSimProps> handler = new SQLiteDatabaseSelectHandler<>(ScvSimProps.class, database); SQLiteDatabaseSelectHandler<ScvSimProps> handler = new SQLiteDatabaseSelectHandler<>(ScvSimProps.class, database);
try { try {
@ -104,6 +102,11 @@ public class SQLiteDbLoader implements IWaveformDbLoader {
return false; return false;
} }
public void dispose() {
database=null;
usedRelationsList=null;
}
@Override @Override
public Collection<RelationType> getAllRelationTypes(){ public Collection<RelationType> getAllRelationTypes(){
return usedRelationsList; return usedRelationsList;

View File

@ -164,7 +164,7 @@ public class Tx implements ITx {
List<ScvStream> streams = new SQLiteDatabaseSelectHandler<ScvStream>(ScvStream.class, database, List<ScvStream> streams = new SQLiteDatabaseSelectHandler<ScvStream>(ScvStream.class, database,
"id="+res.get(0).getStream()).selectObjects(); "id="+res.get(0).getStream()).selectObjects();
if(streams.size()!=1) return null; if(streams.size()!=1) return null;
TxStream tgtStream = (TxStream) trStream.getDb().getStreamByName(streams.get(0).getName()); TxStream tgtStream = (TxStream) database.getWaveformDb().getStreamByName(streams.get(0).getName());
Tx that = (Tx) tgtStream.getTransactions().get(otherId); Tx that = (Tx) tgtStream.getTransactions().get(otherId);
if(outgoing) if(outgoing)
return new TxRelation(trStream.getRelationType(rel.getName()), this, that); return new TxRelation(trStream.getRelationType(rel.getName()), this, that);

View File

@ -10,12 +10,8 @@
*******************************************************************************/ *******************************************************************************/
package com.minres.scviewer.database.sqlite; package com.minres.scviewer.database.sqlite;
import java.util.ArrayList;
import java.util.List;
import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.sqlite.tables.ScvGenerator; import com.minres.scviewer.database.sqlite.tables.ScvGenerator;
import com.minres.scviewer.database.tx.ITx;
import com.minres.scviewer.database.tx.ITxGenerator; import com.minres.scviewer.database.tx.ITxGenerator;
public class TxGenerator implements ITxGenerator { public class TxGenerator implements ITxGenerator {
@ -44,9 +40,4 @@ public class TxGenerator implements ITxGenerator {
return scvGenerator.getName(); return scvGenerator.getName();
} }
@Override
public List<ITx> getTransactions() {
return new ArrayList<>();
}
} }

View File

@ -24,8 +24,8 @@ import com.minres.scviewer.database.EventKind;
import com.minres.scviewer.database.HierNode; import com.minres.scviewer.database.HierNode;
import com.minres.scviewer.database.IEvent; import com.minres.scviewer.database.IEvent;
import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.IWaveformDb;
import com.minres.scviewer.database.RelationType; import com.minres.scviewer.database.RelationType;
import com.minres.scviewer.database.RelationTypeFactory;
import com.minres.scviewer.database.WaveformType; import com.minres.scviewer.database.WaveformType;
import com.minres.scviewer.database.sqlite.db.IDatabase; import com.minres.scviewer.database.sqlite.db.IDatabase;
import com.minres.scviewer.database.sqlite.db.SQLiteDatabaseSelectHandler; import com.minres.scviewer.database.sqlite.db.SQLiteDatabaseSelectHandler;
@ -41,8 +41,6 @@ public class TxStream extends HierNode implements IWaveform {
private String fullName; private String fullName;
private IWaveformDb db;
private ScvStream scvStream; private ScvStream scvStream;
private TreeMap<Integer, TxGenerator> generators; private TreeMap<Integer, TxGenerator> generators;
@ -55,17 +53,11 @@ public class TxStream extends HierNode implements IWaveform {
private List<RelationType> usedRelationsList; private List<RelationType> usedRelationsList;
public TxStream(IDatabase database, IWaveformDb waveformDb, ScvStream scvStream) { public TxStream(IDatabase database, ScvStream scvStream) {
super(scvStream.getName()); super(scvStream.getName());
this.database=database; this.database=database;
fullName=scvStream.getName(); fullName=scvStream.getName();
this.scvStream=scvStream; this.scvStream=scvStream;
db=waveformDb;
}
@Override
public IWaveformDb getDb() {
return db;
} }
@Override @Override
@ -173,7 +165,7 @@ public class TxStream extends HierNode implements IWaveform {
} }
public RelationType getRelationType(String name) { public RelationType getRelationType(String name) {
RelationType relType=RelationType.create(name); RelationType relType=RelationTypeFactory.create(name);
if(!usedRelationsList.contains(relType)) usedRelationsList.add(relType); if(!usedRelationsList.contains(relType)) usedRelationsList.add(relType);
return relType; return relType;
} }

View File

@ -16,6 +16,8 @@ import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import com.minres.scviewer.database.IWaveformDb;
/** /**
* *
* Creates a connection to a database. * Creates a connection to a database.
@ -58,4 +60,6 @@ public interface IDatabase {
public void setData(String name, Object value); public void setData(String name, Object value);
public Object getData(String name); public Object getData(String name);
public IWaveformDb getWaveformDb();
} }

View File

@ -20,10 +20,14 @@ import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.util.HashMap; import java.util.HashMap;
import com.minres.scviewer.database.IWaveformDb;
public class SQLiteDatabase implements IDatabase { public class SQLiteDatabase implements IDatabase {
protected String dbFileName; protected String dbFileName;
protected IWaveformDb waveformDb;
protected HashMap<String, Object> props; protected HashMap<String, Object> props;
static { static {
@ -39,9 +43,10 @@ public class SQLiteDatabase implements IDatabase {
} }
} }
public SQLiteDatabase(String dbFileName) { public SQLiteDatabase(String dbFileName, IWaveformDb waveformDb) {
super(); super();
this.dbFileName = dbFileName; this.dbFileName = dbFileName;
this.waveformDb = waveformDb;
props = new HashMap<String, Object>(); props = new HashMap<String, Object>();
} }
@ -89,4 +94,9 @@ public class SQLiteDatabase implements IDatabase {
return props.get(name); return props.get(name);
} }
@Override
public IWaveformDb getWaveformDb() {
return waveformDb;
}
} }

View File

@ -11,10 +11,7 @@
<attribute name="javadoc_location" value="jar:platform:/resource/com.minres.scviewer.database.text/lib/mapdb-3.0.7-javadoc.jar!/"/> <attribute name="javadoc_location" value="jar:platform:/resource/com.minres.scviewer.database.text/lib/mapdb-3.0.7-javadoc.jar!/"/>
</attributes> </attributes>
</classpathentry> </classpathentry>
<classpathentry kind="src" path="src/"/> <classpathentry kind="src" path="src"/>
<classpathentry exported="true" kind="lib" path="lib/eclipse-collections-9.2.0.jar"/>
<classpathentry exported="true" kind="lib" path="lib/eclipse-collections-api-9.2.0.jar"/>
<classpathentry exported="true" kind="lib" path="lib/eclipse-collections-forkjoin-9.2.0.jar"/>
<classpathentry exported="true" kind="lib" path="lib/kotlin-stdlib-1.2.42.jar"/> <classpathentry exported="true" kind="lib" path="lib/kotlin-stdlib-1.2.42.jar"/>
<classpathentry exported="true" kind="lib" path="lib/lz4-1.3.0.jar"/> <classpathentry exported="true" kind="lib" path="lib/lz4-1.3.0.jar"/>
<classpathentry exported="true" kind="lib" path="lib/elsa-3.0.0-M5.jar"/> <classpathentry exported="true" kind="lib" path="lib/elsa-3.0.0-M5.jar"/>

View File

@ -33,7 +33,6 @@
</buildSpec> </buildSpec>
<natures> <natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature> <nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.groovy.core.groovyNature</nature>
<nature>org.eclipse.pde.PluginNature</nature> <nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature> <nature>org.eclipse.jdt.core.javanature</nature>
</natures> </natures>

View File

@ -7,17 +7,14 @@ Bundle-Vendor: MINRES Technologies GmbH
Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: org.osgi.framework;version="1.3.0" Import-Package: org.osgi.framework;version="1.3.0"
Require-Bundle: com.minres.scviewer.database, Require-Bundle: com.minres.scviewer.database,
org.codehaus.groovy;bundle-version="2.5.8",
org.eclipse.osgi.services;bundle-version="3.4.0", org.eclipse.osgi.services;bundle-version="3.4.0",
com.google.guava;bundle-version="15.0.0" com.google.guava;bundle-version="15.0.0",
org.eclipse.collections;bundle-version="10.4.0"
Service-Component: OSGI-INF/component.xml Service-Component: OSGI-INF/component.xml
Bundle-ActivationPolicy: lazy Bundle-ActivationPolicy: lazy
Automatic-Module-Name: com.minres.scviewer.database.text Automatic-Module-Name: com.minres.scviewer.database.text
Bundle-ClassPath: lib/mapdb-3.0.7.jar, Bundle-ClassPath: .,
., lib/mapdb-3.0.7.jar,
lib/eclipse-collections-9.2.0.jar,
lib/eclipse-collections-api-9.2.0.jar,
lib/eclipse-collections-forkjoin-9.2.0.jar,
lib/kotlin-stdlib-1.2.42.jar, lib/kotlin-stdlib-1.2.42.jar,
lib/lz4-1.3.0.jar, lib/lz4-1.3.0.jar,
lib/elsa-3.0.0-M5.jar lib/elsa-3.0.0-M5.jar

View File

@ -13,9 +13,6 @@ bin.includes = META-INF/,\
OSGI-INF/,\ OSGI-INF/,\
lib/,\ lib/,\
lib/mapdb-3.0.7.jar,\ lib/mapdb-3.0.7.jar,\
lib/eclipse-collections-9.2.0.jar,\
lib/eclipse-collections-api-9.2.0.jar,\
lib/eclipse-collections-forkjoin-9.2.0.jar,\
lib/kotlin-stdlib-1.2.42.jar,\ lib/kotlin-stdlib-1.2.42.jar,\
lib/lz4-1.3.0.jar,\ lib/lz4-1.3.0.jar,\
lib/elsa-3.0.0-M5.jar lib/elsa-3.0.0-M5.jar

View File

@ -0,0 +1,25 @@
package com.minres.scviewer.database.text;
import java.io.Serializable;
import com.minres.scviewer.database.RelationType;
class ScvRelation implements Serializable {
/**
*
*/
private static final long serialVersionUID = -347668857680574140L;
final long source;
final long target;
final RelationType relationType;
public ScvRelation(RelationType relationType, long source, long target) {
this.source = source;
this.target = target;
this.relationType = relationType;
}
}

View File

@ -0,0 +1,47 @@
/*******************************************************************************
* Copyright (c) 2012 IT Just working.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IT Just working - initial API and implementation
*******************************************************************************/
package com.minres.scviewer.database.text;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.minres.scviewer.database.tx.ITxAttribute;
class ScvTx implements Serializable{
/**
*
*/
private static final long serialVersionUID = -855200240003328221L;
final long id;
final long generatorId;
final long streamId;
long beginTime;
long endTime;
final List<ITxAttribute> attributes = new ArrayList<>();
ScvTx(long id, long streamId, long generatorId, long begin){
this.id=id;
this.streamId=streamId;
this.generatorId=generatorId;
this.beginTime=begin;
this.endTime=begin;
}
Long getId() {return id;}
}

View File

@ -1,245 +0,0 @@
/*******************************************************************************
* Copyright (c) 2012 IT Just working.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IT Just working - initial API and implementation
*******************************************************************************/
package com.minres.scviewer.database.text;
import java.nio.charset.CharsetDecoder;
import java.util.Collection;
import java.util.zip.GZIPInputStream
import org.codehaus.groovy.ast.stmt.CatchStatement
import org.mapdb.DB
import org.mapdb.DBMaker
import groovy.io.FileType
import com.minres.scviewer.database.AssociationType
import com.minres.scviewer.database.DataType
import com.minres.scviewer.database.IWaveform
import com.minres.scviewer.database.IWaveformDb
import com.minres.scviewer.database.IWaveformDbLoader
import com.minres.scviewer.database.InputFormatException
import com.minres.scviewer.database.RelationType
import com.minres.scviewer.database.tx.ITxGenerator
public class TextDbLoader implements IWaveformDbLoader{
private Long maxTime;
IWaveformDb db;
def streams = []
def relationTypes=[:]
DB mapDb
public TextDbLoader() {
}
@Override
public Long getMaxTime() {
return maxTime;
}
@Override
public Collection<IWaveform> getAllWaves() {
return streams;
}
public Map<Long, ITxGenerator> getGeneratorsById() {
TreeMap<Long, ITxGenerator> res = new TreeMap<Long, ITxGenerator>();
streams.each{TxStream stream -> stream.generators.each{res.put(it.id, id)} }
return res;
}
static final byte[] x = "scv_tr_stream".bytes
@Override
boolean load(IWaveformDb db, File file) throws InputFormatException {
if(file.isDirectory() || !file.exists()) return false;
this.db=db
this.streams=[]
try {
def gzipped = isGzipped(file)
if(isTxfile(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file))){
def mapDbFile = File.createTempFile("."+file.name, null /*"tmp"*/, null /*file.parentFile*/)
mapDbFile.delete()
mapDbFile.deleteOnExit()
this.mapDb = DBMaker
.fileDB(mapDbFile)
.fileMmapEnableIfSupported()
.fileMmapPreclearDisable()
.cleanerHackEnable()
.allocateStartSize(64*1024*1024)
.allocateIncrement(64*1024*1024)
.make()
// NPE here --->
parseInput(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file))
streams.each{ TxStream stream -> stream.getWidth() }
return true
}
} catch (IndexOutOfBoundsException e) {
return false
} catch (IllegalArgumentException e) {
return false
} catch (NumberFormatException e) {
return false
} catch(EOFException e) {
return true;
} catch(Exception e) {
System.out.println("---->>> Exception "+e.toString()+" caught while loading database");
//System.out.println("---->>> Exception "+e.toString()+" caught while loading database. StackTrace following... ");
//e.printStackTrace()
} catch(Error e) {
System.out.println("---->>> Exception "+e.toString()+" caught while loading database. StackTrace following... ");
e.printStackTrace()
}
return false;
}
private static boolean isTxfile(InputStream istream) {
byte[] buffer = new byte[x.size()]
def readCnt = istream.read(buffer, 0, x.size())
istream.close()
if(readCnt==x.size()){
for(int i=0; i<x.size(); i++)
if(buffer[i]!=x[i]) return false
}
return true
}
private static boolean isGzipped(File f) {
InputStream is = null;
try {
is = new FileInputStream(f);
byte [] signature = new byte[2];
int nread = is.read( signature ); //read the gzip signature
return nread == 2 && signature[ 0 ] == (byte) 0x1f && signature[ 1 ] == (byte) 0x8b;
} catch (IOException e) {
return false;
} finally {
if(is!=null) is.close()
}
}
private stringToScale(String scale){
switch(scale.trim()){
case "fs":return 1L
case "ps":return 1000L
case "ns":return 1000000L
case "us":return 1000000000L
case "ms":return 1000000000000L
case "s": return 1000000000000000L
}
return 1L
}
private def parseInput(InputStream inputStream){
def streamsById = [:]
def generatorsById = [:]
def transactionsById = [:]
TxGenerator generator
Tx transaction
boolean endTransaction=false
def matcher
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
long lineCnt=0;
reader.eachLine { line ->
def tokens = line.split(/\s+/) as ArrayList
switch(tokens[0]){
case "scv_tr_stream":
if ((matcher = line =~ /^scv_tr_stream\s+\(ID (\d+),\s+name\s+"([^"]+)",\s+kind\s+"([^"]+)"\)$/)) {
def id = Integer.parseInt(matcher[0][1])
def stream = new TxStream(this, id, matcher[0][2], matcher[0][3])
streams<<stream
streamsById[id]=stream
}
break;
case "scv_tr_generator":
if ((matcher = line =~ /^scv_tr_generator\s+\(ID\s+(\d+),\s+name\s+"([^"]+)",\s+scv_tr_stream\s+(\d+),$/)) {
def id = Integer.parseInt(matcher[0][1])
TxStream stream=streamsById[Integer.parseInt(matcher[0][3])] as TxStream
generator=new TxGenerator(id, stream, matcher[0][2])
stream.generators<<generator
generatorsById[id]=generator
}
break;
case "begin_attribute":
if ((matcher = line =~ /^begin_attribute \(ID (\d+), name "([^"]+)", type "([^"]+)"\)$/)) {
generator.begin_attrs << TxAttributeType.getAttrType(matcher[0][2], DataType.valueOf(matcher[0][3]), AssociationType.BEGIN)
}
break;
case "end_attribute":
if ((matcher = line =~ /^end_attribute \(ID (\d+), name "([^"]+)", type "([^"]+)"\)$/)) {
generator.end_attrs << TxAttributeType.getAttrType(matcher[0][2], DataType.valueOf(matcher[0][3]), AssociationType.END)
}
break;
case ")":
generator=null
break
case "tx_begin"://matcher = line =~ /^tx_begin\s+(\d+)\s+(\d+)\s+(\d+)\s+([munpf]?s)/
def id = Integer.parseInt(tokens[1])
TxGenerator gen=generatorsById[Integer.parseInt(tokens[2])]
transaction = new Tx(id, gen.stream, gen, Long.parseLong(tokens[3])*stringToScale(tokens[4]))
gen.transactions << transaction
transactionsById[id]= transaction
gen.begin_attrs_idx=0;
maxTime = maxTime>transaction.beginTime?maxTime:transaction.beginTime
endTransaction=false
break
case "tx_end"://matcher = line =~ /^tx_end\s+(\d+)\s+(\d+)\s+(\d+)\s+([munpf]?s)/
def id = Integer.parseInt(tokens[1])
transaction = transactionsById[id]
assert Integer.parseInt(tokens[2])==transaction.generator.id
transaction.endTime = Long.parseLong(tokens[3])*stringToScale(tokens[4])
transaction.generator.end_attrs_idx=0;
maxTime = maxTime>transaction.endTime?maxTime:transaction.endTime
endTransaction=true
break
case "tx_record_attribute"://matcher = line =~ /^tx_record_attribute\s+(\d+)\s+"([^"]+)"\s+(\S+)\s*=\s*(.+)$/
def id = Integer.parseInt(tokens[1])
def name = tokens[2][1..-2]
def type = tokens[3] as DataType
def remaining = tokens.size()>5?tokens[5..-1].join(' '):""
transactionsById[id].attributes<<new TxAttribute(name, type, AssociationType.RECORD, remaining)
break
case "a"://matcher = line =~ /^a\s+(.+)$/
if(endTransaction){
transaction.attributes << new TxAttribute(transaction.generator.end_attrs[transaction.generator.end_attrs_idx], tokens[1])
transaction.generator.end_attrs_idx++
} else {
transaction.attributes << new TxAttribute(transaction.generator.begin_attrs[transaction.generator.begin_attrs_idx], tokens[1])
transaction.generator.begin_attrs_idx++
}
break
case "tx_relation"://matcher = line =~ /^tx_relation\s+\"(\S+)\"\s+(\d+)\s+(\d+)$/
Tx tr2= transactionsById[Integer.parseInt(tokens[2])]
Tx tr1= transactionsById[Integer.parseInt(tokens[3])]
def relType=tokens[1][1..-2]
if(!relationTypes.containsKey(relType)) relationTypes[relType]=RelationType.create(relType)
def rel = new TxRelation(relationTypes[relType], tr1, tr2)
tr1.outgoingRelations<<rel
tr2.incomingRelations<<rel
break
default:
println "Don't know what to do with: '$line'"
}
lineCnt++
}
}
public Collection<RelationType> getAllRelationTypes(){
return relationTypes.values();
}
}

View File

@ -0,0 +1,385 @@
/*******************************************************************************
* Copyright (c) 2012 IT Just working.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IT Just working - initial API and implementation
*******************************************************************************/
package com.minres.scviewer.database.text;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import org.eclipse.collections.impl.map.mutable.UnifiedMap;
import org.mapdb.DB;
import org.mapdb.DB.TreeMapSink;
import org.mapdb.DBMaker;
import org.mapdb.Serializer;
import com.google.common.collect.HashMultimap;
import com.minres.scviewer.database.AssociationType;
import com.minres.scviewer.database.DataType;
import com.minres.scviewer.database.EventKind;
import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.IWaveformDb;
import com.minres.scviewer.database.IWaveformDbLoader;
import com.minres.scviewer.database.InputFormatException;
import com.minres.scviewer.database.RelationType;
import com.minres.scviewer.database.RelationTypeFactory;
import com.minres.scviewer.database.tx.ITx;
public class TextDbLoader implements IWaveformDbLoader{
private Long maxTime=0L;
DB mapDb=null;
final List<String> attrValues = new ArrayList<>();
final Map<String, RelationType> relationTypes = UnifiedMap.newMap();
final Map<Long, TxStream> txStreams = UnifiedMap.newMap();
final Map<Long, TxGenerator> txGenerators = UnifiedMap.newMap();
Map<Long, ScvTx> transactions = null;
final Map<String, TxAttributeType> attributeTypes = UnifiedMap.newMap();
final HashMultimap<Long, ScvRelation> relationsIn = HashMultimap.create();
final HashMultimap<Long, ScvRelation> relationsOut = HashMultimap.create();
HashMap<Long, Tx> txCache = new HashMap<>();
List<Thread> threads = new ArrayList<>();
@Override
public Long getMaxTime() {
return maxTime;
}
@Override
public Collection<IWaveform> getAllWaves() {
return new ArrayList<>(txStreams.values());
}
static final byte[] x = "scv_tr_stream".getBytes();
@SuppressWarnings("unchecked")
@Override
public boolean load(IWaveformDb db, File file) throws InputFormatException {
dispose();
if(file.isDirectory() || !file.exists()) return false;
TextDbParser parser = new TextDbParser(this);
boolean gzipped = isGzipped(file);
try {
if(!isTxfile(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file)))
return false;
} catch(Exception e) {
throw new InputFormatException();
}
if(file.length() < 75000000*(gzipped?1:10) || "memory".equals(System.getProperty("ScvBackingDB", "file")))
mapDb = DBMaker
.memoryDirectDB()
.allocateStartSize(512l*1024l*1024l)
.allocateIncrement(128l*1024l*1024l)
.cleanerHackEnable()
.make();
else {
File mapDbFile;
try {
mapDbFile = File.createTempFile("."+file.getName(), ".mapdb", null /*file.parentFile*/);
Files.delete(Paths.get(mapDbFile.getPath()));
} catch (IOException e1) {
return false;
}
mapDb = DBMaker
.fileDB(mapDbFile)
.fileMmapEnable() // Always enable mmap
.fileMmapEnableIfSupported()
.fileMmapPreclearDisable()
.allocateStartSize(512l*1024l*1024l)
.allocateIncrement(128l*1024l*1024l)
.cleanerHackEnable()
.make();
mapDbFile.deleteOnExit();
}
try {
parser.txSink = mapDb.treeMap("transactions", Serializer.LONG,Serializer.JAVA).createFromSink();
parser.parseInput(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file));
transactions = parser.txSink.create();
} catch(IllegalArgumentException|ArrayIndexOutOfBoundsException e) {
} catch(Exception e) {
System.out.println("---->>> Exception "+e.toString()+" caught while loading database");
e.printStackTrace();
return false;
}
for(TxStream stream:txStreams.values()) {
Thread t = new Thread() {
@Override
public void run() {
try {
stream.calculateConcurrency();
} catch (Exception e) {/* don't let exceptions bubble up */ }
}
};
threads.add(t);
t.start();
}
return true;
}
@Override
public void dispose() {
attrValues.clear();
relationTypes.clear();
txStreams.clear();
txGenerators.clear();
transactions = null;
attributeTypes.clear();
relationsIn.clear();
relationsOut.clear();
if(mapDb!=null) {
mapDb.close();
mapDb=null;
}
}
private static boolean isTxfile(InputStream istream) {
byte[] buffer = new byte[x.length];
try {
int readCnt = istream.read(buffer, 0, x.length);
istream.close();
if(readCnt==x.length){
for(int i=0; i<x.length; i++)
if(buffer[i]!=x[i]) return false;
}
return true;
} catch (IOException e) {
return false;
}
}
private static boolean isGzipped(File f) {
try(InputStream is = new FileInputStream(f)) {
byte [] signature = new byte[2];
int nread = is.read( signature ); //read the gzip signature
return nread == 2 && signature[ 0 ] == (byte) 0x1f && signature[ 1 ] == (byte) 0x8b;
} catch (IOException e) {
return false;
}
}
public Collection<RelationType> getAllRelationTypes(){
return relationTypes.values();
}
static class TextDbParser {
static final Pattern scv_tr_stream = Pattern.compile("^scv_tr_stream\\s+\\(ID (\\d+),\\s+name\\s+\"([^\"]+)\",\\s+kind\\s+\"([^\"]+)\"\\)$");
static final Pattern scv_tr_generator = Pattern.compile("^scv_tr_generator\\s+\\(ID\\s+(\\d+),\\s+name\\s+\"([^\"]+)\",\\s+scv_tr_stream\\s+(\\d+),$");
static final Pattern begin_attribute = Pattern.compile("^begin_attribute \\(ID (\\d+), name \"([^\"]+)\", type \"([^\"]+)\"\\)$");
static final Pattern end_attribute = Pattern.compile("^end_attribute \\(ID (\\d+), name \"([^\"]+)\", type \"([^\"]+)\"\\)$");
final TextDbLoader loader;
HashMap<Long, ScvTx> transactionById = new HashMap<>();
TreeMapSink<Long, ScvTx> txSink;
BufferedReader reader = null;
TxGenerator generator=null;
Map<String, Integer> attrValueLut = new HashMap<>();
public TextDbParser(TextDbLoader loader) {
super();
this.loader = loader;
}
void parseInput(InputStream inputStream) throws IOException{
reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
String curLine = reader.readLine();
String nextLine = null;
while((nextLine=reader.readLine())!=null && curLine!=null) {
curLine=parseLine(curLine, nextLine);
}
if(curLine!=null)
parseLine(curLine, nextLine);
}
private TxAttributeType getAttrType(String name, DataType dataType, AssociationType type){
String key =name+"-"+dataType.toString();
TxAttributeType res;
if(loader.attributeTypes.containsKey(key)){
res=loader.attributeTypes.get(key);
} else {
res=new TxAttributeType(name, dataType, type);
loader.attributeTypes.put(key, res);
}
return res;
}
private String parseLine(String curLine, String nextLine) throws IOException{
String[] tokens = curLine.split("\\s+");
if("tx_record_attribute".equals(tokens[0])){
Long id = Long.parseLong(tokens[1]);
String name = tokens[2].substring(1, tokens[2].length());
DataType type = DataType.valueOf(tokens[3]);
String remaining = tokens.length>5?String.join(" ", Arrays.copyOfRange(tokens, 5, tokens.length)):"";
TxAttributeType attrType = getAttrType(name, type, AssociationType.RECORD);
transactionById.get(id).attributes.add(new TxAttribute(attrType, getAttrString(attrType, remaining)));
} else if("tx_begin".equals(tokens[0])){
Long id = Long.parseLong(tokens[1]);
Long genId = Long.parseLong(tokens[2]);
TxGenerator gen=loader.txGenerators.get(genId);
ScvTx scvTx = new ScvTx(id, gen.stream.getId(), genId, Long.parseLong(tokens[3])*stringToScale(tokens[4]));
loader.maxTime = loader.maxTime>scvTx.beginTime?loader.maxTime:scvTx.beginTime;
TxStream stream = loader.txStreams.get(gen.stream.getId());
stream.setConcurrency(stream.getConcurrency()+1);
if(nextLine!=null && nextLine.charAt(0)=='a') {
int idx=0;
while(nextLine!=null && nextLine.charAt(0)=='a') {
String[] attrTokens=nextLine.split("\\s+");
TxAttributeType attrType = gen.beginAttrs.get(idx);
TxAttribute attr = new TxAttribute(attrType, getAttrString(attrType, attrTokens[1]));
scvTx.attributes.add(attr);
idx++;
nextLine=reader.readLine();
}
}
txSink.put(id, scvTx);
transactionById.put(id, scvTx);
} else if("tx_end".equals(tokens[0])){
Long id = Long.parseLong(tokens[1]);
ScvTx scvTx = transactionById.get(id);
assert Long.parseLong(tokens[2])==scvTx.generatorId;
scvTx.endTime=Long.parseLong(tokens[3])*stringToScale(tokens[4]);
loader.maxTime = loader.maxTime>scvTx.endTime?loader.maxTime:scvTx.endTime;
TxGenerator gen = loader.txGenerators.get(scvTx.generatorId);
TxStream stream = loader.txStreams.get(gen.stream.getId());
if(scvTx.beginTime==scvTx.endTime)
stream.addEvent(new TxEvent(loader, EventKind.SINGLE, id, scvTx.beginTime));
else {
stream.addEvent(new TxEvent(loader, EventKind.BEGIN, id, scvTx.beginTime));
stream.addEvent(new TxEvent(loader, EventKind.END, id, scvTx.endTime));
}
stream.setConcurrency(stream.getConcurrency()-1);
if(nextLine!=null && nextLine.charAt(0)=='a') {
int idx=0;
while(nextLine!=null && nextLine.charAt(0)=='a') {
String[] attrTokens=nextLine.split("\\s+");
TxAttributeType attrType = gen.endAttrs.get(idx);
TxAttribute attr = new TxAttribute(attrType, getAttrString(attrType, attrTokens[1]));
scvTx.attributes.add(attr);
idx++;
nextLine=reader.readLine();
}
}
} else if("tx_relation".equals(tokens[0])){
Long tr2= Long.parseLong(tokens[2]);
Long tr1= Long.parseLong(tokens[3]);
String relType=tokens[1].substring(1, tokens[1].length()-1);
if(!loader.relationTypes.containsKey(relType))
loader.relationTypes.put(relType, RelationTypeFactory.create(relType));
ScvRelation rel = new ScvRelation(loader.relationTypes.get(relType), tr1, tr2);
loader.relationsOut.put(tr1, rel);
loader.relationsIn.put(tr2, rel);
} else if("scv_tr_stream".equals(tokens[0])){
Matcher matcher = scv_tr_stream.matcher(curLine);
if (matcher.matches()) {
Long id = Long.parseLong(matcher.group(1));
TxStream stream = new TxStream(loader, id, matcher.group(2), matcher.group(3));
loader.txStreams.put(id, stream);
}
} else if("scv_tr_generator".equals(tokens[0])){
Matcher matcher = scv_tr_generator.matcher(curLine);
if ((matcher.matches())) {
Long id = Long.parseLong(matcher.group(1));
TxStream stream=loader.txStreams.get(Long.parseLong(matcher.group(3)));
generator=new TxGenerator(id, stream, matcher.group(2));
loader.txGenerators.put(id, generator);
}
} else if("begin_attribute".equals(tokens[0])){
Matcher matcher = begin_attribute.matcher(curLine);
if ((matcher.matches())) {
TxAttributeType attrType = getAttrType(matcher.group(2), DataType.valueOf(matcher.group(3)), AssociationType.BEGIN);
generator.beginAttrs.add(attrType);
}
} else if("end_attribute".equals(tokens[0])){
Matcher matcher = end_attribute.matcher(curLine);
if ((matcher.matches())) {
TxAttributeType attrType = getAttrType(matcher.group(2), DataType.valueOf(matcher.group(3)), AssociationType.END);
generator.endAttrs.add(attrType);
}
} else if(")".equals(tokens[0])){
generator=null;
} else if("a".equals(tokens[0])){//matcher = line =~ /^a\s+(.+)$/
System.out.println("Don't know what to do with: '"+curLine+"'");
} else
System.out.println("Don't know what to do with: '"+curLine+"'");
return nextLine;
}
private String getAttrString(TxAttributeType attrType, String string) {
String value;
switch(attrType.getDataType()){
case STRING:
case ENUMERATION:
value=string.substring(1, string.length()-1);
break;
default:
value=string;
}
if(attrValueLut.containsKey(value)){
return loader.attrValues.get(attrValueLut.get(value));
} else {
attrValueLut.put(value, loader.attrValues.size());
loader.attrValues.add(value);
return value;
}
}
private long stringToScale(String scale){
String cmp = scale.trim();
if("fs".equals(cmp)) return 1L;
if("ps".equals(cmp)) return 1000L;
if("ns".equals(cmp)) return 1000000L;
if("us".equals(cmp)) return 1000000000L;
if("ms".equals(cmp)) return 1000000000000L;
if("s".equals(cmp) ) return 1000000000000000L;
return 1L;
}
}
public ITx getTransaction(long txId) {
if(txCache.containsKey(txId))
return txCache.get(txId);
Tx tx = new Tx(this, txId);
txCache.put(txId, tx);
return tx;
}
}

View File

@ -1,70 +0,0 @@
/*******************************************************************************
* Copyright (c) 2012 IT Just working.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IT Just working - initial API and implementation
*******************************************************************************/
package com.minres.scviewer.database.text
import com.minres.scviewer.database.*
import com.minres.scviewer.database.tx.ITx
import com.minres.scviewer.database.tx.ITxAttribute
import com.minres.scviewer.database.tx.ITxRelation
class Tx implements ITx {
Long id
TxGenerator generator
TxStream stream
int concurrencyIndex
Long beginTime
Long endTime
ArrayList<ITxAttribute> attributes = new ArrayList<ITxAttribute>()
def incomingRelations =[]
def outgoingRelations =[]
Tx(int id, TxStream stream, TxGenerator generator, Long begin){
this.id=id
this.stream=stream
this.generator=generator
this.beginTime=begin
this.endTime=begin
}
@Override
public Collection<ITxRelation> getIncomingRelations() {
return incomingRelations;
}
@Override
public Collection<ITxRelation> getOutgoingRelations() {
return outgoingRelations;
}
@Override
public int compareTo(ITx o) {
def res =beginTime.compareTo(o.beginTime)
if(res!=0)
return res
else
return id.compareTo(o.id)
}
@Override
public String toString() {
return "tx#"+getId()+"["+getBeginTime()/1000000+"ns - "+getEndTime()/1000000+"ns]";
}
}

View File

@ -0,0 +1,132 @@
/*******************************************************************************
* Copyright (c) 2012 IT Just working.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IT Just working - initial API and implementation
*******************************************************************************/
package com.minres.scviewer.database.text;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.tx.ITx;
import com.minres.scviewer.database.tx.ITxAttribute;
import com.minres.scviewer.database.tx.ITxGenerator;
import com.minres.scviewer.database.tx.ITxRelation;
class Tx implements ITx {
private final TextDbLoader loader;
private long id;
long beginTime=-1;
long endTime=-1;
private int concurrencyIndex;
public Tx(TextDbLoader loader, ScvTx scvTx) {
this.loader=loader;
id=scvTx.id;
}
public Tx(TextDbLoader loader, long txId) {
this.loader=loader;
id=txId;
}
@Override
public Collection<ITxRelation> getIncomingRelations() {
Set<ScvRelation> rels = loader.relationsIn.get(id);
return rels.stream().map(rel -> new TxRelation(loader, rel)).collect(Collectors.toList());
}
@Override
public Collection<ITxRelation> getOutgoingRelations() {
Set<ScvRelation> rels = loader.relationsOut.get(id);
return rels.stream().map(rel -> new TxRelation(loader, rel)).collect(Collectors.toList());
}
@Override
public int compareTo(ITx o) {
int res =getBeginTime().compareTo(o.getBeginTime());
if(res!=0)
return res;
else
return getId().compareTo(o.getId());
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
return this.getScvTx().equals(((Tx) obj).getScvTx());
}
@Override
public int hashCode() {
return getScvTx().hashCode();
}
@Override
public String toString() {
return "tx#"+getId()+"["+getBeginTime()/1000000+"ns - "+getEndTime()/1000000+"ns]";
}
@Override
public Long getId() {
return getScvTx().id;
}
@Override
public IWaveform getStream() {
return loader.txStreams.get(getScvTx().streamId);
}
@Override
public ITxGenerator getGenerator() {
return loader.txGenerators.get(getScvTx().generatorId);
}
@Override
public Long getBeginTime() {
if(beginTime<0) beginTime=getScvTx().beginTime;
return beginTime;
}
@Override
public Long getEndTime() {
if(endTime<0) endTime=getScvTx().endTime;
return endTime;
}
void setEndTime(Long time) {
getScvTx().endTime=time;
}
@Override
public int getConcurrencyIndex() {
return concurrencyIndex;
}
void setConcurrencyIndex(int idx) {
concurrencyIndex=idx;
}
@Override
public List<ITxAttribute> getAttributes() {
return getScvTx().attributes;
}
private ScvTx getScvTx() {
return loader.transactions.get(id);
}
}

View File

@ -8,37 +8,28 @@
* Contributors: * Contributors:
* IT Just working - initial API and implementation * IT Just working - initial API and implementation
*******************************************************************************/ *******************************************************************************/
package com.minres.scviewer.database.text package com.minres.scviewer.database.text;
import java.io.Serializable;
import com.minres.scviewer.database.AssociationType; import com.minres.scviewer.database.AssociationType;
import com.minres.scviewer.database.DataType; import com.minres.scviewer.database.DataType;
import com.minres.scviewer.database.tx.ITxAttribute import com.minres.scviewer.database.tx.ITxAttribute;
import com.minres.scviewer.database.tx.ITxAttributeType
class TxAttribute implements ITxAttribute{ public class TxAttribute implements ITxAttribute, Serializable {
TxAttributeType attributeType /**
*
*/
private static final long serialVersionUID = 4767726016651807152L;
def value private final TxAttributeType attributeType;
TxAttribute(String name, DataType dataType, AssociationType type, value){ private final String value;
attributeType = TxAttributeTypeFactory.instance.getAttrType(name, dataType, type)
switch(dataType){
case DataType.STRING:
case DataType.ENUMERATION:
this.value=value[1..-2]
break;
default:
this.value=value
}
}
TxAttribute(TxAttributeType other){ TxAttribute(TxAttributeType type, String value){
attributeType=other this.attributeType=type;
} this.value=value;
TxAttribute(TxAttributeType other, value){
this(other.name, other.dataType, other.type, value)
} }
@Override @Override
@ -48,12 +39,17 @@ class TxAttribute implements ITxAttribute{
@Override @Override
public AssociationType getType() { public AssociationType getType() {
attributeType.type; return attributeType.getType();
} }
@Override @Override
public DataType getDataType() { public DataType getDataType() {
attributeType.dataType; return attributeType.getDataType();
}
@Override
public Object getValue() {
return value;
} }
} }

View File

@ -8,24 +8,44 @@
* Contributors: * Contributors:
* IT Just working - initial API and implementation * IT Just working - initial API and implementation
*******************************************************************************/ *******************************************************************************/
package com.minres.scviewer.database.text package com.minres.scviewer.database.text;
import java.io.Serializable;
import com.minres.scviewer.database.AssociationType; import com.minres.scviewer.database.AssociationType;
import com.minres.scviewer.database.DataType; import com.minres.scviewer.database.DataType;
import com.minres.scviewer.database.tx.ITxAttributeType import com.minres.scviewer.database.tx.ITxAttributeType;
class TxAttributeType implements ITxAttributeType { class TxAttributeType implements ITxAttributeType, Serializable {
String name /**
DataType dataType *
AssociationType type */
private static final long serialVersionUID = 7159721937208946828L;
static TxAttributeType getAttrType(String name, DataType dataType, AssociationType type){ private String name;
TxAttributeTypeFactory.instance.getAttrType(name, dataType, type)
} private DataType dataType;
private AssociationType type;
TxAttributeType(String name, DataType dataType, AssociationType type){ TxAttributeType(String name, DataType dataType, AssociationType type){
this.name=name this.name=name;
this.dataType=dataType this.dataType=dataType;
this.type=type this.type=type;
}
@Override
public String getName() {
return name;
}
@Override
public DataType getDataType() {
return dataType;
}
@Override
public AssociationType getType() {
return type;
} }
} }

View File

@ -1,38 +0,0 @@
/*******************************************************************************
* Copyright (c) 2012 IT Just working.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IT Just working - initial API and implementation
*******************************************************************************/
package com.minres.scviewer.database.text
import com.minres.scviewer.database.AssociationType;
import com.minres.scviewer.database.DataType
import com.minres.scviewer.database.tx.ITxAttribute
import com.minres.scviewer.database.tx.ITxAttributeType
class TxAttributeTypeFactory {
static final TxAttributeTypeFactory instance = new TxAttributeTypeFactory()
def attributes = [:]
private TxAttributeTypeFactory() {
TxAttributeTypeFactory.metaClass.constructor = {-> instance }
}
ITxAttributeType getAttrType(String name, DataType dataType, AssociationType type){
def key = name+":"+dataType.toString()
ITxAttributeType res
if(attributes.containsKey(key)){
res=attributes[key]
} else {
res=new TxAttributeType(name, dataType, type)
attributes[key]=res
}
return res
}
}

View File

@ -7,21 +7,16 @@ import com.minres.scviewer.database.tx.ITxEvent;
class TxEvent implements ITxEvent { class TxEvent implements ITxEvent {
final TextDbLoader loader;
final EventKind kind; final EventKind kind;
final ITx transaction; final Long transaction;
final Long time; final Long time;
TxEvent(EventKind kind, ITx transaction) { TxEvent(TextDbLoader loader, EventKind kind, Long transaction, Long time) {
super(); this.loader=loader;
this.kind = kind;
this.transaction = transaction;
this.time = kind==EventKind.BEGIN?transaction.getBeginTime():transaction.getEndTime();
}
public TxEvent(EventKind kind, ITx transaction, Long time) {
super();
this.kind = kind; this.kind = kind;
this.transaction = transaction; this.transaction = transaction;
this.time = time; this.time = time;
@ -30,13 +25,13 @@ class TxEvent implements ITxEvent {
@Override @Override
public public
ITxEvent duplicate() throws CloneNotSupportedException { ITxEvent duplicate() throws CloneNotSupportedException {
return new TxEvent(kind, transaction, time); return new TxEvent(loader, kind, transaction, time);
} }
@Override @Override
public public
String toString() { String toString() {
return kind.toString()+"@"+time+" of tx #"+transaction.getId(); return kind.toString()+"@"+time+" of tx #"+transaction;
} }
@Override @Override
@ -56,6 +51,6 @@ class TxEvent implements ITxEvent {
@Override @Override
public ITx getTransaction() { public ITx getTransaction() {
return transaction; return loader.getTransaction(transaction);
} }
} }

View File

@ -1,50 +0,0 @@
/*******************************************************************************
* Copyright (c) 2012 IT Just working.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IT Just working - initial API and implementation
*******************************************************************************/
package com.minres.scviewer.database.text
import java.util.ArrayList;
import java.util.List;
import com.minres.scviewer.database.IWaveform
import com.minres.scviewer.database.tx.ITx
import com.minres.scviewer.database.tx.ITxAttribute
import com.minres.scviewer.database.tx.ITxAttributeType
import com.minres.scviewer.database.tx.ITxGenerator
class TxGenerator implements ITxGenerator{
Long id
IWaveform stream
String name
Boolean active = false
ArrayList<ITx> transactions=[]
ArrayList<ITxAttributeType> begin_attrs = []
int begin_attrs_idx = 0
ArrayList<ITxAttributeType> end_attrs= []
int end_attrs_idx = 0
TxGenerator(int id, TxStream stream, name){
this.id=id
this.stream=stream
this.name=name
}
IWaveform getStream(){
return stream;
}
List<ITx> getTransactions(){
return transactions
}
Boolean isActive() {return active};
}

View File

@ -0,0 +1,63 @@
/*******************************************************************************
* Copyright (c) 2012 IT Just working.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IT Just working - initial API and implementation
*******************************************************************************/
package com.minres.scviewer.database.text;
import java.util.ArrayList;
import java.util.List;
import com.minres.scviewer.database.HierNode;
import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.tx.ITxGenerator;
class TxGenerator extends HierNode implements ITxGenerator {
Long id;
IWaveform stream;
Boolean active = false;
List<TxAttributeType> beginAttrs = new ArrayList<>();
List<TxAttributeType> endAttrs= new ArrayList<>();
TxGenerator(Long id, TxStream stream, String name){
super(name, stream);
this.id=id;
this.stream=stream;
}
@Override
public Long getId() {
return id;
}
@Override
public IWaveform getStream(){
return stream;
}
@Override
public String getName() {
return name;
}
public List<TxAttributeType> getBeginAttrs() {
return beginAttrs;
}
public List<TxAttributeType> getEndAttrs() {
return endAttrs;
}
Boolean isActive() {return active;}
}

View File

@ -5,31 +5,29 @@ import com.minres.scviewer.database.tx.ITx;
import com.minres.scviewer.database.tx.ITxRelation; import com.minres.scviewer.database.tx.ITxRelation;
class TxRelation implements ITxRelation { class TxRelation implements ITxRelation {
final Tx source;
final Tx target; final TextDbLoader loader;
final RelationType relationType; final ScvRelation scvRelation;
public TxRelation(RelationType relationType, Tx source, Tx target) { public TxRelation(TextDbLoader loader, ScvRelation scvRelation) {
this.source = source; this.loader = loader;
this.target = target; this.scvRelation = scvRelation;
this.relationType = relationType;
} }
@Override @Override
public RelationType getRelationType() { public RelationType getRelationType() {
return relationType; return scvRelation.relationType;
} }
@Override @Override
public ITx getSource() { public ITx getSource() {
return source; return loader.getTransaction(scvRelation.source);
} }
@Override @Override
public ITx getTarget() { public ITx getTarget() {
return target; return loader.getTransaction(scvRelation.target);
} }
} }

View File

@ -1,135 +0,0 @@
/*******************************************************************************
* Copyright (c) 2012 IT Just working.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IT Just working - initial API and implementation
*******************************************************************************/
package com.minres.scviewer.database.text
import java.beans.PropertyChangeListener;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Map.Entry
import org.mapdb.Serializer
import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.IWaveformDb
import com.minres.scviewer.database.WaveformType
import com.minres.scviewer.database.tx.ITx
import com.minres.scviewer.database.tx.ITxEvent
import com.minres.scviewer.database.tx.ITxGenerator
import com.minres.scviewer.database.EventKind
import com.minres.scviewer.database.HierNode;
import com.minres.scviewer.database.IEvent
import com.minres.scviewer.database.IHierNode
class TxStream extends HierNode implements IWaveform {
Long id
IWaveformDb database
String fullName
def generators = []
int maxConcurrency
private TreeMap<Long, IEvent[]> events
TxStream(TextDbLoader loader, int id, String name, String kind){
super(name)
this.id=id
this.database=loader.db
this.fullName=name
this.maxConcurrency=0
//events = new TreeMap<Long, List<ITxEvent>>()
events = loader.mapDb.treeMap(name).keySerializer(Serializer.LONG).createOrOpen();
}
List<ITxGenerator> getGenerators(){
return generators as List<ITxGenerator>
}
@Override
public IWaveformDb getDb() {
return database
}
@Override
public int getWidth() {
if(!maxConcurrency){
generators.each {TxGenerator generator ->
generator.transactions.each{ Tx tx ->
putEvent(new TxEvent(EventKind.BEGIN, tx))
putEvent(new TxEvent(EventKind.END, tx))
}
}
def rowendtime = [0]
events.keySet().each{long time ->
def value=events.get(time)
def starts=value.findAll{IEvent event ->event.kind==EventKind.BEGIN}
starts.each {ITxEvent event ->
Tx tx = event.transaction
def rowIdx = 0
for(rowIdx=0; rowIdx<rowendtime.size() && rowendtime[rowIdx]>tx.beginTime; rowIdx++);
if(rowendtime.size<=rowIdx)
rowendtime<<tx.endTime
else
rowendtime[rowIdx]=tx.endTime
tx.concurrencyIndex=rowIdx
}
}
maxConcurrency=rowendtime.size()
}
return maxConcurrency
}
private putEvent(ITxEvent event){
if(!events.containsKey(event.time))
events.put(event.time, [event] as IEvent[])
else {
def entries = events[event.time] as List
entries<<event
events.put(event.time, entries as IEvent[])
}
}
@Override
public NavigableMap<Long, IEvent[]> getEvents() {
return events;
}
@Override
public IEvent[] getEventsAtTime(Long time) {
return events.get(time);
}
@Override
public boolean isSame(IWaveform other) {
return(other instanceof TxStream && this.getId()==other.getId());
}
@Override
public IEvent[] getEventsBeforeTime(Long time) {
Entry<Long, IEvent[]> e = events.floorEntry(time);
if(e==null)
return null;
else
return events.floorEntry(time).getValue();
}
@Override
public WaveformType getType() {
return WaveformType.TRANSACTION;
}
}

View File

@ -0,0 +1,138 @@
/*******************************************************************************
* Copyright (c) 2012 IT Just working.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IT Just working - initial API and implementation
*******************************************************************************/
package com.minres.scviewer.database.text;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map.Entry;
import java.util.NavigableMap;
import java.util.TreeMap;
import com.minres.scviewer.database.EventKind;
import com.minres.scviewer.database.HierNode;
import com.minres.scviewer.database.IEvent;
import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.WaveformType;
import com.minres.scviewer.database.tx.ITxEvent;
import com.minres.scviewer.database.tx.ITxGenerator;
class TxStream extends HierNode implements IWaveform {
private Long id;
private TextDbLoader loader;
final String kind;
private int maxConcurrency = 0;
private int concurrency = 0;
boolean concurrencyCalculated = false;
void setConcurrency(int concurrency) {
this.concurrency = concurrency;
if(concurrency>maxConcurrency)
maxConcurrency = concurrency;
}
int getConcurrency() {
return this.concurrency;
}
TreeMap<Long, IEvent[]> events = new TreeMap<>();
TxStream(TextDbLoader loader, Long id, String name, String kind){
super(name);
this.id=id;
this.loader=loader;
this.kind=kind;
}
List<ITxGenerator> getGenerators(){
return new ArrayList<>(loader.txGenerators.values());
}
@Override
public int getWidth() {
return maxConcurrency;
}
public void addEvent(ITxEvent evt) {
if(!events.containsKey(evt.getTime()))
events.put(evt.getTime(), new IEvent[] {evt});
else {
IEvent[] evts = events.get(evt.getTime());
IEvent[] newEvts = Arrays.copyOf(evts, evts.length+1);
newEvts[evts.length]=evt;
events.put(evt.getTime(), newEvts);
}
}
@Override
public NavigableMap<Long, IEvent[]> getEvents() {
if(!concurrencyCalculated) calculateConcurrency();
return events;
}
@Override
public IEvent[] getEventsAtTime(Long time) {
if(!concurrencyCalculated) calculateConcurrency();
return events.get(time);
}
@Override
public boolean isSame(IWaveform other) {
return(other instanceof TxStream && this.getId().equals(other.getId()));
}
@Override
public IEvent[] getEventsBeforeTime(Long time) {
if(!concurrencyCalculated)
calculateConcurrency();
Entry<Long, IEvent[]> e = events.floorEntry(time);
if(e==null)
return new IEvent[] {};
else
return events.floorEntry(time).getValue();
}
@Override
public WaveformType getType() {
return WaveformType.TRANSACTION;
}
@Override
public Long getId() {
return id;
}
synchronized void calculateConcurrency() {
if(concurrencyCalculated) return;
ArrayList<Long> rowendtime = new ArrayList<>();
events.entrySet().stream().forEach( entry -> {
IEvent[] values = entry.getValue();
Arrays.asList(values).stream().filter(e->e.getKind()==EventKind.BEGIN).forEach(evt -> {
Tx tx = (Tx) ((TxEvent)evt).getTransaction();
int rowIdx = 0;
for(; rowIdx<rowendtime.size() && rowendtime.get(rowIdx)>tx.getBeginTime(); rowIdx++);
if(rowendtime.size()<=rowIdx)
rowendtime.add(tx.getEndTime());
else
rowendtime.set(rowIdx, tx.getEndTime());
tx.setConcurrencyIndex(rowIdx);
});
});
concurrencyCalculated=true;
}
}

View File

@ -22,6 +22,7 @@ import org.eclipse.swt.widgets.Control;
import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.RelationType; import com.minres.scviewer.database.RelationType;
import com.minres.scviewer.database.RelationTypeFactory;
public interface IWaveformView extends PropertyChangeListener, ISelectionProvider{ public interface IWaveformView extends PropertyChangeListener, ISelectionProvider{
@ -29,7 +30,7 @@ public interface IWaveformView extends PropertyChangeListener, ISelectionProvide
String MARKER_PROPERTY = "marker_time"; String MARKER_PROPERTY = "marker_time";
public static final RelationType NEXT_PREV_IN_STREAM = RelationType.create("Prev/Next in stream"); public static final RelationType NEXT_PREV_IN_STREAM = RelationTypeFactory.create("Prev/Next in stream");
public void addSelectionChangedListener(ISelectionChangedListener listener); public void addSelectionChangedListener(ISelectionChangedListener listener);

View File

@ -84,17 +84,20 @@ public class StreamPainter extends TrackPainter{
NavigableMap<Long, IEvent[]> entries = stream.getEvents().subMap(firstTx.getKey(), true, lastTx.getKey(), true); NavigableMap<Long, IEvent[]> entries = stream.getEvents().subMap(firstTx.getKey(), true, lastTx.getKey(), true);
boolean highlighed=false; boolean highlighed=false;
proj.setForeground(this.waveCanvas.styleProvider.getColor(WaveformColors.LINE)); proj.setForeground(this.waveCanvas.styleProvider.getColor(WaveformColors.LINE));
long selectedId=waveCanvas.currentSelection!=null? waveCanvas.currentSelection.getId():-1;
for(Entry<Long, IEvent[]> entry: entries.entrySet()) for(Entry<Long, IEvent[]> entry: entries.entrySet())
for(IEvent evt:entry.getValue()){ for(IEvent evt:entry.getValue()){
ITxEvent txEvent = (ITxEvent) evt; ITx tx = ((ITxEvent) evt).getTransaction();
if(txEvent.getKind()==EventKind.BEGIN) highlighed|=selectedId==tx.getId();
seenTx.add(txEvent.getTransaction()); switch(evt.getKind()) {
if(txEvent.getKind()==EventKind.END){ case BEGIN:
ITx tx = txEvent.getTransaction(); seenTx.add(tx);
highlighed|=waveCanvas.currentSelection!=null && waveCanvas.currentSelection.equals(tx); break;
drawTx(proj, area, tx, false); case END:
seenTx.remove(tx); seenTx.remove(tx);
case SINGLE:
drawTx(proj, area, tx, false);
break;
} }
} }
for(ITx tx:seenTx){ for(ITx tx:seenTx){
@ -164,7 +167,8 @@ public class StreamPainter extends TrackPainter{
for(IEvent evt:firstTx.getValue()){ for(IEvent evt:firstTx.getValue()){
if(evt instanceof ITxEvent) { if(evt instanceof ITxEvent) {
ITx tx=((ITxEvent)evt).getTransaction(); ITx tx=((ITxEvent)evt).getTransaction();
if(evt.getKind()==EventKind.BEGIN && tx.getConcurrencyIndex()==lane && tx.getBeginTime()<=timePoint && tx.getEndTime()>=timePoint){ if((evt.getKind()==EventKind.BEGIN || evt.getKind()==EventKind.SINGLE)&&
tx.getConcurrencyIndex()==lane && tx.getBeginTime()<=timePoint && tx.getEndTime()>=timePoint){
return ((ITxEvent)evt).getTransaction(); return ((ITxEvent)evt).getTransaction();
} }
} }
@ -175,7 +179,8 @@ public class StreamPainter extends TrackPainter{
for(IEvent evt:firstTx.getValue()){ for(IEvent evt:firstTx.getValue()){
if(evt instanceof ITxEvent) { if(evt instanceof ITxEvent) {
ITx tx=((ITxEvent)evt).getTransaction(); ITx tx=((ITxEvent)evt).getTransaction();
if(evt.getKind()==EventKind.BEGIN && tx.getConcurrencyIndex()==lane && tx.getBeginTime()<=timePointHigh && tx.getEndTime()>=timePoint){ if((evt.getKind()==EventKind.BEGIN || evt.getKind()==EventKind.SINGLE) &&
tx.getConcurrencyIndex()==lane && tx.getBeginTime()<=timePointHigh && tx.getEndTime()>=timePoint){
return ((ITxEvent)evt).getTransaction(); return ((ITxEvent)evt).getTransaction();
} }
} }

View File

@ -575,7 +575,7 @@ public class WaveformView implements IWaveformView {
for(IEvent evt:firstTx.getValue()){ for(IEvent evt:firstTx.getValue()){
if(evt instanceof ITxEvent) { if(evt instanceof ITxEvent) {
ITx tx=((ITxEvent)evt).getTransaction(); ITx tx=((ITxEvent)evt).getTransaction();
if(evt.getKind()==EventKind.BEGIN && tx.getBeginTime()<=time && tx.getEndTime()>=time){ if((evt.getKind()==EventKind.BEGIN || evt.getKind()==EventKind.SINGLE) && tx.getBeginTime()<=time && tx.getEndTime()>=time){
if(resultsList[tx.getConcurrencyIndex()]==null) if(resultsList[tx.getConcurrencyIndex()]==null)
resultsList[tx.getConcurrencyIndex()]= ((ITxEvent)evt).getTransaction(); resultsList[tx.getConcurrencyIndex()]= ((ITxEvent)evt).getTransaction();
} }
@ -703,7 +703,7 @@ public class WaveformView implements IWaveformView {
} else { } else {
if(!add) currentWaveformSelection.clear(); if(!add) currentWaveformSelection.clear();
for(Object sel:((IStructuredSelection) selection).toArray()){ for(Object sel:((IStructuredSelection) selection).toArray()){
if (sel instanceof ITx && currentTxSelection != sel){ if (sel instanceof ITx){
ITx txSel = (ITx) sel; ITx txSel = (ITx) sel;
TrackEntry trackEntry = getEntryForStream(txSel.getStream()); TrackEntry trackEntry = getEntryForStream(txSel.getStream());
if(trackEntry==null && addIfNeeded){ if(trackEntry==null && addIfNeeded){
@ -711,6 +711,8 @@ public class WaveformView implements IWaveformView {
streams.add(trackEntry); streams.add(trackEntry);
} }
currentTxSelection = txSel; currentTxSelection = txSel;
currentWaveformSelection.clear();
currentWaveformSelection.add(trackEntry);
selectionChanged = true; selectionChanged = true;
} else if (sel instanceof TrackEntry && !currentWaveformSelection.contains(sel)) { } else if (sel instanceof TrackEntry && !currentWaveformSelection.contains(sel)) {
currentWaveformSelection.add((TrackEntry)sel); currentWaveformSelection.add((TrackEntry)sel);
@ -769,32 +771,29 @@ public class WaveformView implements IWaveformView {
*/ */
@Override @Override
public void moveSelection(GotoDirection direction, RelationType relationType) { public void moveSelection(GotoDirection direction, RelationType relationType) {
TrackEntry selectedWaveform=null; if(currentWaveformSelection.size() !=1 && currentTxSelection==null) return;
if(currentTxSelection!=null) TrackEntry selectedWaveform=currentWaveformSelection.size() == 1?
selectedWaveform = getEntryForStream(currentTxSelection.getStream()); currentWaveformSelection.get(0) : getEntryForStream(currentTxSelection.getStream());
else if(currentWaveformSelection.size()!=1) return; if(selectedWaveform.waveform.getType()==WaveformType.TRANSACTION && currentTxSelection!=null) {
if(selectedWaveform==null)
selectedWaveform = currentWaveformSelection.get(1);
if (selectedWaveform!=null && selectedWaveform.waveform.getType()==WaveformType.TRANSACTION && currentTxSelection!=null) {
if(relationType.equals(IWaveformView.NEXT_PREV_IN_STREAM)){ if(relationType.equals(IWaveformView.NEXT_PREV_IN_STREAM)){
ITx transaction = null; ITx transaction = null;
if (direction == GotoDirection.NEXT) { if (direction == GotoDirection.NEXT) {
ITxEvent[] thisEntryList = (ITxEvent[]) selectedWaveform.waveform.getEvents().get(currentTxSelection.getBeginTime()); IEvent[] eventsList = selectedWaveform.waveform.getEvents().get(currentTxSelection.getBeginTime());
boolean meFound=false; boolean meFound=false;
for (ITxEvent evt : thisEntryList) { for (IEvent evt : eventsList) {
if (evt.getKind() == EventKind.BEGIN) { if (evt instanceof ITxEvent && evt.getKind() == EventKind.BEGIN || evt.getKind()==EventKind.SINGLE) {
if(meFound){ if(meFound){
transaction = evt.getTransaction(); transaction = ((ITxEvent)evt).getTransaction();
break; break;
} }
meFound|= evt.getTransaction().equals(currentTxSelection); meFound|= ((ITxEvent)evt).getTransaction().equals(currentTxSelection);
} }
} }
if (transaction == null){ if (transaction == null){
Entry<Long, IEvent[]> entry = selectedWaveform.waveform.getEvents().higherEntry(currentTxSelection.getBeginTime()); Entry<Long, IEvent[]> entry = selectedWaveform.waveform.getEvents().higherEntry(currentTxSelection.getBeginTime());
if (entry != null) do { if (entry != null) do {
for (IEvent evt : entry.getValue()) { for (IEvent evt : entry.getValue()) {
if (evt instanceof ITxEvent && evt.getKind() == EventKind.BEGIN) { if (evt instanceof ITxEvent && (evt.getKind() == EventKind.BEGIN || evt.getKind()==EventKind.SINGLE)) {
transaction = ((ITxEvent)evt).getTransaction(); transaction = ((ITxEvent)evt).getTransaction();
break; break;
} }
@ -804,10 +803,10 @@ public class WaveformView implements IWaveformView {
} while (entry != null && transaction == null); } while (entry != null && transaction == null);
} }
} else if (direction == GotoDirection.PREV) { } else if (direction == GotoDirection.PREV) {
IEvent[] thisEntryList = selectedWaveform.waveform.getEvents().get(currentTxSelection.getBeginTime()); IEvent[] eventsList = selectedWaveform.waveform.getEvents().get(currentTxSelection.getBeginTime());
boolean meFound=false; boolean meFound=false;
for (IEvent evt : Lists.reverse(Arrays.asList(thisEntryList))) { for (IEvent evt : Lists.reverse(Arrays.asList(eventsList))) {
if (evt instanceof ITxEvent && evt.getKind() == EventKind.BEGIN) { if (evt instanceof ITxEvent && (evt.getKind() == EventKind.BEGIN || evt.getKind()==EventKind.SINGLE)) {
if(meFound){ if(meFound){
transaction = ((ITxEvent)evt).getTransaction(); transaction = ((ITxEvent)evt).getTransaction();
break; break;
@ -817,10 +816,9 @@ public class WaveformView implements IWaveformView {
} }
if (transaction == null){ if (transaction == null){
Entry<Long, IEvent[]> entry = selectedWaveform.waveform.getEvents().lowerEntry(currentTxSelection.getBeginTime()); Entry<Long, IEvent[]> entry = selectedWaveform.waveform.getEvents().lowerEntry(currentTxSelection.getBeginTime());
if (entry != null) if (entry != null) do {
do { for (IEvent evt : Lists.reverse(Arrays.asList(entry.getValue()))) {
for (IEvent evt : Lists.reverse(Arrays.asList(thisEntryList))) { if (evt instanceof ITxEvent && (evt.getKind() == EventKind.BEGIN || evt.getKind()==EventKind.SINGLE)) {
if (evt instanceof ITxEvent && evt.getKind() == EventKind.BEGIN) {
transaction = ((ITxEvent)evt).getTransaction(); transaction = ((ITxEvent)evt).getTransaction();
break; break;
} }
@ -834,14 +832,17 @@ public class WaveformView implements IWaveformView {
setSelection(new StructuredSelection(transaction)); setSelection(new StructuredSelection(transaction));
} }
} else { } else {
ITxRelation tx = null;
if (direction == GotoDirection.NEXT) { if (direction == GotoDirection.NEXT) {
Collection<ITxRelation> outRel=currentTxSelection.getOutgoingRelations(); Collection<ITxRelation> outRel=currentTxSelection.getOutgoingRelations();
ITxRelation tx = selectTxToNavigateTo(outRel, relationType, true); tx = selectTxToNavigateTo(outRel, relationType, true);
if(tx!=null) setSelection(new StructuredSelection(tx.getTarget()), true); if(tx!=null)
setSelection(new StructuredSelection(tx.getTarget()), true);
} else if (direction == GotoDirection.PREV) { } else if (direction == GotoDirection.PREV) {
Collection<ITxRelation> inRel=currentTxSelection.getIncomingRelations(); Collection<ITxRelation> inRel=currentTxSelection.getIncomingRelations();
ITxRelation tx = selectTxToNavigateTo(inRel, relationType, false); tx = selectTxToNavigateTo(inRel, relationType, false);
if(tx!=null) setSelection(new StructuredSelection(tx.getSource()), true); if(tx!=null)
setSelection(new StructuredSelection(tx.getSource()), true);
} }
} }
} }
@ -1201,15 +1202,15 @@ public class WaveformView implements IWaveformView {
} }
} }
}); });
// int style = SWT.MULTI | SWT.WRAP | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER; // int style = SWT.MULTI | SWT.WRAP | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER;
// final StyledText text = new StyledText(waveformCanvas, style); // final StyledText text = new StyledText(waveformCanvas, style);
// text.setText("Dragging"); // text.setText("Dragging");
// dragSource.setDragSourceEffect(new DragSourceEffect(text) { // dragSource.setDragSourceEffect(new DragSourceEffect(text) {
// @Override // @Override
// public void dragStart(DragSourceEvent event) { // public void dragStart(DragSourceEvent event) {
// event.image = waveformCanvas.getDisplay().getSystemImage(SWT.ICON_WARNING); // event.image = waveformCanvas.getDisplay().getSystemImage(SWT.ICON_WARNING);
// } // }
// }); // });
} }
private void createWaveformDropTarget(final Canvas canvas) { private void createWaveformDropTarget(final Canvas canvas) {

View File

@ -41,9 +41,6 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder {
/** The Constant TIME_RES. */ /** The Constant TIME_RES. */
private static final Long TIME_RES = 1000L; // ps private static final Long TIME_RES = 1000L; // ps
/** The db. */
private IWaveformDb db;
/** The module stack. */ /** The module stack. */
private ArrayDeque<String> moduleStack; private ArrayDeque<String> moduleStack;
@ -71,8 +68,8 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public boolean load(IWaveformDb db, File file) throws InputFormatException { public boolean load(IWaveformDb db, File file) throws InputFormatException {
dispose();
if(file.isDirectory() || !file.exists()) return false; if(file.isDirectory() || !file.exists()) return false;
this.db=db;
this.maxTime=0; this.maxTime=0;
boolean res = false; boolean res = false;
try { try {
@ -114,6 +111,11 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder {
return true; return true;
} }
public void dispose() {
moduleStack=null;
signals=null;
}
/* (non-Javadoc) /* (non-Javadoc)
* @see com.minres.scviewer.database.ITrDb#getMaxTime() * @see com.minres.scviewer.database.ITrDb#getMaxTime()
*/ */
@ -159,10 +161,10 @@ public class VCDDbLoader implements IWaveformDbLoader, IVCDDatabaseBuilder {
String netName = moduleStack.isEmpty()? name: moduleStack.peek()+"."+name; String netName = moduleStack.isEmpty()? name: moduleStack.peek()+"."+name;
int id = signals.size(); int id = signals.size();
if(width==0) { if(width==0) {
signals.add( i<0 ? new VCDSignal<DoubleVal>(db, id, netName, width) : signals.add( i<0 ? new VCDSignal<DoubleVal>(id, netName, width) :
new VCDSignal<DoubleVal>((VCDSignal<DoubleVal>)signals.get(i), id, netName)); new VCDSignal<DoubleVal>((VCDSignal<DoubleVal>)signals.get(i), id, netName));
} else if(width>0){ } else if(width>0){
signals.add( i<0 ? new VCDSignal<BitVector>(db, id, netName, width) : signals.add( i<0 ? new VCDSignal<BitVector>(id, netName, width) :
new VCDSignal<BitVector>((VCDSignal<BitVector>)signals.get(i), id, netName)); new VCDSignal<BitVector>((VCDSignal<BitVector>)signals.get(i), id, netName));
} }
return id; return id;

View File

@ -17,7 +17,6 @@ import java.util.TreeMap;
import com.minres.scviewer.database.HierNode; import com.minres.scviewer.database.HierNode;
import com.minres.scviewer.database.IEvent; import com.minres.scviewer.database.IEvent;
import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.IWaveformDb;
import com.minres.scviewer.database.WaveformType; import com.minres.scviewer.database.WaveformType;
public class VCDSignal<T extends IEvent> extends HierNode implements IWaveform { public class VCDSignal<T extends IEvent> extends HierNode implements IWaveform {
@ -28,21 +27,18 @@ public class VCDSignal<T extends IEvent> extends HierNode implements IWaveform {
private final int width; private final int width;
private IWaveformDb db;
private NavigableMap<Long, IEvent[]> values; private NavigableMap<Long, IEvent[]> values;
public VCDSignal(IWaveformDb db, String name) { public VCDSignal(String name) {
this(db, 0, name, 1); this(0, name, 1);
} }
public VCDSignal(IWaveformDb db, int id, String name) { public VCDSignal(int id, String name) {
this(db, id,name,1); this(id,name,1);
} }
public VCDSignal(IWaveformDb db, int id, String name, int width) { public VCDSignal(int id, String name, int width) {
super(name); super(name);
this.db=db;
fullName=name; fullName=name;
this.id=id; this.id=id;
this.width=width; this.width=width;
@ -55,7 +51,6 @@ public class VCDSignal<T extends IEvent> extends HierNode implements IWaveform {
this.id=id; this.id=id;
this.width=o.width; this.width=o.width;
this.values=o.values; this.values=o.values;
this.db=o.getDb();
} }
@Override @Override
@ -72,11 +67,6 @@ public class VCDSignal<T extends IEvent> extends HierNode implements IWaveform {
return id; return id;
} }
@Override
public IWaveformDb getDb() {
return db;
}
public void addSignalChange(Long time, T value){ public void addSignalChange(Long time, T value){
if(values.containsKey(time)) { if(values.containsKey(time)) {
IEvent[] oldV = values.get(time); IEvent[] oldV = values.get(time);

View File

@ -8,5 +8,4 @@
<relativePath>../..</relativePath> <relativePath>../..</relativePath>
</parent> </parent>
<packaging>eclipse-plugin</packaging> <packaging>eclipse-plugin</packaging>
<version>2.0.0-SNAPSHOT</version>
</project> </project>

View File

@ -16,8 +16,6 @@ public interface IWaveform extends IHierNode {
public Long getId(); public Long getId();
public IWaveformDb getDb();
public boolean isSame(IWaveform other); public boolean isSame(IWaveform other);
public NavigableMap<Long, IEvent[]> getEvents(); public NavigableMap<Long, IEvent[]> getEvents();

View File

@ -23,4 +23,5 @@ public interface IWaveformDbLoader {
public Collection<RelationType> getAllRelationTypes() ; public Collection<RelationType> getAllRelationTypes() ;
public void dispose();
} }

View File

@ -10,26 +10,17 @@
*******************************************************************************/ *******************************************************************************/
package com.minres.scviewer.database; package com.minres.scviewer.database;
import java.util.HashMap; import java.io.Serializable;
public class RelationType { public class RelationType implements Serializable {
/**
private static HashMap<String, RelationType> registry = new HashMap<>(); *
*/
private static final long serialVersionUID = 6394859077558971735L;
private String name; private String name;
public static RelationType create(String name){ RelationType(String name) {
if(registry.containsKey(name)){
return registry.get(name);
}else{
RelationType relType = new RelationType(name);
registry.put(name, relType);
return relType;
}
}
private RelationType(String name) {
super(); super();
this.name = name; this.name = name;
} }
@ -53,6 +44,9 @@ public class RelationType {
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
return name.equals(obj); if(obj instanceof RelationType)
return name.equals(((RelationType)obj).name);
else
return false;
} }
} }

View File

@ -0,0 +1,22 @@
package com.minres.scviewer.database;
import java.util.HashMap;
public class RelationTypeFactory {
public static RelationType create(String name){
if(registry.containsKey(name)){
return registry.get(name);
}else{
RelationType relType = new RelationType(name);
registry.put(name, relType);
return relType;
}
}
private RelationTypeFactory() {}
private static HashMap<String, RelationType> registry = new HashMap<>();
}

View File

@ -10,13 +10,10 @@
*******************************************************************************/ *******************************************************************************/
package com.minres.scviewer.database.tx; package com.minres.scviewer.database.tx;
import java.util.List;
import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveform;
public interface ITxGenerator { public interface ITxGenerator {
public Long getId(); public Long getId();
public IWaveform getStream(); public IWaveform getStream();
public String getName(); public String getName();
public List<ITx> getTransactions();
} }

View File

@ -30,6 +30,7 @@ import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Composite;
import com.minres.scviewer.database.RelationType; import com.minres.scviewer.database.RelationType;
import com.minres.scviewer.database.RelationTypeFactory;
import com.minres.scviewer.database.tx.ITx; import com.minres.scviewer.database.tx.ITx;
import com.minres.scviewer.e4.application.Messages; import com.minres.scviewer.e4.application.Messages;
import com.minres.scviewer.e4.application.parts.PartListener; import com.minres.scviewer.e4.application.parts.PartListener;
@ -50,7 +51,7 @@ public class RelationTypeToolControl extends PartListener implements ISelectionC
WaveformViewer waveformViewerPart; WaveformViewer waveformViewerPart;
/** The dummy. */ /** The dummy. */
RelationType dummy = RelationType.create(Messages.RelationTypeToolControl_0); RelationType dummy = RelationTypeFactory.create(Messages.RelationTypeToolControl_0);
/** /**
* Instantiates a new relation type tool control. * Instantiates a new relation type tool control.

View File

@ -13,16 +13,12 @@ import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
import org.eclipse.jface.viewers.ComboViewer; import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider; import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider;
import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT; import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.FillLayout;
@ -88,11 +84,11 @@ public class TransactionList extends Composite {
private IWaveform stream; private IWaveform stream;
private ObservableList<AttributeNameBean> attrNames = new WritableList<AttributeNameBean>(); private ObservableList<AttributeNameBean> attrNames = new WritableList<>();
private List<ITx> eventList = new ArrayList<ITx>(); private List<ITx> eventList = new ArrayList<>();
private List<ITx> emptyList = new ArrayList<ITx>(); private List<ITx> emptyList = new ArrayList<>();
TxFilter txFilter; TxFilter txFilter;
@ -115,6 +111,7 @@ public class TransactionList extends Composite {
searchPropComboViewer = new ComboViewer(this, SWT.NONE); searchPropComboViewer = new ComboViewer(this, SWT.NONE);
searchPropComboViewer.setLabelProvider(new LabelProvider() { searchPropComboViewer.setLabelProvider(new LabelProvider() {
@Override
public String getText(Object element) { public String getText(Object element) {
AttributeNameBean entry = (AttributeNameBean) element; AttributeNameBean entry = (AttributeNameBean) element;
return entry.getName()+" ["+entry.getType().toString()+"]"; return entry.getName()+" ["+entry.getType().toString()+"]";
@ -123,20 +120,19 @@ public class TransactionList extends Composite {
searchPropComboViewer.setContentProvider(new ObservableListContentProvider<AttributeNameBean>()); searchPropComboViewer.setContentProvider(new ObservableListContentProvider<AttributeNameBean>());
searchPropComboViewer.setInput(attrNames); searchPropComboViewer.setInput(attrNames);
Combo searchPropCombo = searchPropComboViewer.getCombo(); Combo searchPropCombo = searchPropComboViewer.getCombo();
GridData gd_searchProp = new GridData(SWT.LEFT, SWT.FILL, false, false, 1, 1); GridData gdSearchProp = new GridData(SWT.LEFT, SWT.FILL, false, false, 1, 1);
gd_searchProp.widthHint=100; gdSearchProp.widthHint=100;
searchPropCombo.setLayoutData(gd_searchProp); searchPropCombo.setLayoutData(gdSearchProp);
searchPropCombo.addSelectionListener(new SelectionListener() { searchPropCombo.addSelectionListener(new SelectionListener() {
@Override @Override
public void widgetSelected(SelectionEvent e) { public void widgetSelected(SelectionEvent e) {
int idx = searchPropCombo.getSelectionIndex(); extracted(searchPropCombo);
if(idx<0) return;
AttributeNameBean sel = attrNames.get(idx);
txFilter.setSearchProp(sel.getName(), sel.getType());
tableViewer.refresh();
} }
@Override @Override
public void widgetDefaultSelected(SelectionEvent e) { public void widgetDefaultSelected(SelectionEvent e) {
extracted(searchPropCombo);
}
private void extracted(Combo searchPropCombo) {
int idx = searchPropCombo.getSelectionIndex(); int idx = searchPropCombo.getSelectionIndex();
if(idx<0) return; if(idx<0) return;
AttributeNameBean sel = attrNames.get(idx); AttributeNameBean sel = attrNames.get(idx);
@ -146,15 +142,12 @@ public class TransactionList extends Composite {
}); });
searchPropValue = new Text(this, SWT.BORDER); searchPropValue = new Text(this, SWT.BORDER);
GridData gd_searchPropValue = new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1); GridData gdSearchPropValue = new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1);
gd_searchPropValue.minimumWidth = 50; gdSearchPropValue.minimumWidth = 50;
searchPropValue.setLayoutData(gd_searchPropValue); searchPropValue.setLayoutData(gdSearchPropValue);
searchPropValue.addModifyListener(new ModifyListener() { searchPropValue.addModifyListener(e -> {
@Override
public void modifyText(ModifyEvent e) {
txFilter.setSearchValue(((Text) e.widget).getText()); txFilter.setSearchValue(((Text) e.widget).getText());
tableViewer.refresh(); tableViewer.refresh();
}
}); });
Label lbl2 = new Label(this, SWT.NONE); Label lbl2 = new Label(this, SWT.NONE);
@ -164,6 +157,7 @@ public class TransactionList extends Composite {
viewPropComboViewer = new ComboViewer(this, SWT.NONE); viewPropComboViewer = new ComboViewer(this, SWT.NONE);
viewPropComboViewer.setLabelProvider(new LabelProvider() { viewPropComboViewer.setLabelProvider(new LabelProvider() {
@Override
public String getText(Object element) { public String getText(Object element) {
AttributeNameBean entry = (AttributeNameBean) element; AttributeNameBean entry = (AttributeNameBean) element;
return entry.getName()+" ["+entry.getType().toString()+"]"; return entry.getName()+" ["+entry.getType().toString()+"]";
@ -172,9 +166,9 @@ public class TransactionList extends Composite {
viewPropComboViewer.setContentProvider(new ObservableListContentProvider<AttributeNameBean>()); viewPropComboViewer.setContentProvider(new ObservableListContentProvider<AttributeNameBean>());
viewPropComboViewer.setInput(attrNames); viewPropComboViewer.setInput(attrNames);
Combo viewPropCombo = viewPropComboViewer.getCombo(); Combo viewPropCombo = viewPropComboViewer.getCombo();
GridData gd_viewProp = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); GridData gdviewProp = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
gd_viewProp.widthHint=100; gdviewProp.widthHint=100;
viewPropCombo.setLayoutData(gd_viewProp); viewPropCombo.setLayoutData(gdviewProp);
viewPropCombo.addSelectionListener(new SelectionListener() { viewPropCombo.addSelectionListener(new SelectionListener() {
@Override @Override
public void widgetSelected(SelectionEvent e) { public void widgetSelected(SelectionEvent e) {
@ -184,7 +178,7 @@ public class TransactionList extends Composite {
tableViewer.refresh(true); tableViewer.refresh(true);
} }
@Override @Override
public void widgetDefaultSelected(SelectionEvent e) { } public void widgetDefaultSelected(SelectionEvent e) { /* do nothing */ }
}); });
tableViewer = new TableViewer(this); tableViewer = new TableViewer(this);
@ -200,9 +194,7 @@ public class TransactionList extends Composite {
} }
}); });
tableViewer.addFilter(txFilter); tableViewer.addFilter(txFilter);
tableViewer.addSelectionChangedListener(new ISelectionChangedListener() { tableViewer.addSelectionChangedListener(event -> {
@Override
public void selectionChanged(SelectionChangedEvent event) {
ISelection treeSelection = event.getSelection(); ISelection treeSelection = event.getSelection();
if(treeSelection instanceof IStructuredSelection) { if(treeSelection instanceof IStructuredSelection) {
Object selected = ((IStructuredSelection)treeSelection).getFirstElement(); Object selected = ((IStructuredSelection)treeSelection).getFirstElement();
@ -212,7 +204,6 @@ public class TransactionList extends Composite {
waveformViewer.setSelection(new StructuredSelection(((TransactionTreeNode)selected).element)); waveformViewer.setSelection(new StructuredSelection(((TransactionTreeNode)selected).element));
} }
} }
}
}); });
Table table = tableViewer.getTable(); Table table = tableViewer.getTable();
@ -250,11 +241,11 @@ public class TransactionList extends Composite {
if(trackEntry==null || trackEntry.waveform.getType()!=WaveformType.TRANSACTION) { if(trackEntry==null || trackEntry.waveform.getType()!=WaveformType.TRANSACTION) {
attrNames.clear(); attrNames.clear();
tableViewer.setInput(emptyList); tableViewer.setInput(emptyList);
} else { } else if(stream != trackEntry.waveform) {
stream=trackEntry.waveform; stream=trackEntry.waveform;
tableViewer.setInput(emptyList); tableViewer.setInput(emptyList);
new Thread() { new Thread() {
private ConcurrentHashMap<String, DataType> propNames=new ConcurrentHashMap<String, DataType>(); private ConcurrentHashMap<String, DataType> propNames=new ConcurrentHashMap<>();
private List<AttributeNameBean> getEntries() { private List<AttributeNameBean> getEntries() {
return propNames.entrySet().stream() return propNames.entrySet().stream()
@ -263,11 +254,12 @@ public class TransactionList extends Composite {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
@Override
public void run() { public void run() {
Collection<IEvent[]> values = stream.getEvents().values(); Collection<IEvent[]> values = stream.getEvents().values();
eventList = values.parallelStream().map(Arrays::asList) eventList = values.parallelStream().map(Arrays::asList)
.flatMap(List::stream) .flatMap(List::stream)
.filter(evt -> evt.getKind()==EventKind.BEGIN) .filter(evt -> evt.getKind()==EventKind.BEGIN || evt.getKind()==EventKind.SINGLE)
.map(evt-> { .map(evt-> {
ITx tx = ((ITxEvent)evt).getTransaction(); ITx tx = ((ITxEvent)evt).getTransaction();
for(ITxAttribute attr: tx.getAttributes()) { for(ITxAttribute attr: tx.getAttributes()) {
@ -283,17 +275,18 @@ public class TransactionList extends Composite {
tableViewer.setInput(eventList); tableViewer.setInput(eventList);
attrNames.clear(); attrNames.clear();
attrNames.addAll(getEntries()); attrNames.addAll(getEntries());
if(attrNames.size()>0) if(!attrNames.isEmpty())
txFilter.setSearchProp(attrNames.get(0).getName(), attrNames.get(0).getType()); txFilter.setSearchProp(attrNames.get(0).getName(), attrNames.get(0).getType());
if (searchPropComboViewer!=null) { if (searchPropComboViewer!=null) {
searchPropComboViewer.setInput(attrNames); searchPropComboViewer.setInput(attrNames);
searchPropComboViewer.setSelection(new StructuredSelection(searchPropComboViewer.getElementAt(0))); Object sel = searchPropComboViewer.getElementAt(0);
if(sel!=null) searchPropComboViewer.setSelection(new StructuredSelection(sel));
} }
tableViewer.refresh(true); tableViewer.refresh(true);
} }
}); });
} }
}.run(); }.start();
} }
} }

View File

@ -87,6 +87,7 @@ import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.IWaveformDb; import com.minres.scviewer.database.IWaveformDb;
import com.minres.scviewer.database.IWaveformDbFactory; import com.minres.scviewer.database.IWaveformDbFactory;
import com.minres.scviewer.database.RelationType; import com.minres.scviewer.database.RelationType;
import com.minres.scviewer.database.RelationTypeFactory;
import com.minres.scviewer.database.tx.ITx; import com.minres.scviewer.database.tx.ITx;
import com.minres.scviewer.database.tx.ITxAttribute; import com.minres.scviewer.database.tx.ITxAttribute;
import com.minres.scviewer.database.tx.ITxEvent; import com.minres.scviewer.database.tx.ITxEvent;
@ -1237,7 +1238,7 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis
* @param relationName the new navigation relation type * @param relationName the new navigation relation type
*/ */
public void setNavigationRelationType(String relationName) { public void setNavigationRelationType(String relationName) {
setNavigationRelationType(RelationType.create(relationName)); setNavigationRelationType(RelationTypeFactory.create(relationName));
} }
/** /**

View File

@ -3,5 +3,6 @@
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src/"/> <classpathentry kind="src" path="src/"/>
<classpathentry kind="con" path="GROOVY_DSL_SUPPORT"/>
<classpathentry kind="output" path="target/classes"/> <classpathentry kind="output" path="target/classes"/>
</classpath> </classpath>

View File

@ -2,3 +2,11 @@
/.my_db.txlog* /.my_db.txlog*
/EyeQ6_mem_platform.txlog /EyeQ6_mem_platform.txlog
/EyeQ6_mem_platform.vcd /EyeQ6_mem_platform.vcd
/hw_cfg7.txlog
/hw_cfg7.vcd
/hw_cfg_2_gen.txlog
/hw_cfg_2_gen.vcd
/hw_cfg_2_nc.txlog
/hw_cfg_2_nc.vcd
/test_05.txlog
/test_05.vcd

View File

@ -93,8 +93,18 @@ public class DatabaseServicesTest {
assertTrue(f.exists()); assertTrue(f.exists());
waveformDb.load(f); waveformDb.load(f);
assertNotNull(waveformDb); assertNotNull(waveformDb);
assertEquals(3, waveformDb.getAllWaves().size()); List<IWaveform> waveforms = waveformDb.getAllWaves();
assertEquals(3, waveforms.size());
assertEquals(1, waveformDb.getChildNodes().size()); assertEquals(1, waveformDb.getChildNodes().size());
for(IWaveform w:waveforms) {
if(w.getId().equals(1l)) {
assertEquals(2, w.getWidth());
} else if(w.getId().equals(2l)) {
assertEquals(1, w.getWidth());
} else if(w.getId().equals(3l)) {
assertEquals(1, w.getWidth());
}
}
} }
@Test @Test