refactor internal transaction representation

This commit is contained in:
Eyck Jentzsch 2021-01-03 14:16:56 +01:00
parent b44f3418f4
commit 85ce07f11f
15 changed files with 373 additions and 287 deletions

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

@ -11,7 +11,6 @@
package com.minres.scviewer.database.text;
import java.io.BufferedReader;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@ -21,69 +20,72 @@ 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.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import org.mapdb.BTreeMap;
import org.mapdb.DB;
import org.mapdb.DB.TreeMapSink;
import org.mapdb.DBMaker;
import org.mapdb.Serializer;
import org.mapdb.serializer.SerializerArrayTuple;
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.tx.ITxGenerator;
import com.minres.scviewer.database.tx.ITx;
import com.minres.scviewer.database.tx.ITxAttributeType;
public class TextDbLoader implements IWaveformDbLoader{
private Long maxTime=0L;
IWaveformDb db;
List<IWaveform> streams;
Map<String, RelationType> relationTypes=new HashMap<String, RelationType>();
DB mapDb;
TreeMap<Long, TxStream> txStreams;
TreeMap<Long, TxGenerator> txGenerators;
BTreeMap<Long, ScvTx> transactions;
BTreeMap<Long[], ScvRelation> relations;
public TextDbLoader() {
}
BTreeMap<String[], TxAttributeType> attributeTypes;
@Override
HashMap<Long, Tx> txCache = new HashMap<>();
@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>();
for(IWaveform stream: streams){ for(ITxGenerator it: ((TxStream)stream).getGenerators()){res.put(it.getId(), it);} }
return res;
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 {
if(file.isDirectory() || !file.exists()) return false;
this.db=db;
this.streams = new ArrayList<>();
TextDbParser parser = new TextDbParser(this);
boolean gzipped = isGzipped(file);
try {
if(!isTxfile(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file)))
return false;
} catch(Throwable e) {
} catch(Exception e) {
throw new InputFormatException();
}
File mapDbFile;
@ -94,7 +96,7 @@ public class TextDbLoader implements IWaveformDbLoader{
}
mapDbFile.delete(); // we just need a file name
mapDbFile.deleteOnExit();
this.mapDb = DBMaker
mapDb = DBMaker
.fileDB(mapDbFile)
.fileMmapEnableIfSupported()
.fileMmapPreclearDisable()
@ -102,15 +104,26 @@ public class TextDbLoader implements IWaveformDbLoader{
.allocateStartSize(64*1024*1024)
.allocateIncrement(64*1024*1024)
.make();
TreeMapSink<Long, ScvTx> txSink = mapDb.treeMap("transactions", Serializer.LONG,Serializer.JAVA).createFromSink();
relations = mapDb
.treeMap("relations", new SerializerArrayTuple(Serializer.LONG, Serializer.LONG) ,Serializer.JAVA)
.createOrOpen();
attributeTypes = mapDb
.treeMap("attributeTypes", new SerializerArrayTuple(Serializer.STRING, Serializer.STRING) ,Serializer.JAVA)
.createOrOpen();
try {
parser.parseInput(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file));
parser.setTransactionSink(txSink).setRelationMap(relations);
parser.parseInput(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file));
} catch(IllegalArgumentException|ArrayIndexOutOfBoundsException e) {
} catch(Throwable e) {
} catch(Exception e) {
System.out.println("---->>> Exception "+e.toString()+" caught while loading database");
e.printStackTrace();
return false;
}
streams.addAll(parser.streamsById.values());
transactions=txSink.create();
txStreams=new TreeMap<>(parser.streamsById);
txGenerators=new TreeMap<>(parser.generatorsById);
txCache.clear();
return true;
}
@ -149,20 +162,37 @@ public class TextDbLoader implements IWaveformDbLoader{
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 \"([^\"]+)\"\\)$");
HashMap<Long, TxStream> streamsById = new HashMap<Long, TxStream>();
HashMap<Long, TxGenerator> generatorsById = new HashMap<Long, TxGenerator>();
HashMap<Long, Tx> transactionsById = new HashMap<Long, Tx>();
TxGenerator generator = null;
Tx transaction = null;
boolean endTransaction=false;
HashMap<Long, TxStream> streamsById = new HashMap<>();
HashMap<Long, TxGenerator> generatorsById = new HashMap<>();
HashMap<Long, ScvTx> transactionsById = new HashMap<>();
final TextDbLoader loader;
BufferedReader reader =null;
BufferedReader reader = null;
TxGenerator generator = null;
private TreeMapSink<Long, ScvTx> txSink;
private BTreeMap<Long[], ScvRelation> relations;
public TextDbParser(TextDbLoader loader) {
super();
this.loader = loader;
}
public TextDbParser setTransactionSink(TreeMapSink<Long, ScvTx> sink) {
this.txSink=sink;
return this;
}
public TextDbParser setRelationMap(BTreeMap<Long[], ScvRelation> relations) {
this.relations=relations;
return this;
}
void parseInput(InputStream inputStream) throws IOException{
reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
String curLine = reader.readLine();
@ -174,6 +204,18 @@ public class TextDbLoader implements IWaveformDbLoader{
parseLine(curLine, nextLine);
}
private TxAttributeType getAttrType(String name, DataType dataType, AssociationType type){
String[] key = new String[] {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])){//matcher = line =~ /^tx_record_attribute\s+(\d+)\s+"([^"]+)"\s+(\S+)\s*=\s*(.+)$/
@ -181,54 +223,62 @@ public class TextDbLoader implements IWaveformDbLoader{
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-1)):"";
transactionsById.get(id).getAttributes().add(new TxAttribute(name, type, AssociationType.RECORD, remaining));
TxAttributeType attrType = getAttrType(name, type, AssociationType.RECORD);
transactionsById.get(id).attributes.add(new TxAttribute(attrType, remaining));
} else if("tx_begin".equals(tokens[0])){
Long id = Long.parseLong(tokens[1]);
TxGenerator gen=generatorsById.get(Long.parseLong(tokens[2]));
TxStream stream = (TxStream) gen.getStream();
Long genId = Long.parseLong(tokens[2]);
TxGenerator gen=generatorsById.get(genId);
ScvTx tx = new ScvTx(id, gen.stream.getId(), genId, Long.parseLong(tokens[3])*stringToScale(tokens[4]));
transactionsById.put(id, tx);
loader.maxTime = loader.maxTime>tx.beginTime?loader.maxTime:tx.beginTime;
TxStream stream = streamsById.get(gen.stream.getId());
stream.setConcurrency(stream.getConcurrency()+1);
transaction = new Tx(id, gen.getStream(), gen, Long.parseLong(tokens[3])*stringToScale(tokens[4]));
gen.getTransactions().add(transaction);
transactionsById.put(id, transaction);
loader.maxTime = loader.maxTime>transaction.getBeginTime()?loader.maxTime:transaction.getBeginTime();
if(nextLine!=null && nextLine.charAt(0)=='a') {
int idx=0;
while(nextLine!=null && nextLine.charAt(0)=='a') {
String[] attrTokens=nextLine.split("\\s+");
TxAttribute attr = new TxAttribute(gen.getBeginAttrs().get(idx), attrTokens[1]);
transaction.getAttributes().add(attr);
TxAttribute attr = new TxAttribute(gen.beginAttrs.get(idx), attrTokens[1]);
tx.attributes.add(attr);
idx++;
nextLine=reader.readLine();
}
}
txSink.put(tx.id, tx);
} else if("tx_end".equals(tokens[0])){//matcher = line =~ /^tx_end\s+(\d+)\s+(\d+)\s+(\d+)\s+([munpf]?s)/
Long id = Long.parseLong(tokens[1]);
transaction = transactionsById.get(id);
assert Integer.parseInt(tokens[2])==transaction.getGenerator().getId();
transaction.setEndTime(Long.parseLong(tokens[3])*stringToScale(tokens[4]));
loader.maxTime = loader.maxTime>transaction.getEndTime()?loader.maxTime:transaction.getEndTime();
TxGenerator gen = (TxGenerator) transaction.getGenerator();
TxStream stream = (TxStream) gen.getStream();
ScvTx tx = transactionsById.get(id);
assert Long.parseLong(tokens[2])==tx.generatorId;
tx.endTime=Long.parseLong(tokens[3])*stringToScale(tokens[4]);
loader.maxTime = loader.maxTime>tx.endTime?loader.maxTime:tx.endTime;
TxGenerator gen = generatorsById.get(tx.generatorId);
TxStream stream = streamsById.get(gen.stream.getId());
if(tx.beginTime==tx.endTime)
stream.addEvent(new TxEvent(loader, EventKind.SINGLE, id, tx.beginTime));
else {
stream.addEvent(new TxEvent(loader, EventKind.BEGIN, id, tx.beginTime));
stream.addEvent(new TxEvent(loader, EventKind.END, id, tx.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+");
TxAttribute attr = new TxAttribute(gen.getEndAttrs().get(idx), attrTokens[1]);
transaction.getAttributes().add(attr);
TxAttribute attr = new TxAttribute(gen.endAttrs.get(idx), attrTokens[1]);
tx.attributes.add(attr);
idx++;
nextLine=reader.readLine();
}
}
transactionsById.remove(tx.id);
} else if("tx_relation".equals(tokens[0])){//matcher = line =~ /^tx_relation\s+\"(\S+)\"\s+(\d+)\s+(\d+)$/
Tx tr2= transactionsById.get(Long.parseLong(tokens[2]));
Tx tr1= transactionsById.get(Long.parseLong(tokens[3]));
Long tr2= Long.parseLong(tokens[2]);
Long tr1= Long.parseLong(tokens[3]);
String relType=tokens[1].substring(1, tokens[1].length()-2);
if(!loader.relationTypes.containsKey(relType))
loader.relationTypes.put(relType, RelationType.create(relType));
TxRelation rel = new TxRelation(loader.relationTypes.get(relType), tr1, tr2);
tr1.getOutgoingRelations().add(rel);
tr2.getIncomingRelations().add(rel);
ScvRelation rel = new ScvRelation(loader.relationTypes.get(relType), tr1, tr2);
relations.put(new Long[]{tr1, tr2}, rel);
} else if("scv_tr_stream".equals(tokens[0])){
Matcher matcher = scv_tr_stream.matcher(curLine);
if (matcher.matches()) {
@ -242,18 +292,19 @@ public class TextDbLoader implements IWaveformDbLoader{
Long id = Long.parseLong(matcher.group(1));
TxStream stream=streamsById.get(Long.parseLong(matcher.group(3)));
generator=new TxGenerator(id, stream, matcher.group(2));
stream.getGenerators().add(generator);
generatorsById.put(id, generator);
}
} else if("begin_attribute".equals(tokens[0])){
Matcher matcher = begin_attribute.matcher(curLine);
if ((matcher.matches())) {
generator.getBeginAttrs().add(TxAttributeType.getAttrType(matcher.group(2), DataType.valueOf(matcher.group(3)), AssociationType.BEGIN));
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())) {
generator.getEndAttrs().add(TxAttributeType.getAttrType(matcher.group(2), DataType.valueOf(matcher.group(3)), AssociationType.END));
TxAttributeType attrType = getAttrType(matcher.group(2), DataType.valueOf(matcher.group(3)), AssociationType.END);
generator.endAttrs.add(attrType);
}
} else if(")".equals(tokens[0])){
generator=null;
@ -275,5 +326,13 @@ public class TextDbLoader implements IWaveformDbLoader{
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

@ -10,67 +10,49 @@
*******************************************************************************/
package com.minres.scviewer.database.text;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.NavigableMap;
import java.util.stream.Collectors;
import com.minres.scviewer.database.*;
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, Serializable{
class Tx implements ITx {
/**
*
*/
private static final long serialVersionUID = -855200240003328221L;
private final Long id;
private final TextDbLoader loader;
private final TxGenerator generator;
private final IWaveform stream;
private ScvTx scvTx = null;
private int concurrencyIndex;
private final Long beginTime;
private Long endTime;
private final List<ITxAttribute> attributes = new ArrayList<>();
private final List<ITxRelation> incomingRelations = new ArrayList<>();
private final List<ITxRelation> outgoingRelations = new ArrayList<>();
Tx(Long id, IWaveform stream, TxGenerator generator, Long begin){
this.id=id;
this.stream=stream;
this.generator=generator;
this.beginTime=begin;
this.endTime=begin;
Tx(TextDbLoader loader, Long id){
this.loader=loader;
this.scvTx = loader.transactions.get(id);
}
@Override
public Collection<ITxRelation> getIncomingRelations() {
return incomingRelations;
NavigableMap<Long[], ScvRelation> rels = loader.relations.prefixSubMap(new Long[]{scvTx.getId(), null});
return rels.values().stream().map(rel -> new TxRelation(loader, rel)).collect(Collectors.toList());
}
@Override
public Collection<ITxRelation> getOutgoingRelations() {
return outgoingRelations;
NavigableMap<Long[], ScvRelation> rels = loader.relations.prefixSubMap(new Long[]{null, scvTx.getId()});
return rels.values().stream().map(rel -> new TxRelation(loader, rel)).collect(Collectors.toList());
}
@Override
public int compareTo(ITx o) {
int res =beginTime.compareTo(o.getBeginTime());
int res =getBeginTime().compareTo(o.getBeginTime());
if(res!=0)
return res;
else
return id.compareTo(o.getId());
return getId().compareTo(o.getId());
}
@Override
@ -80,31 +62,27 @@ class Tx implements ITx, Serializable{
@Override
public Long getId() {
return id;
return scvTx.id;
}
@Override
public IWaveform getStream() {
return stream;
return loader.txStreams.get(scvTx.streamId);
}
@Override
public ITxGenerator getGenerator() {
return generator;
return loader.txGenerators.get(scvTx.generatorId);
}
@Override
public Long getBeginTime() {
return beginTime;
return scvTx.beginTime;
}
@Override
public Long getEndTime() {
return endTime;
}
public void setEndTime(long l) {
endTime=l;
return scvTx.endTime;
}
@Override
@ -118,7 +96,7 @@ class Tx implements ITx, Serializable{
@Override
public List<ITxAttribute> getAttributes() {
return attributes;
return scvTx.attributes;
}
}

View File

@ -15,7 +15,6 @@ import java.io.Serializable;
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;
public class TxAttribute implements ITxAttribute, Serializable {
@ -24,28 +23,24 @@ public class TxAttribute implements ITxAttribute, Serializable {
*/
private static final long serialVersionUID = 4767726016651807152L;
ITxAttributeType attributeType;
private TxAttributeType attributeType;
String value;
private String value=null;
TxAttribute(String name, DataType dataType, AssociationType type, String value){
attributeType = TxAttributeTypeFactory.INSTANCE.getAttrType(name, dataType, type);
switch(dataType){
case STRING:
case ENUMERATION:
this.value=value.substring(1, value.length()-2);
break;
default:
this.value=value;
}
TxAttribute(TxAttributeType attributeType){
this.attributeType=attributeType;
}
TxAttribute(ITxAttributeType type){
TxAttribute(TxAttributeType type, String value){
attributeType=type;
}
TxAttribute(ITxAttributeType type, String value){
this(type.getName(), type.getDataType(), type.getType(), value);
switch(type.getDataType()){
case STRING:
case ENUMERATION:
this.value=value.substring(1, value.length()-2);
break;
default:
this.value=value;
}
}
@Override

View File

@ -28,10 +28,6 @@ class TxAttributeType implements ITxAttributeType, Serializable {
private AssociationType type;
static ITxAttributeType getAttrType(String name, DataType dataType, AssociationType type){
return TxAttributeTypeFactory.INSTANCE.getAttrType(name, dataType, type);
}
TxAttributeType(String name, DataType dataType, AssociationType type){
this.name=name;
this.dataType=dataType;

View File

@ -1,37 +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.HashMap;
import com.minres.scviewer.database.AssociationType;
import com.minres.scviewer.database.DataType;
import com.minres.scviewer.database.tx.ITxAttributeType;
public class TxAttributeTypeFactory {
public static final TxAttributeTypeFactory INSTANCE = new TxAttributeTypeFactory();
HashMap<String, ITxAttributeType> attributes = new HashMap<>();
private TxAttributeTypeFactory() {}
ITxAttributeType getAttrType(String name, DataType dataType, AssociationType type){
String key = name+":"+dataType.toString();
ITxAttributeType res;
if(attributes.containsKey(key)){
res=attributes.get(key);
} else {
res=new TxAttributeType(name, dataType, type);
attributes.put(key, res);
}
return res;
}
}

View File

@ -1,34 +1,22 @@
package com.minres.scviewer.database.text;
import java.io.Serializable;
import com.minres.scviewer.database.EventKind;
import com.minres.scviewer.database.WaveformType;
import com.minres.scviewer.database.tx.ITx;
import com.minres.scviewer.database.tx.ITxEvent;
class TxEvent implements ITxEvent, Serializable {
/**
*
*/
private static final long serialVersionUID = 4481575593229248159L;
class TxEvent implements ITxEvent {
final TextDbLoader loader;
final EventKind kind;
final ITx transaction;
final Long transaction;
final Long time;
TxEvent(EventKind kind, ITx transaction) {
super();
this.kind = kind;
this.transaction = transaction;
this.time = kind==EventKind.BEGIN?transaction.getBeginTime():transaction.getEndTime();
}
public TxEvent(EventKind kind, ITx transaction, Long time) {
super();
TxEvent(TextDbLoader loader, EventKind kind, Long transaction, Long time) {
this.loader=loader;
this.kind = kind;
this.transaction = transaction;
this.time = time;
@ -37,13 +25,13 @@ class TxEvent implements ITxEvent, Serializable {
@Override
public
ITxEvent duplicate() throws CloneNotSupportedException {
return new TxEvent(kind, transaction, time);
return new TxEvent(loader, kind, transaction, time);
}
@Override
public
String toString() {
return kind.toString()+"@"+time+" of tx #"+transaction.getId();
return kind.toString()+"@"+time+" of tx #"+transaction;
}
@Override
@ -63,6 +51,6 @@ class TxEvent implements ITxEvent, Serializable {
@Override
public ITx getTransaction() {
return transaction;
return loader.getTransaction(transaction);
}
}

View File

@ -35,9 +35,9 @@ class TxGenerator implements ITxGenerator, Serializable{
ArrayList<ITx> transactions=new ArrayList<ITx>();
ArrayList<ITxAttributeType> beginAttrs = new ArrayList<ITxAttributeType>();
ArrayList<TxAttributeType> beginAttrs = new ArrayList<>();
ArrayList<ITxAttributeType> endAttrs= new ArrayList<ITxAttributeType>();
ArrayList<TxAttributeType> endAttrs= new ArrayList<>();
TxGenerator(Long id, TxStream stream, String name){
this.id=id;
@ -45,32 +45,34 @@ class TxGenerator implements ITxGenerator, Serializable{
this.name=name;
}
public IWaveform getStream(){
return stream;
}
public List<ITx> getTransactions(){
return transactions;
}
Boolean isActive() {return active;}
@Override
public Long getId() {
return id;
}
@Override
public IWaveform getStream(){
return stream;
}
@Override
public String getName() {
return name;
}
public ArrayList<ITxAttributeType> getBeginAttrs() {
@Override
public List<ITx> getTransactions(){
return transactions;
}
public List<TxAttributeType> getBeginAttrs() {
return beginAttrs;
}
public ArrayList<ITxAttributeType> getEndAttrs() {
public List<TxAttributeType> getEndAttrs() {
return endAttrs;
}
Boolean isActive() {return active;}
}

View File

@ -12,31 +12,28 @@ class TxRelation implements ITxRelation, Serializable {
*/
private static final long serialVersionUID = -347668857680574140L;
final Tx source;
final TextDbLoader loader;
final Tx target;
final ScvRelation scvRelation;
final RelationType relationType;
public TxRelation(RelationType relationType, Tx source, Tx target) {
this.source = source;
this.target = target;
this.relationType = relationType;
public TxRelation(TextDbLoader loader, ScvRelation scvRelation) {
this.loader = loader;
this.scvRelation = scvRelation;
}
@Override
public RelationType getRelationType() {
return relationType;
return scvRelation.relationType;
}
@Override
public ITx getSource() {
return source;
return loader.getTransaction(scvRelation.source);
}
@Override
public ITx getTarget() {
return target;
return loader.getTransaction(scvRelation.target);
}
}

View File

@ -10,40 +10,32 @@
*******************************************************************************/
package com.minres.scviewer.database.text;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map.Entry;
import java.util.NavigableMap;
import org.mapdb.BTreeMap;
import org.mapdb.Serializer;
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.ITx;
import com.minres.scviewer.database.tx.ITxEvent;
import com.minres.scviewer.database.tx.ITxGenerator;
class TxStream extends HierNode implements IWaveform, Serializable {
/**
*
*/
private static final long serialVersionUID = 6721893017334753858L;
class TxStream extends HierNode implements IWaveform {
private Long id;
private ArrayList<ITxGenerator> generators = new ArrayList<ITxGenerator>();
private TextDbLoader loader;
private int maxConcurrency = 0;
private int concurrency = 0;
boolean concurrencyCalculated = false;
void setConcurrency(int concurrency) {
this.concurrency = concurrency;
if(concurrency>maxConcurrency)
@ -54,19 +46,16 @@ class TxStream extends HierNode implements IWaveform, Serializable {
return this.concurrency;
}
private BTreeMap<Long, IEvent[]> events;
TreeMap<Long, IEvent[]> events = new TreeMap<>();
@SuppressWarnings("unchecked")
TxStream(TextDbLoader loader, Long id, String name, String kind){
super(name);
this.id=id;
this.maxConcurrency=0;
//events = new TreeMap<Long, List<ITxEvent>>()
events = (BTreeMap<Long, IEvent[]>) loader.mapDb.treeMap(name).keySerializer(Serializer.LONG).createOrOpen();
this.loader=loader;
}
List<ITxGenerator> getGenerators(){
return generators;
return new ArrayList<>(loader.txGenerators.values());
}
@Override
@ -74,13 +63,26 @@ class TxStream extends HierNode implements IWaveform, Serializable {
return maxConcurrency;
}
public void addEvent(TxEvent evt) {
if(!events.containsKey(evt.time))
events.put(evt.time, new IEvent[] {evt});
else {
IEvent[] evts = events.get(evt.time);
IEvent[] newEvts = Arrays.copyOf(evts, evts.length+1);
newEvts[evts.length]=evt;
events.put(evt.time, newEvts);
}
}
@Override
public NavigableMap<Long, IEvent[]> getEvents() {
if(!concurrencyCalculated) calculateConcurrency();
return (NavigableMap<Long, IEvent[]>)events;
}
@Override
public IEvent[] getEventsAtTime(Long time) {
if(!concurrencyCalculated) calculateConcurrency();
return events.get(time);
}
@ -91,6 +93,7 @@ class TxStream extends HierNode implements IWaveform, Serializable {
@Override
public IEvent[] getEventsBeforeTime(Long time) {
if(!concurrencyCalculated) calculateConcurrency();
Entry<Long, IEvent[]> e = events.floorEntry(time);
if(e==null)
return null;
@ -108,4 +111,22 @@ class TxStream extends HierNode implements IWaveform, Serializable {
return id;
}
private void calculateConcurrency() {
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

@ -84,17 +84,20 @@ public class StreamPainter extends TrackPainter{
NavigableMap<Long, IEvent[]> entries = stream.getEvents().subMap(firstTx.getKey(), true, lastTx.getKey(), true);
boolean highlighed=false;
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(IEvent evt:entry.getValue()){
ITxEvent txEvent = (ITxEvent) evt;
if(txEvent.getKind()==EventKind.BEGIN)
seenTx.add(txEvent.getTransaction());
if(txEvent.getKind()==EventKind.END){
ITx tx = txEvent.getTransaction();
highlighed|=waveCanvas.currentSelection!=null && waveCanvas.currentSelection.equals(tx);
drawTx(proj, area, tx, false);
ITx tx = ((ITxEvent) evt).getTransaction();
highlighed|=selectedId==tx.getId();
switch(evt.getKind()) {
case BEGIN:
seenTx.add(tx);
break;
case END:
seenTx.remove(tx);
case SINGLE:
drawTx(proj, area, tx, false);
break;
}
}
for(ITx tx:seenTx){

View File

@ -116,9 +116,9 @@ public class WaveformView implements IWaveformView {
final WaveformCanvas waveformCanvas;
final ToolTipHandler toolTipHandler;
private boolean revealSelected=false;
private Composite top;
protected ObservableList<TrackEntry> streams;
@ -128,13 +128,13 @@ public class WaveformView implements IWaveformView {
private int tracksVerticalHeight;
private TreeMap<Integer, TrackEntry> trackVerticalOffset;
private IWaveformStyleProvider styleProvider;
protected TrackEntry lastClickedEntry;
protected MouseListener nameValueMouseListener = new MouseAdapter() {
@Override
public void mouseDown(MouseEvent e) {
if (e.button == 1) {
@ -146,7 +146,7 @@ public class WaveformView implements IWaveformView {
if(topMenu!=null) topMenu.setVisible(true);
}
}
@Override
public void mouseUp(MouseEvent e) {
if (e.button == 1) {
@ -168,7 +168,7 @@ public class WaveformView implements IWaveformView {
}
}
};
class WaveformMouseListener implements PaintListener, Listener {
Point start;
Point end;
@ -178,13 +178,13 @@ public class WaveformView implements IWaveformView {
@Override
public void paintControl(PaintEvent e) {
if(down) {
GC gc = e.gc;
gc.setAlpha(128);
int minX = Math.min(start.x, end.x);
int width = Math.max(start.x, end.x) - minX;
int yTop = waveformCanvas.getRulerHeight();
int yBottom = waveformCanvas.getSize().y;
gc.fillRectangle(minX, yTop, width,yBottom);
GC gc = e.gc;
gc.setAlpha(128);
int minX = Math.min(start.x, end.x);
int width = Math.max(start.x, end.x) - minX;
int yTop = waveformCanvas.getRulerHeight();
int yBottom = waveformCanvas.getSize().y;
gc.fillRectangle(minX, yTop, width,yBottom);
}
}
@ -243,7 +243,7 @@ public class WaveformView implements IWaveformView {
asyncUpdate(e.widget);
}
}
protected long snapOffsetToEvent(Point p) {
long time= waveformCanvas.getTimeForOffset(p.x);
long scaling=5*waveformCanvas.getScaleFactor();
@ -304,7 +304,7 @@ public class WaveformView implements IWaveformView {
default:
break;
}
}
}
@ -312,7 +312,7 @@ public class WaveformView implements IWaveformView {
public WaveformView(Composite parent, IWaveformStyleProvider styleProvider) {
this.styleProvider=styleProvider;
pcs=new PropertyChangeSupport(this);
trackVerticalOffset = new TreeMap<>();
@ -326,7 +326,7 @@ public class WaveformView implements IWaveformView {
SashForm topSash = new SashForm(top, SWT.SMOOTH);
topSash.setBackground(topSash.getDisplay().getSystemColor(SWT.COLOR_GRAY));
Composite namePane = new Composite(topSash, SWT.NONE);
Composite rightPane = new Composite(topSash, SWT.NONE);
rightPane.setLayout(new FillLayout(SWT.HORIZONTAL));
@ -339,7 +339,7 @@ public class WaveformView implements IWaveformView {
// create the name pane
createTextPane(namePane, "Name");
namePaneHeader= namePane.getChildren()[0];
namePane.setBackground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND));
@ -373,7 +373,7 @@ public class WaveformView implements IWaveformView {
nameListScrolled.setContent(nameList);
createTextPane(valuePane, "Value");
valuePane.setBackground(SWTResourceManager.getColor(SWT.COLOR_WIDGET_BACKGROUND));
valueListScrolled = new ScrolledComposite(valuePane, SWT.H_SCROLL | SWT.V_SCROLL);
valueListScrolled.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
@ -410,7 +410,7 @@ public class WaveformView implements IWaveformView {
waveformCanvas.addListener(SWT.MouseUp,waveformMouseListener);
waveformCanvas.addListener(SWT.MouseMove,waveformMouseListener);
waveformCanvas.addListener(SWT.MouseWheel, waveformMouseListener);
nameListScrolled.getVerticalBar().addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
@ -446,7 +446,7 @@ public class WaveformView implements IWaveformView {
createStreamDropTarget(valueList);
createWaveformDragSource(waveformCanvas);
createWaveformDropTarget(waveformCanvas);
toolTipHandler = new ToolTipHandler(parent.getShell());
toolTipHandler.activateHoverHelp(waveformCanvas);
}
@ -478,10 +478,10 @@ public class WaveformView implements IWaveformView {
if ("size".equals(pce.getPropertyName()) || "content".equals(pce.getPropertyName())) {
if(revealSelected) {
waveformCanvas.getDisplay().asyncExec(() ->{
update();
currentWaveformSelection.stream().forEach(e -> waveformCanvas.reveal(e.waveform));
valueList.redraw();
nameList.redraw();
update();
currentWaveformSelection.stream().forEach(e -> waveformCanvas.reveal(e.waveform));
valueList.redraw();
nameList.redraw();
});
revealSelected=false;
} else
@ -574,11 +574,11 @@ public class WaveformView implements IWaveformView {
do {
for(IEvent evt:firstTx.getValue()){
if(evt instanceof ITxEvent) {
ITx tx=((ITxEvent)evt).getTransaction();
if(evt.getKind()==EventKind.BEGIN && tx.getBeginTime()<=time && tx.getEndTime()>=time){
if(resultsList[tx.getConcurrencyIndex()]==null)
resultsList[tx.getConcurrencyIndex()]= ((ITxEvent)evt).getTransaction();
}
ITx tx=((ITxEvent)evt).getTransaction();
if(evt.getKind()==EventKind.BEGIN && tx.getBeginTime()<=time && tx.getEndTime()>=time){
if(resultsList[tx.getConcurrencyIndex()]==null)
resultsList[tx.getConcurrencyIndex()]= ((ITxEvent)evt).getTransaction();
}
}
}
firstTx=entry.waveform.getEvents().lowerEntry(firstTx.getKey());
@ -600,8 +600,8 @@ public class WaveformView implements IWaveformView {
valueListScrolled.setMinSize(width, tracksVerticalHeight);
valueListScrolled.redraw();
}
private boolean isArrayFull(Object[] array){
for(Object o:array){
if(o==null) return false;
@ -691,7 +691,7 @@ public class WaveformView implements IWaveformView {
public void addToSelection(ISelection selection, boolean showIfNeeded) {
setSelection(selection, true, showIfNeeded);
}
public void setSelection(ISelection selection, boolean add, boolean addIfNeeded) {
boolean selectionChanged = false;
currentWaveformSelection.forEach(e->e.selected=false);
@ -754,12 +754,12 @@ public class WaveformView implements IWaveformView {
moveSelection(direction, NEXT_PREV_IN_STREAM) ;
else {
if(currentWaveformSelection.size()==1) {
int idx = streams.indexOf(currentWaveformSelection.get(0));
if(direction==GotoDirection.UP && idx>0) {
setSelection(new StructuredSelection(streams.get(idx-1)));
} else if(direction==GotoDirection.DOWN && idx<(streams.size()-1)) {
setSelection(new StructuredSelection(streams.get(idx+1)));
}
int idx = streams.indexOf(currentWaveformSelection.get(0));
if(direction==GotoDirection.UP && idx>0) {
setSelection(new StructuredSelection(streams.get(idx-1)));
} else if(direction==GotoDirection.DOWN && idx<(streams.size()-1)) {
setSelection(new StructuredSelection(streams.get(idx+1)));
}
}
}
}
@ -863,7 +863,7 @@ public class WaveformView implements IWaveformView {
}
}
}
private boolean streamsVisible(ITxRelation relation) {
final IWaveform src = relation.getSource().getStream();
final IWaveform tgt = relation.getTarget().getStream();
@ -1175,7 +1175,7 @@ public class WaveformView implements IWaveformView {
public List<Object> getElementsAt(Point pt){
return waveformCanvas.getElementsAt(pt);
}
private void createWaveformDragSource(final Canvas canvas) {
Transfer[] types = new Transfer[] { LocalSelectionTransfer.getTransfer() };
DragSource dragSource = new DragSource(canvas, DND.DROP_MOVE);
@ -1201,15 +1201,15 @@ public class WaveformView implements IWaveformView {
}
}
});
// int style = SWT.MULTI | SWT.WRAP | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER;
// final StyledText text = new StyledText(waveformCanvas, style);
// text.setText("Dragging");
// dragSource.setDragSourceEffect(new DragSourceEffect(text) {
// @Override
// public void dragStart(DragSourceEvent event) {
// event.image = waveformCanvas.getDisplay().getSystemImage(SWT.ICON_WARNING);
// }
// });
// int style = SWT.MULTI | SWT.WRAP | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER;
// final StyledText text = new StyledText(waveformCanvas, style);
// text.setText("Dragging");
// dragSource.setDragSourceEffect(new DragSourceEffect(text) {
// @Override
// public void dragStart(DragSourceEvent event) {
// event.image = waveformCanvas.getDisplay().getSystemImage(SWT.ICON_WARNING);
// }
// });
}
private void createWaveformDropTarget(final Canvas canvas) {
@ -1348,7 +1348,7 @@ public class WaveformView implements IWaveformView {
origin.x=(int) (-time/waveformCanvas.getScaleFactorPow10());
waveformCanvas.setOrigin(origin);
}
@Override
public void scrollHorizontal(int percent) {
if(percent<-100) percent=-100;
@ -1365,7 +1365,7 @@ public class WaveformView implements IWaveformView {
updateValueList();
});
}
/// probably not the way it should be done
@Override
public void addDisposeListener(DisposeListener listener ) {

View File

@ -10,6 +10,8 @@
*******************************************************************************/
package com.minres.scviewer.database.tx;
import java.io.Serializable;
import com.minres.scviewer.database.AssociationType;
import com.minres.scviewer.database.DataType;

View File

@ -93,8 +93,18 @@ public class DatabaseServicesTest {
assertTrue(f.exists());
waveformDb.load(f);
assertNotNull(waveformDb);
assertEquals(3, waveformDb.getAllWaves().size());
List<IWaveform> waveforms = waveformDb.getAllWaves();
assertEquals(3, waveforms.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