From 85ce07f11fae065a49ad270213ddc25f33e54b79 Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sun, 3 Jan 2021 14:16:56 +0100 Subject: [PATCH] refactor internal transaction representation --- .../scviewer/database/text/ScvRelation.java | 25 +++ .../minres/scviewer/database/text/ScvTx.java | 47 +++++ .../scviewer/database/text/TextDbLoader.java | 171 ++++++++++++------ .../com/minres/scviewer/database/text/Tx.java | 66 +++---- .../scviewer/database/text/TxAttribute.java | 33 ++-- .../database/text/TxAttributeType.java | 4 - .../database/text/TxAttributeTypeFactory.java | 37 ---- .../scviewer/database/text/TxEvent.java | 30 +-- .../scviewer/database/text/TxGenerator.java | 30 +-- .../scviewer/database/text/TxRelation.java | 19 +- .../scviewer/database/text/TxStream.java | 61 +++++-- .../ui/swt/internal/StreamPainter.java | 19 +- .../ui/swt/internal/WaveformView.java | 104 +++++------ .../database/tx/ITxAttributeType.java | 2 + .../database/test/DatabaseServicesTest.java | 12 +- 15 files changed, 373 insertions(+), 287 deletions(-) create mode 100644 plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/ScvRelation.java create mode 100644 plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/ScvTx.java delete mode 100644 plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxAttributeTypeFactory.java diff --git a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/ScvRelation.java b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/ScvRelation.java new file mode 100644 index 0000000..de07918 --- /dev/null +++ b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/ScvRelation.java @@ -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; + } + +} diff --git a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/ScvTx.java b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/ScvTx.java new file mode 100644 index 0000000..92498f2 --- /dev/null +++ b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/ScvTx.java @@ -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 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;} +} diff --git a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TextDbLoader.java b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TextDbLoader.java index f5eb5e3..51c2090 100644 --- a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TextDbLoader.java +++ b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TextDbLoader.java @@ -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 streams; - Map relationTypes=new HashMap(); DB mapDb; + + TreeMap txStreams; + + TreeMap txGenerators; + + BTreeMap transactions; + + BTreeMap relations; - public TextDbLoader() { - } + BTreeMap attributeTypes; - @Override + HashMap txCache = new HashMap<>(); + + @Override public Long getMaxTime() { return maxTime; } @Override public Collection getAllWaves() { - return streams; - } - - public Map getGeneratorsById() { - TreeMap res = new TreeMap(); - 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 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 streamsById = new HashMap(); - HashMap generatorsById = new HashMap(); - HashMap transactionsById = new HashMap(); - TxGenerator generator = null; - Tx transaction = null; - boolean endTransaction=false; + HashMap streamsById = new HashMap<>(); + + HashMap generatorsById = new HashMap<>(); + + HashMap transactionsById = new HashMap<>(); + final TextDbLoader loader; - BufferedReader reader =null; + + BufferedReader reader = null; + + TxGenerator generator = null; + + private TreeMapSink txSink; + + private BTreeMap relations; public TextDbParser(TextDbLoader loader) { super(); this.loader = loader; } + public TextDbParser setTransactionSink(TreeMapSink sink) { + this.txSink=sink; + return this; + } + + public TextDbParser setRelationMap(BTreeMap 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; + } } diff --git a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/Tx.java b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/Tx.java index 190eee9..1ff96c2 100644 --- a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/Tx.java +++ b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/Tx.java @@ -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 attributes = new ArrayList<>(); - - private final List incomingRelations = new ArrayList<>(); - - private final List 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 getIncomingRelations() { - return incomingRelations; + NavigableMap 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 getOutgoingRelations() { - return outgoingRelations; + NavigableMap 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 getAttributes() { - return attributes; + return scvTx.attributes; } } diff --git a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxAttribute.java b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxAttribute.java index 948e0fe..0048bf9 100644 --- a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxAttribute.java +++ b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxAttribute.java @@ -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 diff --git a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxAttributeType.java b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxAttributeType.java index de25fac..67c72aa 100644 --- a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxAttributeType.java +++ b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxAttributeType.java @@ -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; diff --git a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxAttributeTypeFactory.java b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxAttributeTypeFactory.java deleted file mode 100644 index dbc482b..0000000 --- a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxAttributeTypeFactory.java +++ /dev/null @@ -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 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; - } -} diff --git a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxEvent.java b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxEvent.java index 67ea2af..c4c977d 100644 --- a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxEvent.java +++ b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxEvent.java @@ -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); } } diff --git a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxGenerator.java b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxGenerator.java index 8b00e30..bc6dbff 100644 --- a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxGenerator.java +++ b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxGenerator.java @@ -35,9 +35,9 @@ class TxGenerator implements ITxGenerator, Serializable{ ArrayList transactions=new ArrayList(); - ArrayList beginAttrs = new ArrayList(); + ArrayList beginAttrs = new ArrayList<>(); - ArrayList endAttrs= new ArrayList(); + ArrayList 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 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 getBeginAttrs() { + @Override + public List getTransactions(){ + return transactions; + } + + public List getBeginAttrs() { return beginAttrs; } - public ArrayList getEndAttrs() { + public List getEndAttrs() { return endAttrs; } + Boolean isActive() {return active;} + } diff --git a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxRelation.java b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxRelation.java index 034ad1e..a36150f 100644 --- a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxRelation.java +++ b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxRelation.java @@ -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); } } diff --git a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxStream.java b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxStream.java index 468f3a8..af8635b 100644 --- a/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxStream.java +++ b/plugins/com.minres.scviewer.database.text/src/com/minres/scviewer/database/text/TxStream.java @@ -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 generators = new ArrayList(); + 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 events; + TreeMap 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>() - events = (BTreeMap) loader.mapDb.treeMap(name).keySerializer(Serializer.LONG).createOrOpen(); + this.loader=loader; } List 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 getEvents() { + if(!concurrencyCalculated) calculateConcurrency(); return (NavigableMap)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 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 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(; rowIdxtx.getBeginTime(); rowIdx++); + if(rowendtime.size()<=rowIdx) + rowendtime.add(tx.getEndTime()); + else + rowendtime.set(rowIdx, tx.getEndTime()); + tx.setConcurrencyIndex(rowIdx); + }); + }); + concurrencyCalculated=true; + } + } diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/StreamPainter.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/StreamPainter.java index 2b06b4b..66fd272 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/StreamPainter.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/StreamPainter.java @@ -84,17 +84,20 @@ public class StreamPainter extends TrackPainter{ NavigableMap 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 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){ diff --git a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java index 205ad87..2a83aab 100644 --- a/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java +++ b/plugins/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/ui/swt/internal/WaveformView.java @@ -116,9 +116,9 @@ public class WaveformView implements IWaveformView { final WaveformCanvas waveformCanvas; final ToolTipHandler toolTipHandler; - + private boolean revealSelected=false; - + private Composite top; protected ObservableList streams; @@ -128,13 +128,13 @@ public class WaveformView implements IWaveformView { private int tracksVerticalHeight; private TreeMap 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 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 ) { diff --git a/plugins/com.minres.scviewer.database/src/com/minres/scviewer/database/tx/ITxAttributeType.java b/plugins/com.minres.scviewer.database/src/com/minres/scviewer/database/tx/ITxAttributeType.java index fe21390..355910b 100644 --- a/plugins/com.minres.scviewer.database/src/com/minres/scviewer/database/tx/ITxAttributeType.java +++ b/plugins/com.minres.scviewer.database/src/com/minres/scviewer/database/tx/ITxAttributeType.java @@ -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; diff --git a/tests/com.minres.scviewer.database.test/src/com/minres/scviewer/database/test/DatabaseServicesTest.java b/tests/com.minres.scviewer.database.test/src/com/minres/scviewer/database/test/DatabaseServicesTest.java index 882f7db..4029e07 100644 --- a/tests/com.minres.scviewer.database.test/src/com/minres/scviewer/database/test/DatabaseServicesTest.java +++ b/tests/com.minres.scviewer.database.test/src/com/minres/scviewer/database/test/DatabaseServicesTest.java @@ -93,8 +93,18 @@ public class DatabaseServicesTest { assertTrue(f.exists()); waveformDb.load(f); assertNotNull(waveformDb); - assertEquals(3, waveformDb.getAllWaves().size()); + List 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