/******************************************************************************* * Copyright (c) 2012 IT Just working. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IT Just working - initial API and implementation *******************************************************************************/ package com.minres.scviewer.database.text; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; import com.google.common.collect.HashMultimap; import com.minres.scviewer.database.AssociationType; import com.minres.scviewer.database.DataType; import com.minres.scviewer.database.EventKind; import com.minres.scviewer.database.IWaveform; import com.minres.scviewer.database.IWaveformDb; import com.minres.scviewer.database.IWaveformDbLoader; import com.minres.scviewer.database.InputFormatException; import com.minres.scviewer.database.RelationType; import com.minres.scviewer.database.RelationTypeFactory; import com.minres.scviewer.database.tx.ITx; public class TextDbLoader implements IWaveformDbLoader{ private Long maxTime=0L; Map relationTypes = null; Map txStreams = null; Map txGenerators = null; Map transactions = null; Map attributeTypes = null; HashMultimap relationsIn = null; HashMultimap relationsOut = null; @Override public Long getMaxTime() { return maxTime; } @Override public Collection getAllWaves() { return new ArrayList<>(txStreams.values()); } static final byte[] x = "scv_tr_stream".getBytes(); @SuppressWarnings("unchecked") @Override public boolean load(IWaveformDb db, File file) throws InputFormatException { if(file.isDirectory() || !file.exists()) return false; TextDbParser parser = new TextDbParser(this); boolean gzipped = isGzipped(file); try { if(!isTxfile(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file))) return false; } catch(Exception e) { throw new InputFormatException(); } relationTypes=new HashMap(); txStreams = new HashMap<>(); txGenerators = new HashMap<>(); transactions = new HashMap<>(); attributeTypes = new HashMap<>(); relationsIn = HashMultimap.create(); relationsOut = HashMultimap.create(); try { parser.parseInput(gzipped?new GZIPInputStream(new FileInputStream(file)):new FileInputStream(file)); } catch(IllegalArgumentException|ArrayIndexOutOfBoundsException e) { } catch(Exception e) { System.out.println("---->>> Exception "+e.toString()+" caught while loading database"); e.printStackTrace(); return false; } return true; } private static boolean isTxfile(InputStream istream) { byte[] buffer = new byte[x.length]; try { int readCnt = istream.read(buffer, 0, x.length); istream.close(); if(readCnt==x.length){ for(int i=0; i getAllRelationTypes(){ return relationTypes.values(); } static class TextDbParser { static final Pattern scv_tr_stream = Pattern.compile("^scv_tr_stream\\s+\\(ID (\\d+),\\s+name\\s+\"([^\"]+)\",\\s+kind\\s+\"([^\"]+)\"\\)$"); static final Pattern scv_tr_generator = Pattern.compile("^scv_tr_generator\\s+\\(ID\\s+(\\d+),\\s+name\\s+\"([^\"]+)\",\\s+scv_tr_stream\\s+(\\d+),$"); static final Pattern begin_attribute = Pattern.compile("^begin_attribute \\(ID (\\d+), name \"([^\"]+)\", type \"([^\"]+)\"\\)$"); static final Pattern end_attribute = Pattern.compile("^end_attribute \\(ID (\\d+), name \"([^\"]+)\", type \"([^\"]+)\"\\)$"); final TextDbLoader loader; BufferedReader reader = null; TxGenerator generator=null; public TextDbParser(TextDbLoader loader) { super(); this.loader = loader; } void parseInput(InputStream inputStream) throws IOException{ reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); String curLine = reader.readLine(); String nextLine = null; while((nextLine=reader.readLine())!=null && curLine!=null) { curLine=parseLine(curLine, nextLine); } if(curLine!=null) parseLine(curLine, nextLine); } private TxAttributeType getAttrType(String name, DataType dataType, AssociationType type){ String key =name+"-"+dataType.toString(); TxAttributeType res; if(loader.attributeTypes.containsKey(key)){ res=loader.attributeTypes.get(key); } else { res=new TxAttributeType(name, dataType, type); loader.attributeTypes.put(key, res); } return res; } private String parseLine(String curLine, String nextLine) throws IOException{ String[] tokens = curLine.split("\\s+"); if("tx_record_attribute".equals(tokens[0])){ Long id = Long.parseLong(tokens[1]); String name = tokens[2].substring(1, tokens[2].length()); DataType type = DataType.valueOf(tokens[3]); String remaining = tokens.length>5?String.join(" ", Arrays.copyOfRange(tokens, 5, tokens.length)):""; TxAttributeType attrType = getAttrType(name, type, AssociationType.RECORD); loader.transactions.get(id).attributes.add(new TxAttribute(attrType, remaining)); } else if("tx_begin".equals(tokens[0])){ Long id = Long.parseLong(tokens[1]); Long genId = Long.parseLong(tokens[2]); TxGenerator gen=loader.txGenerators.get(genId); ScvTx scvTx = new ScvTx(id, gen.stream.getId(), genId, Long.parseLong(tokens[3])*stringToScale(tokens[4])); Tx tx = new Tx(loader, scvTx); loader.maxTime = loader.maxTime>scvTx.beginTime?loader.maxTime:scvTx.beginTime; TxStream stream = loader.txStreams.get(gen.stream.getId()); stream.setConcurrency(stream.getConcurrency()+1); if(nextLine!=null && nextLine.charAt(0)=='a') { int idx=0; while(nextLine!=null && nextLine.charAt(0)=='a') { String[] attrTokens=nextLine.split("\\s+"); TxAttribute attr = new TxAttribute(gen.beginAttrs.get(idx), attrTokens[1]); tx.getAttributes().add(attr); idx++; nextLine=reader.readLine(); } } loader.transactions.put(id, scvTx); gen.getTransactions().add(tx); } else if("tx_end".equals(tokens[0])){ Long id = Long.parseLong(tokens[1]); ScvTx tx = loader.transactions.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 = loader.txGenerators.get(tx.generatorId); TxStream stream = loader.txStreams.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.endAttrs.get(idx), attrTokens[1]); tx.attributes.add(attr); idx++; nextLine=reader.readLine(); } } } else if("tx_relation".equals(tokens[0])){ Long tr2= Long.parseLong(tokens[2]); Long tr1= Long.parseLong(tokens[3]); String relType=tokens[1].substring(1, tokens[1].length()-1); if(!loader.relationTypes.containsKey(relType)) loader.relationTypes.put(relType, RelationTypeFactory.create(relType)); ScvRelation rel = new ScvRelation(loader.relationTypes.get(relType), tr1, tr2); loader.relationsOut.put(tr1, rel); loader.relationsIn.put(tr2, rel); } else if("scv_tr_stream".equals(tokens[0])){ Matcher matcher = scv_tr_stream.matcher(curLine); if (matcher.matches()) { Long id = Long.parseLong(matcher.group(1)); TxStream stream = new TxStream(loader, id, matcher.group(2), matcher.group(3)); loader.txStreams.put(id, stream); } } else if("scv_tr_generator".equals(tokens[0])){ Matcher matcher = scv_tr_generator.matcher(curLine); if ((matcher.matches())) { Long id = Long.parseLong(matcher.group(1)); TxStream stream=loader.txStreams.get(Long.parseLong(matcher.group(3))); generator=new TxGenerator(id, stream, matcher.group(2)); loader.txGenerators.put(id, generator); } } else if("begin_attribute".equals(tokens[0])){ Matcher matcher = begin_attribute.matcher(curLine); if ((matcher.matches())) { TxAttributeType attrType = getAttrType(matcher.group(2), DataType.valueOf(matcher.group(3)), AssociationType.BEGIN); generator.beginAttrs.add(attrType); } } else if("end_attribute".equals(tokens[0])){ Matcher matcher = end_attribute.matcher(curLine); if ((matcher.matches())) { TxAttributeType attrType = getAttrType(matcher.group(2), DataType.valueOf(matcher.group(3)), AssociationType.END); generator.endAttrs.add(attrType); } } else if(")".equals(tokens[0])){ generator=null; } else if("a".equals(tokens[0])){//matcher = line =~ /^a\s+(.+)$/ System.out.println("Don't know what to do with: '"+curLine+"'"); } else System.out.println("Don't know what to do with: '"+curLine+"'"); return nextLine; } private long stringToScale(String scale){ String cmp = scale.trim(); if("fs".equals(cmp)) return 1L; if("ps".equals(cmp)) return 1000L; if("ns".equals(cmp)) return 1000000L; if("us".equals(cmp)) return 1000000000L; if("ms".equals(cmp)) return 1000000000000L; if("s".equals(cmp) ) return 1000000000000000L; return 1L; } } public ITx getTransaction(long source) { return new Tx(this, transactions.get(source)); } }