/******************************************************************************* * Copyright (c) 2010 Freescale Semiconductor. * 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: * Serge Beauchamp (Freescale Semiconductor) - initial API and implementation *******************************************************************************/ package com.freescale.deadlockpreventer; import java.io.BufferedReader; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.LinkedList; import com.freescale.deadlockpreventer.NetworkServer.Session; import com.freescale.deadlockpreventer.QueryService.IBundleInfo; import com.freescale.deadlockpreventer.QueryService.ITransaction; import com.freescale.deadlockpreventer.ReportService.IListener; @SuppressWarnings("unused") public class ConsoleNetworkServer { static QueryService queryService; public static void main(String[] args) { int port = NetworkServer.DEFAULT_PORT; if (args.length > 0) port = Integer.parseInt(args[0]); NetworkServer networkServer = new NetworkServer(); queryService = new QueryService() { public void handle(Session session) { System.out.println("New session started for: " + session.getKey()); super.handle(session); } }; String queryKey = networkServer.createNewSessionKey(QueryService.ID); networkServer.registerSevice(queryKey, queryService); String reportKey = networkServer.createNewSessionKey(ReportService.ID); ReportService reportService = new ReportService() { public void handle(Session session) { System.out.println("New session started for: " + session.getKey()); super.handle(session); } }; reportService.setListener(new IListener() { @Override public int report(String type, String threadID, String conflictThreadID, String lock, String[] lockStack, String precedent, String[] precedentStack, String conflict, String[] conflictStack, String conflictPrecedent, String[] conflictPrecedentStack, String message) { System.out.println(message); System.out.println("(C)ontinue, (E)xception, (A)bort?"); if (alwaysContinue) { System.out.println(" -> always (C)ontinue"); return IConflictListener.CONTINUE; } char c = readLine().charAt(0); if (Character.toLowerCase(c) == 'c') return IConflictListener.CONTINUE; if (Character.toLowerCase(c) == 'e') return IConflictListener.EXCEPTION; if (Character.toLowerCase(c) == 'a') return IConflictListener.ABORT; return IConflictListener.CONTINUE; } }); networkServer.registerSevice(reportKey, reportService); Thread thread = networkServer.start(port); startReadLine(); System.out.println("Server started on port: " + port); System.out.println("services:"); System.out.println(" report: " + reportKey); System.out.println(" query: " + queryKey); System.out.println("Type 'help' for a list of commands."); String line = readLine(); while (line != null) { try { if (processLine(line) != 0) break; } catch (Throwable e) { e.printStackTrace(); } line = readLine(); } networkServer.stop(); exiting = true; if (thread != null) { try { thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } } static LinkedList<Object> waitingList = new LinkedList<Object>(); static volatile boolean exiting = false; static LinkedList<String> readLines = new LinkedList<String>(); private static String readLine() { synchronized(readLines) { if (!readLines.isEmpty()) return readLines.removeFirst(); } Object wait = new Object(); synchronized(waitingList) { waitingList.addFirst(wait); } try { synchronized(wait) { wait.wait(); } } catch (InterruptedException e) { } synchronized(readLines) { return readLines.removeFirst(); } } private static void startReadLine() { Thread thread = new Thread(new Runnable() { @Override public void run() { String line = null; BufferedReader stream = new BufferedReader(new InputStreamReader(System.in)); try { while(!exiting) { line = stream.readLine(); synchronized(readLines) { readLines.add(line); } Object wait = null; synchronized(waitingList) { if (!waitingList.isEmpty()) wait = waitingList.removeFirst(); } if (wait != null) { synchronized(wait) { wait.notify(); } } } } catch (IOException e1) { e1.printStackTrace(); } } }); thread.start(); } private static int processLine(String line) { String[] lines = line.split(" "); try { Method method = ConsoleNetworkServer.class.getDeclaredMethod("command_" + lines[0], String[].class); Object result = method.invoke(null, new Object[] {lines}); if (result instanceof Integer) return ((Integer) result).intValue(); } catch (NoSuchMethodException e) { System.out.println("Command not recognized: " + line); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { System.out.println("Command not recognized: " + line); } return 0; } private static int command_exit(String[] args) { return -1; } static boolean alwaysContinue = false; private static int command_alwaysContinue(String[] args) { alwaysContinue = !alwaysContinue; System.out.println(Boolean.toString(alwaysContinue)); return 0; } private static int command_help(String[] args) { Method[] methods = ConsoleNetworkServer.class.getDeclaredMethods(); for (Method method : methods) { if (method.getName().startsWith("command_")) { System.out.println(method.getName().split("_")[1]); } } return 0; } static ITransaction transaction = null; private static int command_getLockCount(String[] args) { if (!waitForConnection()) return 0; if (transaction != null) transaction.close(); transaction = queryService.createTransaction(); System.out.println(transaction.getLockCount() + " locks"); return 0; } private static int command_getLock(String[] args) { if (!waitForConnection()) return 0; if (transaction == null) transaction = queryService.createTransaction(); int index = Integer.parseInt(args[1]); ILock lock = transaction.getLocks(index, index + 1)[0]; if (lock == null) System.out.println("lock index(" + index + ") not found"); else { PrintWriter writer = new PrintWriter(System.out); Logger.dumpLockInformation(new ILock[] {lock}, writer); writer.flush(); } return 0; } private static int command_newTransaction(String[] args) { if (!waitForConnection()) return 0; if (transaction != null) transaction.close(); transaction = queryService.createTransaction(); System.out.println("Transaction created: " + transaction.toString()); return 0; } private static int command_getDetails(String[] args) { if (!waitForConnection()) return 0; if (transaction == null) transaction = queryService.createTransaction(); int index = Integer.parseInt(args[1]); int end = index + 1; if (args.length > 2) end = Integer.parseInt(args[2]); ILock[] locks = transaction.getLocks(index, end); if (locks == null) System.out.println("lock index(" + index + ") not found"); else { PrintWriter writer = new PrintWriter(System.out); Logger.dumpLockInformation(locks, writer); writer.flush(); } return 0; } private static int command_getBundleInfo(String[] args) { if (!waitForConnection()) return 0; if (transaction == null) transaction = queryService.createTransaction(); int index = Integer.parseInt(args[1]); int end = index + 1; ILock[] locks = transaction.getLocks(index, end); if (locks == null) System.out.println("lock index(" + index + ") not found"); else { IBundleInfo info = transaction.getBundleInfo(locks[0]); PrintWriter writer = new PrintWriter(System.out); Logger.dumpBundleInfo(info, writer); writer.flush(); } return 0; } static int DEFAULT_PACKET_SIZE = 100; private static int command_getAll(String[] args) { if (!waitForConnection()) return 0; if (transaction == null) transaction = queryService.createTransaction(); int max = transaction.getLockCount(); int index = 0; System.out.println("Listing all locks: ('q' for cancel)..."); while (index < max) { ILock[] locks = transaction.getLocks(index, Math.min(index + DEFAULT_PACKET_SIZE, max)); if (locks == null) System.out.println("lock index(" + index + ") not found"); else { PrintWriter writer = new PrintWriter(System.out); Logger.dumpLockInformation(locks, writer); writer.flush(); } index += DEFAULT_PACKET_SIZE; } System.out.println("done."); return 0; } private static int command_writeAll(String[] args) { if (!waitForConnection()) return 0; if (transaction == null) transaction = queryService.createTransaction(); int max = transaction.getLockCount(); int index = 0; System.out.println("Writing all locks..."); String file = args[1]; long time = System.currentTimeMillis(); File outputFile = new File(file); if (!outputFile.getParentFile().exists()) outputFile.getParentFile().mkdirs(); try { if (!outputFile.exists()) outputFile.createNewFile(); FileWriter writer = new FileWriter(outputFile); while (index < max) { System.out.println("fetching index " + index + " ..."); ILock[] locks = transaction.getLocks(index, Math.min(index + DEFAULT_PACKET_SIZE, max)); if (locks == null) System.out.println("lock index(" + index + ") not found"); else { Logger.dumpLockInformation(locks, writer); } index += DEFAULT_PACKET_SIZE; } writer.close(); } catch (IOException e) { e.printStackTrace(); } System.out.println("done in " + ((System.currentTimeMillis() - time) / 1000.0) + " seconds."); return 0; } private static boolean waitForConnection() { while (!queryService.isConnected()) { System.out.println("Waiting for connection..."); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } if (queryService.isClosed()) { System.out.println("Connection is closed"); return false; } return true; } }