package main.java.com.bag.main;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Runs multiple clients at the same time.
 */
public class MultipleClientRunner
{

    public class OutputPrinter extends Thread
    {
        private InputStream stream;
        private String      clientName;

        public OutputPrinter(String clientName, InputStream stream)
        {
            this.stream = stream;
            this.clientName = clientName;
        }

        @Override
        public void run()
        {
            try
            {
                BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
                String line;
                while ((line = reader.readLine()) != null)
                {
                    System.out.println(clientName + ": " + line);
                }
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }

    public MultipleClientRunner()
    {

    }

    public void runClients(final String option, final int initialClient, final int finalClient, final int totalClients, final int amountsOfServers, final String addresses)
    {
        try
        {
    public void runClients(String option, int initialClient, int finalClient, double percOfWrites, String addresses) {
        try {
            Random rnd = new Random();
            System.out.printf("Starting...\n");
            List<Process> procs = new ArrayList<Process>();
            String[] directAddresses = new String[0];
            if (addresses != null)
            {
                directAddresses = addresses.split(",");
            }

            for (int i = initialClient; i <= finalClient; i++)
            {
                int serverPartner = i % amountsOfServers;
                String cmd;
                if (option.equals("bag")) {
                    cmd = String.format("java -cp build/libs/1.0-0.1-Setup-fat.jar main.java.com.bag.main.RunTests true %d -1 %d %s",
                            serverPartner, i, String.valueOf(percOfWrites).replace(',','.'));
                }
                else if (option.equals("direct"))
                {
                    serverPartner = i % directAddresses.length;
                    String[] address = directAddresses[serverPartner].split(":");
                    cmd = String.format("java -cp build/libs/1.0-0.1-Setup-fat.jar main.java.com.bag.main.RunTests false %s %s %d %s",
                            address[0], address[1], i, String.valueOf(percOfWrites).replace(',','.'));
                }
                else
                {
                    System.out.println("Invalid option " + option);
                    return;
                }
                System.out.printf("Running Command: %s\n", cmd);
                /*ProcessBuilder pb = new ProcessBuilder("/bin/sh", "-e", cmd);
                pb.redirectOutput(ProcessBuilder.Redirect.INHERIT);
                pb.redirectError(ProcessBuilder.Redirect.INHERIT);
                Process proc = pb.start();*/
                Process proc = Runtime.getRuntime().exec(cmd);

                OutputPrinter printer = new MultipleClientRunner.OutputPrinter("Client " + i, proc.getInputStream());
                printer.start();
                procs.add(proc);
                Thread.sleep(rnd.nextInt(200));
            }

            for (Process p : procs)
            {
                p.waitFor();
            }

            System.out.printf("Finishing...\n");
        }
        catch (Throwable t)
        {
            t.printStackTrace();
        }
    }

    public static void main(String[] args)
    {
        String opt = args[0];
        String address = null;
        int initialClient = Integer.parseInt(args[1]);
        int finalClient = Integer.parseInt(args[2]);
        double percOfWrites = Double.parseDouble(args[3]);
        if (args.length > 4)
            address = args[4];

        MultipleClientRunner runner = new MultipleClientRunner();
        runner.runClients(opt, initialClient, finalClient, percOfWrites, address);
    }
}

@@ -1006,109 +1006,254 @@
     
-public MultipleClientRunner()%0A    %7B%0A%0A    %7D%0A%0A    public void runClients(final String option, final int
+/**%0A     * Standard constructor.%0A     */%0A    public MultipleClientRunner()%0A    %7B%0A        /*%0A         * Intentionally lef empty.%0A         */%0A    %7D%0A%0A    /**%0A     * Run defined number of clients.%0A     * @param option (if bag or direct)%0A     * @param
  ini
@@ -1266,147 +1266,250 @@
 ient
-,
  fi
-nal int finalClient, final int totalClients, final int amountsOfServers, final String addresses)%0A    %7B%0A        try
+rst client id%0A     * @param finalClient last client id%0A     * @param percOfWrites percentage of writes%0A     * @param amountsOfServers amount of servers to contact%0A     * @param addresses addresses of servers to contact.
 %0A     
-   %7B
+*/
 %0A    p
-ublic
+rivate
  voi
@@ -1521,16 +1521,22 @@
 Clients(
+final 
 String o
@@ -1541,16 +1541,22 @@
  option,
+ final
  int ini
@@ -1566,16 +1566,22 @@
 lClient,
+ final
  int fin
@@ -1589,16 +1589,22 @@
 lClient,
+ final
  double 
@@ -1616,16 +1616,50 @@
 fWrites,
+ final int amountsOfServers, final
  String 
@@ -1668,16 +1668,20 @@
 dresses)
+%0A   
  %7B%0A     
@@ -1686,16 +1686,24 @@
      try
+%0A       
  %7B%0A     
@@ -2222,16 +2222,32 @@
 (%22bag%22))
+%0A               
  %7B%0A     
@@ -2454,32 +2454,33 @@
 es).replace(',',
+ 
 '.'));%0A         
@@ -2933,16 +2933,17 @@
 ace(',',
+ 
 '.'));%0A 
@@ -4262,24 +4262,81 @@
 e(args%5B3%5D);%0A
+        int amountOfServers = Integer.parseInt(args%5B4%5D);%0A
         if (
@@ -4353,23 +4353,29 @@
 h %3E 
-4
+5
 )%0A    
+  
+  %7B%0A
         
 addr
@@ -4366,24 +4366,28 @@
   %7B%0A        
+    
 address = ar
@@ -4393,11 +4393,21 @@
 rgs%5B
-4
+5
 %5D;
+%0A        %7D
 %0A%0A  
@@ -4542,16 +4542,33 @@
 fWrites,
+ amountOfServers,
  address

Clean up merge problems