/** * SAMOA - PROTOCOL FRAMEWORK * Copyright (C) 2005 Olivier Rütti (EPFL) (olivier.rutti@a3.epfl.ch) * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package seqSamoa.test.staticRecovery; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Iterator; import seqSamoa.BoundModuleOrderManager; import seqSamoa.Callback; import seqSamoa.ConcurrencyManager; import seqSamoa.RouteModuleOrderManager; import seqSamoa.SamoaFlowControl; import seqSamoa.SamoaScheduler; import seqSamoa.SequentialManager; import seqSamoa.SimpleModuleOrderManager; import seqSamoa.api.ApiSamoaCrashRecoveryAbcastStackCommit; import seqSamoa.exceptions.AlreadyBoundServiceException; import seqSamoa.services.abcast.AbcastResponseParameters; import seqSamoa.services.commit.NbCommitsCallParameters; import uka.transport.Transportable; import framework.PID; import framework.libraries.BinaryStableStorage; import framework.libraries.serialization.THashMap; import framework.libraries.serialization.TInteger; import framework.libraries.serialization.TLinkedList; import framework.libraries.serialization.TLong; import framework.libraries.serialization.TMap; import framework.libraries.serialization.TString; public class AbcastMainCommit implements Callback { private static long start = 0; static ApiSamoaCrashRecoveryAbcastStackCommit stack; private static long applState = 0; private static long nb_checks = 0; private static TMap checkpoints = null; private static BinaryStableStorage storage = null; // Buffer for the standard input private static BufferedReader in = new BufferedReader( new InputStreamReader(System.in)); public static void main(String args[]) { try { if ((args.length != 3) || (Integer.parseInt(args[2]) < 1) || (Integer.parseInt(args[2]) > 5)) { System.err .println("Usage:: main <num_port> <num_incarnation> <concurrency_manager>"); System.err .println(" concurrency_manager = 1 ====> SequentialManager"); System.err .println(" concurrency_manager = 2 ====> SimpleModuleOrderManager"); System.err .println(" concurrency_manager = 3 ====> BoundModuleOrderManager"); System.err .println(" concurrency_manager = 4 ====> RouteModuleOrderManager"); System.exit(1); } int port = Integer.parseInt(args[0]); int inc = Integer.parseInt(args[1]); int managerID = Integer.parseInt(args[2]); PID myself; try { // Initialize myself myself = new PID(InetAddress.getLocalHost(), port, inc); } catch (UnknownHostException e) { throw new RuntimeException( "IP address for local host not found!"); } // 1. Initialisation BufferedReader in = new BufferedReader(new InputStreamReader( System.in)); String line; boolean debugMode = false; // 2. Welcome System.out .println("+-----------------------------------------------+"); System.out .println("| CACTUS TEST |"); System.out .println("+-----------------------------------------------+"); System.out .println("| Abcast layer test (Crash recovery with commit) |"); System.out .println("+-----------------------------------------------+"); System.out .println("LOCALHOST.ip = " + InetAddress.getLocalHost()); System.out.println("LOCALHOST.port = " + port); System.out.println("LOCALHOST.inc = " + inc); // 3. Get processes TLinkedList processes = new TLinkedList(); do { PID pid; System.out.println("PID to add."); pid = readPID(); processes.addLast(pid); System.out.println("Added process: " + pid.toString()); System.out .print("Press 'y' to add more. Press ENTER if you are done: "); line = readLine(); } while (!line.equals("") && !line.equals("OR") && !line.equals("KC")); if (line.equals("OR")) { PID pid; processes.clear(); pid = readPID("lsepc32.epfl.ch", "2765", "0"); processes.addLast(pid); pid = readPID("lsepc32.epfl.ch", "2766", "0"); processes.addLast(pid); pid = readPID("lsepc32.epfl.ch", "2777", "0"); processes.addLast(pid); } else if (line.equals("KC")) { PID pid; processes.clear(); pid = readPID("lsec1.epfl.ch", "2765", "0"); processes.addLast(pid); pid = readPID("lsec2.epfl.ch", "2765", "0"); processes.addLast(pid); pid = readPID("lsec8.epfl.ch", "2765", "0"); processes.addLast(pid); } System.out .println("\nDo you want the protocol to be UNIFORM (Y/n)?"); line = in.readLine(); boolean uniform = !(line.equals("n") || line.equals("N")); System.out.println("There are " + processes.size() + " processes registered"); // 4. Create and couple composite String path = "tmp/CRabcastCommit_" + InetAddress.getLocalHost().getHostName() + "_" + port + "_" + inc + ".application"; storage = new BinaryStableStorage(path); Object temp = storage.retrieve(0, 0); if (temp == null) { // We are not recovering checkpoints = new THashMap(); // each item = (nb_checkpoints, state) checkpoints.put(new TLong(0), new TLong(0)); storage.store(0, 0, checkpoints, true); } else { // We are recovering checkpoints = (TMap) temp; } System.out.println("Creating Cactus composite..."); ConcurrencyManager manager; switch (managerID) { case 1: manager = new SequentialManager(); break; case 2: manager = new SimpleModuleOrderManager(2); break; case 3: manager = new BoundModuleOrderManager(2); break; case 4: manager = new RouteModuleOrderManager(2); break; default: manager = new SequentialManager(); break; } stack = new ApiSamoaCrashRecoveryAbcastStackCommit(myself, processes, new SamoaScheduler(manager), new SamoaFlowControl(100), new AbcastMainCommit(), uniform, null); try { stack.init(); } catch (AlreadyBoundServiceException abse) { System.err.println("Can load the stack!"); System.exit(1); } // 5. Main loop line = ""; System.out.println("\nType messages to be sent after the prompt."); help(); while (!line.equals("exit") && !line.equals("kill")) { if (line.equals("dump")) { stack.sendDump(System.err); } else if (line.equals("help")) { help(); } else if (line.equals("debug")) { debugMode = !debugMode; System.out.println("Debug mode: " + debugMode); stack.sendDebug(debugMode); } else if (line.equals("cp")) { // We need to pass a reference!!! Runnable r = new Runnable() { @SuppressWarnings("unchecked") public void run() { nb_checks++; TMap cp2 = new THashMap(); Iterator it = checkpoints.keySet().iterator(); while (it.hasNext()) { TLong i = (TLong) it.next(); if (i.longValue() > nb_checks - 2) cp2.put(i, checkpoints.get(i)); } checkpoints = cp2; checkpoints.put(new TLong(nb_checks), new TLong( applState)); storage.store(0, 0, checkpoints, true); } }; stack.commit(r); } else if (line.equals("flood")) { System.out.print("First number > "); int inf = (new Integer(readLine())).intValue(); System.out.print("Last number > "); int sup = (new Integer(readLine())).intValue(); System.out.print(" Message length (ENTER -> 0) > "); int l = 0; try { l = (new Integer(in.readLine())).intValue(); } catch (Exception exc) { } System.out.print(" Sleep time (ENTER -> 0) > "); int s = 0; try { s = (new Integer(in.readLine())).intValue(); } catch (Exception exc) { } for (int i = inf; i < sup; i++) { Integer fl = new Integer(i); TLinkedList toSend = new TLinkedList(); if (i == inf) toSend .addLast(new TLong(System .currentTimeMillis())); toSend.addLast(new TString("FLOOD MESSAGE " + fl)); toSend.addLast(new TLong(System.currentTimeMillis())); for (int j = 0; j < l / 16; j++) toSend.addLast(new TInteger(j)); try { stack.abcastMessage(toSend); if (s > 0) Thread.sleep(s); } catch (InterruptedException ex) { System.err.println("Sleep Interrupted"); } } } else if (!line.equals("")) { stack.abcastMessage(new TString(line)); } System.out.print("> "); line = in.readLine(); } // while // exiting if (line.equals("kill")) System.exit(1); stack.finalize(); // bye try { Thread.sleep(1000); } catch (Exception e) { } System.exit(0); } catch (Exception ex) { System.err.println("CrashRecovery: TestAbcast: An error occured."); System.err.println(ex.toString()); ex.printStackTrace(); System.err.println("Application must close."); System.exit(1); } } private static void help() { System.out.println("\nType messages to be sent after the prompt."); System.out.println(" Available commands: "); System.out.println(" 'help' to show this menu"); System.out.println(" 'exit' for a PERMANENT crash (logs deleted)"); System.out .println(" 'kill' for a TEMPORARY crash (logs not deleted)"); System.out.println(" 'dump' to dump the stack"); System.out.println(" 'debug' to enable/disable logging"); System.out.println(" 'cp' to make an Application Checkpoint"); System.out.println(" 'flood' to send several messages at full speed"); } // Read a line form standard input static private String readLine() { String str = null; try { str = in.readLine(); } catch (IOException e) { System.err.println("MicroTest : readLine : Erreur le lecture!"); } if (str == null) { in = new BufferedReader(new InputStreamReader(System.in)); return readLine(); } return str; } // Ask user for a PID static private PID readPID() { String host = null; int port = 0; int incarnation = 0; String str = null; System.out.print("Host name :"); host = readLine(); System.out.print("Port number: "); port = Integer.parseInt(readLine()); System.out.print("Incarnation number (ENTER -> 0) :"); str = readLine(); if (!str.equals("")) { incarnation = Integer.parseInt(str); } PID p = null; try { p = new PID(InetAddress.getByName(host), port, incarnation); } catch (UnknownHostException e) { System.err.println("MicroTestFD : readPID : UnknownHostException"); } return p; } // Return a PID created thanks to the parameters static private PID readPID(String host, String Port, String Incar) { int port = 0; int incarnation = 0; port = Integer.parseInt(Port); incarnation = Integer.parseInt(Incar); PID p = null; try { p = new PID(InetAddress.getByName(host), port, incarnation); } catch (UnknownHostException e) { System.err.println("MicroTestFD : readPID : UnknownHostException"); } return p; } public void serviceCallback(Object infos, Transportable message) { if (infos instanceof AbcastResponseParameters) { applState++; TLinkedList msg = (TLinkedList) message; if (msg.getFirst() instanceof TLong) start = ((TLong) msg.removeFirst()).longValue(); System.out.println("ADeliver: " + msg.removeFirst() + " TEMPS ECOULE: " + (System.currentTimeMillis() - start) + " LATENCE MESSAGE: " + (System.currentTimeMillis() - ((TLong) msg.removeFirst()) .longValue())); } else if (infos instanceof NbCommitsCallParameters) { NbCommitsCallParameters commitInfos = (NbCommitsCallParameters) infos; nb_checks = commitInfos.nbCommits.longValue(); TLong newState = (TLong) checkpoints.get(new TLong(nb_checks)); applState = newState.longValue(); System.out.println("**Nb_commits event received. Value: " + nb_checks + ". New application state: " + newState); } } }