/** * Replication Benchmarker * https://github.com/score-team/replication-benchmarker/ * Copyright (C) 2013 LORIA / Inria / SCORE Team * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package jbenchmarker.trace; /** * * @author medhi * @author urso */ import crdt.simulator.IncorrectTraceException; import crdt.CRDT; import crdt.Factory; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Result; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import crdt.simulator.CausalSimulator; import crdt.simulator.Trace; import org.jdom.input.DOMBuilder; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; public class Trace2XML { private static final String fill = ""; // private static final int fillerReplica = 99999; /** * @param args */ // static InputStreamReader stream = null; // static LineNumberReader llog = null; public static void transformerXml(Document document, String fichier) throws TransformerConfigurationException, TransformerException { // Création de la source DOM Source source = new DOMSource(document); // Création du fichier de sortie File file = new File(fichier); Result resultat = new StreamResult(fichier); // Configuration du transformer TransformerFactory fabrique = TransformerFactory.newInstance(); Transformer transformer = fabrique.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1"); // Transformation transformer.transform(source, resultat); } public static void main(String[] args) throws Exception { if (args.length < 1 || args.length > 2) { System.err.println("Arguments : trace [document]"); System.err.println("- trace : a file.log to parse "); System.err.println("- document : keep only operation on a document (default all document)"); System.err.println("Produces file.xml"); System.exit(1); } // Création d'un nouveau DOM DocumentBuilderFactory fabrique = DocumentBuilderFactory.newInstance(); DocumentBuilder constructeur = fabrique.newDocumentBuilder(); Document document = constructeur.newDocument(); // Propriétés du DOM document.setXmlVersion("1.0"); document.setXmlStandalone(true); Element racine1 = document.createElement("Traces"); document.appendChild(racine1); Element trace = document.createElement("Trace"); racine1.appendChild(trace); File f = new File(args[0]); int doc = (args.length == 2) ? Integer.parseInt(args[1]) : 0; System.out.print(f.getName() + " "); decompose(new InputStreamReader(new FileInputStream(f)), document, trace, true, true, null, doc); transformerXml(document, f.getName().replace("log", "xml")); } public static Element operation(Document document, String type, String replica, String position, String timestamp, int doc, Node VC) { Element OP = document.createElement("Operation"); Element t = document.createElement("Type"); Element p = document.createElement("Position"); Element r = document.createElement("NumReplica"); Element ts = document.createElement("Timestamp"); Element d = document.createElement("NumDocument"); t.setTextContent(type); p.setTextContent(position); r.setTextContent(replica); ts.setTextContent(timestamp); d.setTextContent(""+doc); OP.appendChild(t); OP.appendChild(d); OP.appendChild(r); OP.appendChild(p); OP.appendChild(ts); OP.appendChild(VC); return OP; } public static Element insert(Document document, String replica, String position, String content, String timestamp, int doc, Node VC) { Element n = operation(document, "Ins", replica, position, timestamp, doc, VC); Element t = document.createElement("Text"); t.setTextContent(content); n.appendChild(t); return n; } public static Element delete(Document document, String replica, String position, String offset, String timestamp, int doc, Node VC) { Element n = operation(document, "Del", replica, position, timestamp, doc, VC); Element o = document.createElement("Offset"); o.setTextContent(offset); n.appendChild(o); return n; } /** * construct XML Entry of a vector clock */ public static Element entry(Document document, String replica, String clock) { Element Entry = document.createElement("Entry"); Element r = document.createElement("Replica"); Element c = document.createElement("Clock"); r.setTextContent(replica); Entry.appendChild(r); c.setTextContent(clock); Entry.appendChild(c); return Entry; } /** * Translate a input stream log into a XML trace * @param stream IO input stream of trace * @param document DOM doc to be generated * @param racine racine of trace * @param checkCausality can throw IncorrectTraceException if true * @param checkPosition can throw IncorrectTraceException if operation are incorrect (out of bounds) on trace * @param out output produced by log * @throws Exception IO or IncorrectTraceException */ static void decompose(InputStreamReader stream, Document document, Element racine, boolean checkCausality, boolean checkPosition, BufferedWriter out, int docToKeep) throws Exception { String[] Clock = null, Separation = null; String myLine; String[] Info; StringBuffer sb; Set<Integer> docs = new HashSet<Integer>(); // Clocks : doc -> replica -> VC // Map<Integer, Map<Integer, VectorClock>> clocks = new HashMap<Integer, Map<Integer, VectorClock>>(); DOMBuilder builder = new DOMBuilder(); // To test positions Map<Integer, StringBuilder> docsTest = null; if (checkPosition) { docsTest = new HashMap<Integer, StringBuilder>(); } LineNumberReader llog = new LineNumberReader(stream); String pos; String text = null; try { while ((myLine = llog.readLine()) != null) { //System.out.println(myLine); Element OP; int doc; Clock = ExtraireVH(myLine); Element VH = document.createElement("VectorClock"); for (int i = 0; i < Clock.length; i++) { Separation = Clock[i].split("-"); VH.appendChild(entry(document,Separation[0].replace("[", ""),Separation[1].replace("]", ""))); } // VH.appendChild(entry(document, "" + fillerReplica, "1")); if (myLine.contains("Del")) { Info = DecomposeLigne("Del", myLine); pos = Info[0].replace("(", ""); doc = Integer.parseInt(Info[3]); int doct = (doc == docToKeep) ? 1 : doc; OP = Trace2XML.delete(document, Info[4], pos, Info[1], Info[2], doct, VH); } else { Info = DecomposeLigne("Ins", myLine); sb = new StringBuffer(Info[0]); sb.delete(0, 1); text = sb.toString(); if(text.equals("\"\"\"")) text = "\""; else text = text.replace("\"", ""); text = text.replace("\\n", "\n"); pos = Info[1]; doc = Integer.parseInt(Info[3]); int doct = (doc == docToKeep) ? 1 : doc; OP = Trace2XML.insert(document, Info[4], pos, text, Info[2], doct, VH); } docs.add(doc); if (checkPosition) { StringBuilder s = docsTest.get(doc); if (s == null) { s = new StringBuilder(""); docsTest.put(doc, s); } try { int p = Integer.parseInt(pos); if (myLine.contains("Ins")) { s.insert(p, text); } else { int e = p + Integer.parseInt(Info[1]); if (s.length()<e) throw new StringIndexOutOfBoundsException(); s.delete(p, e); } } catch (StringIndexOutOfBoundsException e) { // Position error throw new IncorrectTraceException("Operation position " + pos + " out of bound " + s.length() + " in \n" + s.toString()); } } if (docToKeep==0 || doc==1) racine.appendChild(OP); } if (out != null) { for (Entry<Integer, StringBuilder> d : docsTest.entrySet()) { out.write("%%% ---------------------\n%%% Document " + d.getKey() + "\n%%% ---------------------\n"); out.write(d.getValue().toString() + "\n"); } out.close(); } if (checkCausality) { org.jdom.Element opl = builder.build(racine); for (int d : docs) { Trace trace = new TraceGenerator.XMLTrace(d, opl.getChildren().iterator()); CausalSimulator cd = new CausalSimulator(new CausalCheckerFactory(), false, 0); cd.run(trace); } } System.out.println("OK"); } catch (Exception e) { // --- Gestion erreur lecture du fichier (fichier non existant, illisible, etc.) System.err.println("Error line number : " + llog.getLineNumber()); throw e; } } static String[] DecomposeLigne(String type, String line) { String[] info, aide, fin; aide = line.split(type); info = aide[1].split(","); String Sauv = ""; for (int i = 0; i < info.length; i++) { if (info[i].startsWith("[")) { while (!info[i].endsWith("]")) { i++; } } else { Sauv = Sauv + info[i] + "!"; } } fin = Sauv.split("!"); fin[4] = fin[4].replace(")", ""); return fin; } static String[] ExtraireVH(String Chaine) { String[] divise = Chaine.split(","), fin; String essaye = ""; for (int i = 0; i < divise.length; i++) { if (divise[i].startsWith("[")) { while (!divise[i].endsWith("]")) { essaye = essaye + divise[i] + "!"; i++; } essaye = essaye + divise[i]; } } fin = essaye.split("!"); for (int j = 0; j < fin.length; j++) { if (fin[j].startsWith("[")) { fin[j] = fin[j].replace("[", ""); } else if (fin[j].endsWith("]")) { fin[j] = fin[j].replace("]", ""); } } return fin; } }