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; package com.minres.scviewer.database.text;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.EOFException;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
@ -21,39 +20,49 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import org.mapdb.BTreeMap;
import org.mapdb.DB; import org.mapdb.DB;
import org.mapdb.DB.TreeMapSink;
import org.mapdb.DBMaker; import org.mapdb.DBMaker;
import org.mapdb.Serializer;
import org.mapdb.serializer.SerializerArrayTuple;
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.EventKind;
import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveform;
import com.minres.scviewer.database.IWaveformDb; import com.minres.scviewer.database.IWaveformDb;
import com.minres.scviewer.database.IWaveformDbLoader; import com.minres.scviewer.database.IWaveformDbLoader;
import com.minres.scviewer.database.InputFormatException; import com.minres.scviewer.database.InputFormatException;
import com.minres.scviewer.database.RelationType; 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{ public class TextDbLoader implements IWaveformDbLoader{
private Long maxTime=0L; private Long maxTime=0L;
IWaveformDb db;
List<IWaveform> streams;
Map<String, RelationType> relationTypes=new HashMap<String, RelationType>(); Map<String, RelationType> relationTypes=new HashMap<String, RelationType>();
DB mapDb; DB mapDb;
public TextDbLoader() { TreeMap<Long, TxStream> txStreams;
}
TreeMap<Long, TxGenerator> txGenerators;
BTreeMap<Long, ScvTx> transactions;
BTreeMap<Long[], ScvRelation> relations;
BTreeMap<String[], TxAttributeType> attributeTypes;
HashMap<Long, Tx> txCache = new HashMap<>();
@Override @Override
public Long getMaxTime() { public Long getMaxTime() {
@ -62,28 +71,21 @@ public class TextDbLoader implements IWaveformDbLoader{
@Override @Override
public Collection<IWaveform> getAllWaves() { public Collection<IWaveform> getAllWaves() {
return streams; return new ArrayList<>(txStreams.values());
}
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;
} }
static final byte[] x = "scv_tr_stream".getBytes(); static final byte[] x = "scv_tr_stream".getBytes();
@SuppressWarnings("unchecked")
@Override @Override
public boolean load(IWaveformDb db, File file) throws InputFormatException { public boolean load(IWaveformDb db, File file) throws InputFormatException {
if(file.isDirectory() || !file.exists()) return false; if(file.isDirectory() || !file.exists()) return false;
this.db=db;
this.streams = new ArrayList<>();
TextDbParser parser = new TextDbParser(this); TextDbParser parser = new TextDbParser(this);
boolean gzipped = isGzipped(file); boolean gzipped = isGzipped(file);
try { try {
if(!isTxfile(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file))) if(!isTxfile(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file)))
return false; return false;
} catch(Throwable e) { } catch(Exception e) {
throw new InputFormatException(); throw new InputFormatException();
} }
File mapDbFile; File mapDbFile;
@ -94,7 +96,7 @@ public class TextDbLoader implements IWaveformDbLoader{
} }
mapDbFile.delete(); // we just need a file name mapDbFile.delete(); // we just need a file name
mapDbFile.deleteOnExit(); mapDbFile.deleteOnExit();
this.mapDb = DBMaker mapDb = DBMaker
.fileDB(mapDbFile) .fileDB(mapDbFile)
.fileMmapEnableIfSupported() .fileMmapEnableIfSupported()
.fileMmapPreclearDisable() .fileMmapPreclearDisable()
@ -102,15 +104,26 @@ public class TextDbLoader implements IWaveformDbLoader{
.allocateStartSize(64*1024*1024) .allocateStartSize(64*1024*1024)
.allocateIncrement(64*1024*1024) .allocateIncrement(64*1024*1024)
.make(); .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 { try {
parser.setTransactionSink(txSink).setRelationMap(relations);
parser.parseInput(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file)); parser.parseInput(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file));
} catch(IllegalArgumentException|ArrayIndexOutOfBoundsException e) { } catch(IllegalArgumentException|ArrayIndexOutOfBoundsException e) {
} catch(Throwable e) { } catch(Exception e) {
System.out.println("---->>> Exception "+e.toString()+" caught while loading database"); System.out.println("---->>> Exception "+e.toString()+" caught while loading database");
e.printStackTrace(); e.printStackTrace();
return false; return false;
} }
streams.addAll(parser.streamsById.values()); transactions=txSink.create();
txStreams=new TreeMap<>(parser.streamsById);
txGenerators=new TreeMap<>(parser.generatorsById);
txCache.clear();
return true; 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 begin_attribute = Pattern.compile("^begin_attribute \\(ID (\\d+), name \"([^\"]+)\", type \"([^\"]+)\"\\)$");
static final Pattern end_attribute = Pattern.compile("^end_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, TxStream> streamsById = new HashMap<>();
HashMap<Long, TxGenerator> generatorsById = new HashMap<Long, TxGenerator>();
HashMap<Long, Tx> transactionsById = new HashMap<Long, Tx>(); HashMap<Long, TxGenerator> generatorsById = new HashMap<>();
TxGenerator generator = null;
Tx transaction = null; HashMap<Long, ScvTx> transactionsById = new HashMap<>();
boolean endTransaction=false;
final TextDbLoader loader; 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) { public TextDbParser(TextDbLoader loader) {
super(); super();
this.loader = loader; 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{ void parseInput(InputStream inputStream) throws IOException{
reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
String curLine = reader.readLine(); String curLine = reader.readLine();
@ -174,6 +204,18 @@ public class TextDbLoader implements IWaveformDbLoader{
parseLine(curLine, nextLine); 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{ private String parseLine(String curLine, String nextLine) throws IOException{
String[] tokens = curLine.split("\\s+"); String[] tokens = curLine.split("\\s+");
if("tx_record_attribute".equals(tokens[0])){//matcher = line =~ /^tx_record_attribute\s+(\d+)\s+"([^"]+)"\s+(\S+)\s*=\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()); String name = tokens[2].substring(1, tokens[2].length());
DataType type = DataType.valueOf(tokens[3]); DataType type = DataType.valueOf(tokens[3]);
String remaining = tokens.length>5?String.join(" ", Arrays.copyOfRange(tokens, 5, tokens.length-1)):""; 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])){ } else if("tx_begin".equals(tokens[0])){
Long id = Long.parseLong(tokens[1]); Long id = Long.parseLong(tokens[1]);
TxGenerator gen=generatorsById.get(Long.parseLong(tokens[2])); Long genId = Long.parseLong(tokens[2]);
TxStream stream = (TxStream) gen.getStream(); 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); 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') { if(nextLine!=null && nextLine.charAt(0)=='a') {
int idx=0; int idx=0;
while(nextLine!=null && nextLine.charAt(0)=='a') { while(nextLine!=null && nextLine.charAt(0)=='a') {
String[] attrTokens=nextLine.split("\\s+"); String[] attrTokens=nextLine.split("\\s+");
TxAttribute attr = new TxAttribute(gen.getBeginAttrs().get(idx), attrTokens[1]); TxAttribute attr = new TxAttribute(gen.beginAttrs.get(idx), attrTokens[1]);
transaction.getAttributes().add(attr); tx.attributes.add(attr);
idx++; idx++;
nextLine=reader.readLine(); 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)/ } 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]); Long id = Long.parseLong(tokens[1]);
transaction = transactionsById.get(id); ScvTx tx = transactionsById.get(id);
assert Integer.parseInt(tokens[2])==transaction.getGenerator().getId(); assert Long.parseLong(tokens[2])==tx.generatorId;
transaction.setEndTime(Long.parseLong(tokens[3])*stringToScale(tokens[4])); tx.endTime=Long.parseLong(tokens[3])*stringToScale(tokens[4]);
loader.maxTime = loader.maxTime>transaction.getEndTime()?loader.maxTime:transaction.getEndTime(); loader.maxTime = loader.maxTime>tx.endTime?loader.maxTime:tx.endTime;
TxGenerator gen = (TxGenerator) transaction.getGenerator(); TxGenerator gen = generatorsById.get(tx.generatorId);
TxStream stream = (TxStream) gen.getStream(); 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); stream.setConcurrency(stream.getConcurrency()-1);
if(nextLine!=null && nextLine.charAt(0)=='a') { if(nextLine!=null && nextLine.charAt(0)=='a') {
int idx=0; int idx=0;
while(nextLine!=null && nextLine.charAt(0)=='a') { while(nextLine!=null && nextLine.charAt(0)=='a') {
String[] attrTokens=nextLine.split("\\s+"); String[] attrTokens=nextLine.split("\\s+");
TxAttribute attr = new TxAttribute(gen.getEndAttrs().get(idx), attrTokens[1]); TxAttribute attr = new TxAttribute(gen.endAttrs.get(idx), attrTokens[1]);
transaction.getAttributes().add(attr); tx.attributes.add(attr);
idx++; idx++;
nextLine=reader.readLine(); nextLine=reader.readLine();
} }
} }
transactionsById.remove(tx.id);
} else if("tx_relation".equals(tokens[0])){//matcher = line =~ /^tx_relation\s+\"(\S+)\"\s+(\d+)\s+(\d+)$/ } 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])); Long tr2= Long.parseLong(tokens[2]);
Tx tr1= transactionsById.get(Long.parseLong(tokens[3])); Long tr1= Long.parseLong(tokens[3]);
String relType=tokens[1].substring(1, tokens[1].length()-2); String relType=tokens[1].substring(1, tokens[1].length()-2);
if(!loader.relationTypes.containsKey(relType)) if(!loader.relationTypes.containsKey(relType))
loader.relationTypes.put(relType, RelationType.create(relType)); loader.relationTypes.put(relType, RelationType.create(relType));
TxRelation rel = new TxRelation(loader.relationTypes.get(relType), tr1, tr2); ScvRelation rel = new ScvRelation(loader.relationTypes.get(relType), tr1, tr2);
tr1.getOutgoingRelations().add(rel); relations.put(new Long[]{tr1, tr2}, rel);
tr2.getIncomingRelations().add(rel);
} else if("scv_tr_stream".equals(tokens[0])){ } else if("scv_tr_stream".equals(tokens[0])){
Matcher matcher = scv_tr_stream.matcher(curLine); Matcher matcher = scv_tr_stream.matcher(curLine);
if (matcher.matches()) { if (matcher.matches()) {
@ -242,18 +292,19 @@ public class TextDbLoader implements IWaveformDbLoader{
Long id = Long.parseLong(matcher.group(1)); Long id = Long.parseLong(matcher.group(1));
TxStream stream=streamsById.get(Long.parseLong(matcher.group(3))); TxStream stream=streamsById.get(Long.parseLong(matcher.group(3)));
generator=new TxGenerator(id, stream, matcher.group(2)); generator=new TxGenerator(id, stream, matcher.group(2));
stream.getGenerators().add(generator);
generatorsById.put(id, generator); generatorsById.put(id, generator);
} }
} else if("begin_attribute".equals(tokens[0])){ } else if("begin_attribute".equals(tokens[0])){
Matcher matcher = begin_attribute.matcher(curLine); Matcher matcher = begin_attribute.matcher(curLine);
if ((matcher.matches())) { 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])){ } else if("end_attribute".equals(tokens[0])){
Matcher matcher = end_attribute.matcher(curLine); Matcher matcher = end_attribute.matcher(curLine);
if ((matcher.matches())) { 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])){ } else if(")".equals(tokens[0])){
generator=null; generator=null;
@ -275,5 +326,13 @@ public class TextDbLoader implements IWaveformDbLoader{
return 1L; 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; package com.minres.scviewer.database.text;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; 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.ITx;
import com.minres.scviewer.database.tx.ITxAttribute; import com.minres.scviewer.database.tx.ITxAttribute;
import com.minres.scviewer.database.tx.ITxGenerator; import com.minres.scviewer.database.tx.ITxGenerator;
import com.minres.scviewer.database.tx.ITxRelation; import com.minres.scviewer.database.tx.ITxRelation;
class Tx implements ITx, Serializable{ class Tx implements ITx {
/** private final TextDbLoader loader;
*
*/
private static final long serialVersionUID = -855200240003328221L;
private final Long id; private ScvTx scvTx = null;
private final TxGenerator generator;
private final IWaveform stream;
private int concurrencyIndex; private int concurrencyIndex;
private final Long beginTime; Tx(TextDbLoader loader, Long id){
this.loader=loader;
private Long endTime; this.scvTx = loader.transactions.get(id);
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;
} }
@Override @Override
public Collection<ITxRelation> getIncomingRelations() { 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 @Override
public Collection<ITxRelation> getOutgoingRelations() { 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 @Override
public int compareTo(ITx o) { public int compareTo(ITx o) {
int res =beginTime.compareTo(o.getBeginTime()); int res =getBeginTime().compareTo(o.getBeginTime());
if(res!=0) if(res!=0)
return res; return res;
else else
return id.compareTo(o.getId()); return getId().compareTo(o.getId());
} }
@Override @Override
@ -80,31 +62,27 @@ class Tx implements ITx, Serializable{
@Override @Override
public Long getId() { public Long getId() {
return id; return scvTx.id;
} }
@Override @Override
public IWaveform getStream() { public IWaveform getStream() {
return stream; return loader.txStreams.get(scvTx.streamId);
} }
@Override @Override
public ITxGenerator getGenerator() { public ITxGenerator getGenerator() {
return generator; return loader.txGenerators.get(scvTx.generatorId);
} }
@Override @Override
public Long getBeginTime() { public Long getBeginTime() {
return beginTime; return scvTx.beginTime;
} }
@Override @Override
public Long getEndTime() { public Long getEndTime() {
return endTime; return scvTx.endTime;
}
public void setEndTime(long l) {
endTime=l;
} }
@Override @Override
@ -118,7 +96,7 @@ class Tx implements ITx, Serializable{
@Override @Override
public List<ITxAttribute> getAttributes() { 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.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;
public class TxAttribute implements ITxAttribute, Serializable { public class TxAttribute implements ITxAttribute, Serializable {
@ -24,13 +23,17 @@ public class TxAttribute implements ITxAttribute, Serializable {
*/ */
private static final long serialVersionUID = 4767726016651807152L; 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){ TxAttribute(TxAttributeType attributeType){
attributeType = TxAttributeTypeFactory.INSTANCE.getAttrType(name, dataType, type); this.attributeType=attributeType;
switch(dataType){ }
TxAttribute(TxAttributeType type, String value){
attributeType=type;
switch(type.getDataType()){
case STRING: case STRING:
case ENUMERATION: case ENUMERATION:
this.value=value.substring(1, value.length()-2); this.value=value.substring(1, value.length()-2);
@ -40,14 +43,6 @@ public class TxAttribute implements ITxAttribute, Serializable {
} }
} }
TxAttribute(ITxAttributeType type){
attributeType=type;
}
TxAttribute(ITxAttributeType type, String value){
this(type.getName(), type.getDataType(), type.getType(), value);
}
@Override @Override
public String getName() { public String getName() {
return attributeType.getName(); return attributeType.getName();

View File

@ -28,10 +28,6 @@ class TxAttributeType implements ITxAttributeType, Serializable {
private AssociationType type; 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){ TxAttributeType(String name, DataType dataType, AssociationType type){
this.name=name; this.name=name;
this.dataType=dataType; 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; package com.minres.scviewer.database.text;
import java.io.Serializable;
import com.minres.scviewer.database.EventKind; import com.minres.scviewer.database.EventKind;
import com.minres.scviewer.database.WaveformType; import com.minres.scviewer.database.WaveformType;
import com.minres.scviewer.database.tx.ITx; import com.minres.scviewer.database.tx.ITx;
import com.minres.scviewer.database.tx.ITxEvent; import com.minres.scviewer.database.tx.ITxEvent;
class TxEvent implements ITxEvent, Serializable { class TxEvent implements ITxEvent {
/** final TextDbLoader loader;
*
*/
private static final long serialVersionUID = 4481575593229248159L;
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;
@ -37,13 +25,13 @@ class TxEvent implements ITxEvent, Serializable {
@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
@ -63,6 +51,6 @@ class TxEvent implements ITxEvent, Serializable {
@Override @Override
public ITx getTransaction() { 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<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){ TxGenerator(Long id, TxStream stream, String name){
this.id=id; this.id=id;
@ -45,32 +45,34 @@ class TxGenerator implements ITxGenerator, Serializable{
this.name=name; this.name=name;
} }
public IWaveform getStream(){
return stream;
}
public List<ITx> getTransactions(){
return transactions;
}
Boolean isActive() {return active;}
@Override @Override
public Long getId() { public Long getId() {
return id; return id;
} }
@Override
public IWaveform getStream(){
return stream;
}
@Override @Override
public String getName() { public String getName() {
return name; return name;
} }
public ArrayList<ITxAttributeType> getBeginAttrs() { @Override
public List<ITx> getTransactions(){
return transactions;
}
public List<TxAttributeType> getBeginAttrs() {
return beginAttrs; return beginAttrs;
} }
public ArrayList<ITxAttributeType> getEndAttrs() { public List<TxAttributeType> getEndAttrs() {
return endAttrs; return endAttrs;
} }
Boolean isActive() {return active;}
} }

View File

@ -12,31 +12,28 @@ class TxRelation implements ITxRelation, Serializable {
*/ */
private static final long serialVersionUID = -347668857680574140L; private static final long serialVersionUID = -347668857680574140L;
final Tx source; final TextDbLoader loader;
final Tx target; final ScvRelation scvRelation;
final RelationType relationType; public TxRelation(TextDbLoader loader, ScvRelation scvRelation) {
this.loader = loader;
public TxRelation(RelationType relationType, Tx source, Tx target) { this.scvRelation = scvRelation;
this.source = source;
this.target = target;
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

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

View File

@ -1201,15 +1201,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

@ -10,6 +10,8 @@
*******************************************************************************/ *******************************************************************************/
package com.minres.scviewer.database.tx; package com.minres.scviewer.database.tx;
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;

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