/* * Copyright (c) 2013-2014, Pierre Laporte * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3 only, as * published by the Free Software Foundation. * * This code 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 work; if not, see <http://www.gnu.org/licenses/>. */ package fr.pingtimeout.tyrion.model; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.*; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.logging.Level; import java.util.logging.Logger; public class LocksFileReader { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private final Logger logger = Logger.getLogger(getClass().getName()); private final Set<Access> criticalSections = new TreeSet<>(); public LocksFileReader(File file) { try (InputStream inputStream = new FileInputStream(file)) { loadFile(inputStream); } catch (IOException e) { throw new IllegalStateException("Could not load file " + file, e); } } public LocksFileReader(InputStream inputStream) { loadFile(inputStream); } private void loadFile(InputStream inputStream) { final Map<Accessor, CriticalSectionEntered> lastEnterInCriticalSection = new HashMap<>(); try (InputStreamReader inputStreamReader = new InputStreamReader(inputStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) { String line; while ((line = bufferedReader.readLine()) != null) { processLine(line, lastEnterInCriticalSection); } } catch (IOException e) { logger.log(Level.SEVERE, "Could not load file", e); } } private void processLine(String line, Map<Accessor, CriticalSectionEntered> lastEnterInCriticalSection) throws IOException { if (line.startsWith("{\"enter\":")) { CriticalSectionEntered event = OBJECT_MAPPER.readValue(line, CriticalSectionEntered.class); process(event, lastEnterInCriticalSection); } else if (line.startsWith("{\"exit\":")) { CriticalSectionExit event = OBJECT_MAPPER.readValue(line, CriticalSectionExit.class); process(event, lastEnterInCriticalSection); } else { // TODO: for the time being we will ignore "entering" event logger.warning("Unknown line: " + line); } } private void process(CriticalSectionExit exit, Map<Accessor, CriticalSectionEntered> lastEnterInCriticalSection) { Accessor accessor = exit.getAccessor(); CriticalSectionEntered lastEnter = lastEnterInCriticalSection.get(accessor); if (lastEnter == null) { logger.log(Level.FINE, "Got 'exit' without matching 'enter', ignoring event", exit); } else { criticalSections.add(new Access(lastEnter, exit)); lastEnterInCriticalSection.remove(accessor); } } private void process(CriticalSectionEntered enter, Map<Accessor, CriticalSectionEntered> lastEnterInCriticalSection) { Accessor accessor = enter.getAccessor(); CriticalSectionEntered lastEnter = lastEnterInCriticalSection.get(accessor); if (lastEnter == null) { lastEnterInCriticalSection.put(accessor, enter); } else { logger.log(Level.FINE, "Got two consecutive 'enter', ignoring the first one", enter); } } public AccessReport buildAccessReport() { return new AccessReport(criticalSections); } }