diff --git a/storage/test.txt b/dstore/test.txt
similarity index 100%
rename from storage/test.txt
rename to dstore/test.txt
diff --git a/storage/test2.txt b/dstore/test2.txt
similarity index 100%
rename from storage/test2.txt
rename to dstore/test2.txt
diff --git a/storage/test1.txt b/dstore2/test.txt
similarity index 100%
rename from storage/test1.txt
rename to dstore2/test.txt
diff --git a/dstore2/test2.txt b/dstore2/test2.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/dstore2/test3.txt b/dstore2/test3.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/dstore3/test.txt b/dstore3/test.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/dstore3/test2.txt b/dstore3/test2.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/dstore3/test3.txt b/dstore3/test3.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/dstore3/test4.txt b/dstore3/test4.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/nioExampleFiles/AbstractTest.java b/nioExampleFiles/AbstractTest.java
deleted file mode 100644
index 14383e74570f71d0f1f8127cc3601a23c85da5c7..0000000000000000000000000000000000000000
--- a/nioExampleFiles/AbstractTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-import static org.junit.Assert.assertEquals;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-
-public abstract class AbstractTest {
-
-    protected static final String SRC = "/README.md";
-    protected static final String TARGET = "/tmp/output";
-    protected static final long AWAIT_TEST_COMPLETE = 20000l;
-
-    protected File srcFile;
-    protected File targetFile;
-
-    @BeforeClass
-    public static void init() {
-        Thread.currentThread().getContextClassLoader().setDefaultAssertionStatus(true);
-    }
-
-    @AfterClass
-    public static void destroy() {
-        Thread.currentThread().getContextClassLoader().setDefaultAssertionStatus(false);
-    }
-
-    @Before
-    public void setUp() throws IOException {
-        this.srcFile = new File(SRC);
-        this.targetFile = new File(TARGET + "/" + this.srcFile.getName());
-
-        Files.deleteIfExists(this.targetFile.toPath());
-    }
-
-    protected final void compare() {
-        assertEquals("file did not copy completely", this.srcFile.length(), this.targetFile.length());
-    }
-}
diff --git a/nioExampleFiles/Constants.java b/nioExampleFiles/Constants.java
deleted file mode 100644
index 269cb7b84167b377484480da7158b08738131cdc..0000000000000000000000000000000000000000
--- a/nioExampleFiles/Constants.java
+++ /dev/null
@@ -1,15 +0,0 @@
-public final class Constants {
-
-    public static final String INSTANTIATION_NOT_ALLOWED = "Instantiation not allowed";
-    public static final long TRANSFER_MAX_SIZE = (1024 * 1024);
-    public static final int BUFFER_SIZE = 2048;
-
-    public static final String END_MESSAGE_MARKER = ":END";
-    public static final String MESSAGE_DELIMITTER = "#";
-
-    public static final String CONFIRMATION = "OK";
-
-    private Constants() {
-        throw new IllegalStateException(INSTANTIATION_NOT_ALLOWED);
-    }
-}
diff --git a/nioExampleFiles/FileCopyTest.java b/nioExampleFiles/FileCopyTest.java
deleted file mode 100644
index a3997380e511b51f1e12f97e40ef78db747edcb1..0000000000000000000000000000000000000000
--- a/nioExampleFiles/FileCopyTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-import java.io.IOException;
-import java.util.concurrent.CountDownLatch;
-
-import org.junit.Test;
-
-public class FileCopyTest extends AbstractTest {
-
-    private static final int PORT = 9999;
-
-    @Test
-    public void copyLargeFile() throws IOException, InterruptedException {
-        final CountDownLatch latch = new CountDownLatch(1);
-        final FileReceiver receiver = new FileReceiver(PORT, new FileWriter(TARGET + "/" + super.srcFile.getName()), super.srcFile.length());
-
-        new Thread() {
-            public void run() {
-                try {
-                    receiver.receive();
-                } catch (IOException e) {
-
-                } finally {
-                    latch.countDown();
-                }
-            }
-        }.start();
-
-        final FileReader reader = new FileReader(new FileSender(PORT), SRC);
-        reader.read();
-
-        latch.await();
-        compare();
-    }   
-}
diff --git a/nioExampleFiles/FileReader.java b/nioExampleFiles/FileReader.java
deleted file mode 100644
index e66f754cd5b562b55d2f9934e5bc1e4edf3d1152..0000000000000000000000000000000000000000
--- a/nioExampleFiles/FileReader.java
+++ /dev/null
@@ -1,37 +0,0 @@
-import java.io.IOException;
-import java.nio.channels.FileChannel;
-import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
-import java.util.Objects;
-
-final class FileReader {
- 
-    private final FileChannel channel;
-    private final FileSender sender;
- 
-    FileReader(final FileSender sender, final String path) throws IOException {
-        if (Objects.isNull(sender) || path == "") {
-            throw new IllegalArgumentException("sender and path required");
-        }
- 
-        this.sender = sender;
-        this.channel = FileChannel.open(Paths.get(path), StandardOpenOption.READ);
-    }
- 
-    void read() throws IOException {
-        try {
-            transfer();
-        } finally {
-            close();
-        }
-    }
- 
-    void close() throws IOException {
-        this.sender.close();
-        this.channel.close();
-    }
- 
-    private void transfer() throws IOException {
-        this.sender.transfer(this.channel, 0l, this.channel.size());
-    }
-}
\ No newline at end of file
diff --git a/nioExampleFiles/FileReceiver.java b/nioExampleFiles/FileReceiver.java
deleted file mode 100644
index eaf3e26e8ebca01ad5d6937534824f3b401e7b3e..0000000000000000000000000000000000000000
--- a/nioExampleFiles/FileReceiver.java
+++ /dev/null
@@ -1,48 +0,0 @@
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.nio.channels.ServerSocketChannel;
-import java.nio.channels.SocketChannel;
-import java.util.Objects;
-
-final class FileReceiver {
- 
-    private final int port;
-    private final FileWriter fileWriter;
-    private final long size;
- 
-    FileReceiver(final int port, final FileWriter fileWriter, final long size) {
-        this.port = port;
-        this.fileWriter = fileWriter;
-        this.size = size;
-    }
- 
-    void receive() throws IOException {
-        SocketChannel channel = null;
- 
-        try (final ServerSocketChannel serverSocketChannel = ServerSocketChannel.open()) {
-            init(serverSocketChannel);
- 
-            channel = serverSocketChannel.accept();
- 
-            doTransfer(channel);
-        } finally {
-            if (!Objects.isNull(channel)) {
-                channel.close();
-            }
- 
-            this.fileWriter.close();
-        }
-    }
- 
-    private void doTransfer(final SocketChannel channel) throws IOException {
-        assert !Objects.isNull(channel);
- 
-        this.fileWriter.transfer(channel, this.size);
-    }
- 
-    private void init(final ServerSocketChannel serverSocketChannel) throws IOException {
-        assert !Objects.isNull(serverSocketChannel);
- 
-        serverSocketChannel.bind(new InetSocketAddress(this.port));
-    }
-}
\ No newline at end of file
diff --git a/nioExampleFiles/FileSender.java b/nioExampleFiles/FileSender.java
deleted file mode 100644
index f0c3a0b66b1eaff0a0890d1451a29e3ee7f26c50..0000000000000000000000000000000000000000
--- a/nioExampleFiles/FileSender.java
+++ /dev/null
@@ -1,32 +0,0 @@
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.nio.channels.FileChannel;
-import java.nio.channels.SocketChannel;
-import java.util.Objects;
-
-final class FileSender {
- 
-    private final InetSocketAddress hostAddress;
-    private SocketChannel client;
- 
-    FileSender(final int port) throws IOException {
-        this.hostAddress = new InetSocketAddress(port);
-        this.client = SocketChannel.open(this.hostAddress);
-    }
- 
-    void transfer(final FileChannel channel, long position, long size) throws IOException {
-        assert !Objects.isNull(channel);
- 
-        while (position < size) {
-            position += channel.transferTo(position, Constants.TRANSFER_MAX_SIZE, this.client);
-        }
-    }
-     
-    SocketChannel getChannel() {
-        return this.client;
-    }
- 
-    void close() throws IOException {
-        this.client.close();
-    }
-}
\ No newline at end of file
diff --git a/nioExampleFiles/FileWriter.java b/nioExampleFiles/FileWriter.java
deleted file mode 100644
index e0be9b8e897c7028cef6bbf2b353df8947681974..0000000000000000000000000000000000000000
--- a/nioExampleFiles/FileWriter.java
+++ /dev/null
@@ -1,44 +0,0 @@
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.FileChannel;
-import java.nio.channels.SocketChannel;
-import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
-import java.util.Objects;
-
-final class FileWriter {
- 
-    private final FileChannel channel;
- 
-    FileWriter(final String path) throws IOException {
-        if (path == "") {
-            throw new IllegalArgumentException("path required");
-        }
- 
-        this.channel = FileChannel.open(Paths.get(path), StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW);
-    }
- 
-    void transfer(final SocketChannel channel, final long bytes) throws IOException {
-        assert !Objects.isNull(channel);
- 
-        long position = 0l;
-        while (position < bytes) {
-            position += this.channel.transferFrom(channel, position, Constants.TRANSFER_MAX_SIZE);
-        }
-    }
-     
-    int write(final ByteBuffer buffer, long position) throws IOException {
-        assert !Objects.isNull(buffer);
- 
-        int bytesWritten = 0;        
-        while(buffer.hasRemaining()) {
-            bytesWritten += this.channel.write(buffer, position + bytesWritten);            
-        }
-         
-        return bytesWritten;
-    }
- 
-    void close() throws IOException {
-        this.channel.close();
-    }
-}
\ No newline at end of file
diff --git a/src/ftp/Controller.java b/src/ftp/Controller.java
index 608d9fef7b55ebec2f055fd2d6e09678bce37fa2..008ccf6494c150909d8261abfb17e443205254e1 100644
--- a/src/ftp/Controller.java
+++ b/src/ftp/Controller.java
@@ -11,10 +11,12 @@ import java.util.stream.Stream;
 
 public class Controller extends Server {
 
-    int r;
-    int rbPeriod;
+    private int r;
+    private int rbPeriod;
+    private int nextID = 0;
 
-    private ArrayList<DstoreConnection> index;
+    private DstoreIndex dstoreIndex;
+    private FileIndex fileIndex;
 
 
     /**
@@ -30,7 +32,8 @@ public class Controller extends Server {
         this.timeout = timeout;
         this.rbPeriod = rbPeriod;
 
-        index = new ArrayList<DstoreConnection>();
+        dstoreIndex = new DstoreIndex();
+        fileIndex = new FileIndex();
 
         start();
     }
@@ -56,6 +59,8 @@ public class Controller extends Server {
 
         switch(args[0]) {
             case "JOIN":
+                Integer port = Integer.parseInt(args[1]);
+
                 send("LIST", client);
 
                 String files = readSocket(client);
@@ -63,15 +68,38 @@ public class Controller extends Server {
                 // todo use stream instead
                 //
                 List<String[]> filesInfo = new ArrayList<String[]>() {{
-                    String[] filesAndSizes = files.split(" | ");
+                    String[] filesAndSizes = files.split("\\|");
                     for (String file : filesAndSizes) add(file.split(" "));
                 }};
 
-                System.out.println("test");
+                dstoreIndex.addDstore(filesInfo, port, nextID);
+                threadIDOutput("New Dstore (ID: " + nextID + ") successfully joined");
+                nextID++;
+
+
+                send ("ACK", client);
+
+                break;
+
+            case "STORE":
+                String filename = args[1];
+                Long filesize = Long.parseLong(args[2]);
+
+                DstoreFile file = fileIndex.addFile(filename,filesize);
+
+                file.setStoreInProgress(true);
+
+
+                List<DstoreConnection> dstores = dstoreIndex.getFirstN(r);
+
+                dstores.stream().forEach(x -> x.addFile(file));
+
+                String ports = dstores.stream().
+                        map(x -> Integer.toString(x.getPort())).
+                        collect(Collectors.joining(" "));
 
-                index.add(new DstoreConnection(filesInfo, Integer.parseInt(args[1])));
 
-                threadIDOutput(index.get(0).getFile_index().getFile(0).getFilename());
+                send("STORE_TO " + ports, client);
 
                 break;
         }
diff --git a/src/ftp/Dstore.java b/src/ftp/Dstore.java
index f46db3b206433e88901fb6548b7d3dfdc5df9829..8c9091df6b773c6642910c3e3fb749eb0be6e558 100644
--- a/src/ftp/Dstore.java
+++ b/src/ftp/Dstore.java
@@ -31,19 +31,36 @@ public class Dstore extends Server {
      * @param timeout timeout (ms)
      * @param file_folder where to store data locally
      */
-    public Dstore(int port, int cport, int timeout, String file_folder) throws IOException{
+    public Dstore(int port, int cport, int timeout, String file_folder) {
         this.port = port;
         this.cport = cport;
         this.timeout = timeout;
         this.file_folder = file_folder;
 
-        Socket controller = new Socket("localhost",cport);
+        Socket controller = null;
 
-        send("JOIN " + port, controller);
 
-        handleRequest(readSocket(controller), controller);
+        Boolean joined = false;
+        for (int i = 0; (i < 10) && !joined; i++) {
+            try { controller = new Socket("localhost",cport); joined = true; }
+            catch(IOException e) {
+                threadIDErr(e.getMessage());
+            }
+
+            try {threadIDErr("Retrying Connection..."); Thread.sleep(1000);}
+            catch(InterruptedException e) {threadIDErr(e.getMessage());}
+        }
+
+
+        if (controller != null) {
+            send("JOIN " + port, controller);
+            handleRequest(readSocket(controller), controller);
+            start();
+        }
+        else {
+            threadIDErr("Unable to connect to Controller");
+        }
 
-        start();
     }
 
 
@@ -55,11 +72,8 @@ public class Dstore extends Server {
         List<Integer> intArgs = str.map(x -> {return Integer.parseInt(x);})
                 .collect(Collectors.toList());
 
-        try {
-            Dstore dstore = new Dstore(intArgs.get(0), intArgs.get(1), intArgs.get(2), args[3]);
-        } catch (IOException e) {
-            System.out.println("IOException " + e.getMessage());
-        }
+
+        Dstore dstore = new Dstore(intArgs.get(0), intArgs.get(1), intArgs.get(2), args[3]);
     }
 
 
@@ -70,7 +84,7 @@ public class Dstore extends Server {
 
         switch(args[0]) {
             case "LIST":
-                File folder = new File("storage");
+                File folder = new File(file_folder);
 
 
                 //todo use stream instead
@@ -79,15 +93,30 @@ public class Dstore extends Server {
                     for (File file : folder.listFiles()) add(file.getName() + " " + file.length());
                 }};
 
+                // todo use joining instead of reduce
+                //
                 String ident = files.get(0);
                 files.remove(0);
 
                 String fileMessage = files.stream()
-                        .reduce(ident, (file1, file2) -> (file1 + " | " + file2));
+                        .reduce( ident, (file1, file2) -> (file1 + "|" + file2) );
+
 
                 send(fileMessage, client);
 
+
+                String response = readSocket(client);
+                if (response.equals("ACK")) threadIDOutput("Successfully joined Controller");
+
                 break;
+
+            case "STORE":
+                String filename = args[1];
+                Long filesize = Long.parseLong(args[2]);
+
+                send("ACK", client);
+
+
         }
     }
 
diff --git a/src/ftp/DstoreConnection.java b/src/ftp/DstoreConnection.java
index eeab5e5894c300197a91422bcec994b8029fe71a..8ded0f94e655c2938a2cc9254e18eb281e913d73 100644
--- a/src/ftp/DstoreConnection.java
+++ b/src/ftp/DstoreConnection.java
@@ -5,22 +5,28 @@ import java.util.stream.Collectors;
 
 public class DstoreConnection {
 
-    private Index file_index;
+    private FileIndex file_index;
     private int port;
+    private int id;
 
 
-    public DstoreConnection(List<String[]> files, int port) {
+    public DstoreConnection(List<String[]> files, int port, int id) {
         this.port = port;
+        this.id = id;
 
         List<DstoreFile> dstoreFiles = files.stream()
-                .map(x -> {return new DstoreFile(x[0],Long.parseLong(x[1]));})
+                .map(x -> new DstoreFile(x[0],Long.parseLong(x[1])))
                 .collect(Collectors.toList());
 
-        file_index = new Index(dstoreFiles);
+        file_index = new FileIndex(dstoreFiles);
     }
 
 
-    public Index getFile_index() {
-        return file_index;
-    }
+    public void addFile(String filename, Long filesize) { file_index.addFile(filename,filesize); }
+
+    public void addFile(DstoreFile file) { file_index.add(file); }
+
+
+    public int getPort() { return port; }
+
 }
diff --git a/src/ftp/DstoreFile.java b/src/ftp/DstoreFile.java
index 655d8b8ecf4b27011fd0bf4029ffc754788f9301..3e91f3cd15b94ede9eaefee44364e346d2dcb07a 100644
--- a/src/ftp/DstoreFile.java
+++ b/src/ftp/DstoreFile.java
@@ -24,6 +24,12 @@ public class DstoreFile {
     public boolean isRemoveComplete() {return removeComplete;}
 
 
+    public void setStoreInProgress(Boolean store) { storeInProgress = store; }
+    public void setStoreComplete(Boolean complete) { storeComplete = complete; }
+    public void setRemoveInProgress(Boolean remove) { removeInProgress = remove; }
+    public void setRemoveComplete(Boolean complete) { removeComplete = complete; }
+
+
     public String getFilename() { return filename; }
     public Long getFilesize() { return filesize; }
 }
diff --git a/src/ftp/DstoreIndex.java b/src/ftp/DstoreIndex.java
new file mode 100644
index 0000000000000000000000000000000000000000..88532cf1090fa067ea1bdbda2643058fd98cc254
--- /dev/null
+++ b/src/ftp/DstoreIndex.java
@@ -0,0 +1,20 @@
+package ftp;
+
+import java.util.List;
+
+public class DstoreIndex extends Index<DstoreConnection> {
+
+    public DstoreIndex() {}
+
+    public DstoreIndex(List<DstoreConnection> list) {
+        super(list);
+    }
+
+
+    public DstoreConnection addDstore(List<String[]> files, int port, int id) {
+        DstoreConnection dstore = new DstoreConnection(files,port,id);
+        add(dstore);
+        return dstore;
+    }
+
+}
diff --git a/src/ftp/FileIndex.java b/src/ftp/FileIndex.java
new file mode 100644
index 0000000000000000000000000000000000000000..d79efc1319921b1a8199e276fc115b2f03e9f336
--- /dev/null
+++ b/src/ftp/FileIndex.java
@@ -0,0 +1,20 @@
+package ftp;
+
+import java.util.List;
+
+public class FileIndex extends Index<DstoreFile>{
+
+    public FileIndex() {}
+
+    public FileIndex(List<DstoreFile> list) {
+        super(list);
+    }
+
+
+    public DstoreFile addFile(String filename, Long filesize) {
+        DstoreFile file = new DstoreFile(filename,filesize);
+        add(file);
+        return file;
+    }
+
+}
diff --git a/src/ftp/Index.java b/src/ftp/Index.java
index a308aa0890f1c27b38e3ada2e2b7eae893e95e27..cebeb419a2b612d26afe03124b82f8fc72577030 100644
--- a/src/ftp/Index.java
+++ b/src/ftp/Index.java
@@ -2,30 +2,19 @@ package ftp;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
-public class Index {
+public class Index<E> extends ArrayList<E> {
 
-    private List<DstoreFile> files;
+    public Index() {}
 
-
-    public Index() {
-        files = new ArrayList<DstoreFile>();
-    }
-
-    public Index(List<DstoreFile> files) {
-        this.files = new ArrayList<DstoreFile>(files);
+    public Index(List<E> list) {
+        super(list);
     }
 
 
-
-    public void addFile(String filename, Long filesize) {
-        files.add(new DstoreFile(filename,filesize));
+    public List<E> getFirstN(int n) {
+        return stream().limit(n).collect(Collectors.toList());
     }
 
-    public List<DstoreFile> getIndex() {
-        return files;
-    }
-
-    public DstoreFile getFile(int index) { return files.get(index); }
-
 }
diff --git a/src/ftp/Server.java b/src/ftp/Server.java
index 16d0e789d4f4b67f2fc0ae75005ded40113c4d70..aba6c7ccf5e46a7c1987ed83e01fd9f7c8c5ebd8 100644
--- a/src/ftp/Server.java
+++ b/src/ftp/Server.java
@@ -23,7 +23,9 @@ public abstract class Server {
                                 String request = readSocket(client);
                                 handleRequest(request, client);
                                 client.close();
-                            } catch (Exception e) {}
+                            } catch (Exception e) {
+                                threadIDErr("Exception thrown: " + e.getMessage());
+                            }
                         }
                     }).start();
                 } catch (Exception e) {
diff --git a/testing/ClientMain.class b/testing/ClientMain.class
new file mode 100644
index 0000000000000000000000000000000000000000..27b4b0711be390b9e87535c87d214850f4561f7f
Binary files /dev/null and b/testing/ClientMain.class differ
diff --git a/testingWithClient/ClientMain.java b/testing/ClientMain.java
similarity index 53%
rename from testingWithClient/ClientMain.java
rename to testing/ClientMain.java
index 17d0fe134845c56ee9b976bfc0ad0af04498161f..0c124ad351c700dbce50edee6eba64001eac82c5 100644
--- a/testingWithClient/ClientMain.java
+++ b/testing/ClientMain.java
@@ -13,63 +13,11 @@ public class ClientMain {
 		if (!downloadFolder.exists())
 			if (!downloadFolder.mkdir()) throw new RuntimeException("Cannot create download folder (folder absolute path: " + downloadFolder.getAbsolutePath() + ")");
 		
-		File uploadFolder = new File("to_store");
-		if (!uploadFolder.exists())
-			throw new RuntimeException("to_store folder does not exist");
 		
-		// testClient(cport, timeout, downloadFolder);
+		testClient(cport, timeout, downloadFolder);
 		
-		// example to launch a number of concurrent clients, each doing the same operations
-		for (int i = 0; i < 10; i++) {
-			new Thread() {
-				public void run() {
-					test2Client(cport, timeout, downloadFolder, uploadFolder);
-				}
-			}.start();
-		}
 	}
 	
-	public static void test2Client(int cport, int timeout, File downloadFolder, File uploadFolder) {
-		Client client = null;
-		
-		try {
-			client = new Client(cport, timeout, Logger.LoggingType.ON_FILE_AND_TERMINAL);
-			client.connect();
-			Random random = new Random(System.currentTimeMillis() * System.nanoTime());
-			
-			File fileList[] = uploadFolder.listFiles();
-			for (int i=0; i<fileList.length/2; i++) {
-				File fileToStore = fileList[random.nextInt(fileList.length)];
-				try {					
-					client.store(fileToStore);
-				} catch (Exception e) {
-					System.out.println("Error storing file " + fileToStore);
-					e.printStackTrace();
-				}
-			}
-			
-			String list[] = null;
-			try { list = list(client); } catch(IOException e) { e.printStackTrace(); }
-			
-			for (int i = 0; i < list.length/4; i++) {
-				String fileToRemove = list[random.nextInt(list.length)];
-				try {
-					client.remove(fileToRemove);
-				} catch (Exception e) {
-					System.out.println("Error remove file " + fileToRemove);
-					e.printStackTrace();
-				}
-			}
-			
-			try { list = list(client); } catch(IOException e) { e.printStackTrace(); }
-			
-		} catch(IOException e) {
-			e.printStackTrace();
-		} finally {
-			if (client != null)
-				try { client.disconnect(); } catch(Exception e) { e.printStackTrace(); }
-		}
-	}
 	
 	public static void testClient(int cport, int timeout, File downloadFolder) {
 		Client client = null;
@@ -82,7 +30,7 @@ public class ClientMain {
 			
 //			try { list(client); } catch(IOException e) { e.printStackTrace(); }
 			
-			try { client.store(new File("Clipboard01.pdf")); } catch(IOException e) { e.printStackTrace(); }
+			try { client.store(new File("test.txt")); } catch(IOException e) { e.printStackTrace(); }
 			
 //			try { client.store(new File("Clipboard01.pdf")); } catch(IOException e) { e.printStackTrace(); }
 //
diff --git a/testing/ControllerLogger.java b/testing/ControllerLogger.java
new file mode 100644
index 0000000000000000000000000000000000000000..e178d3c3979ba19673823adcc1f544ad825a3877
--- /dev/null
+++ b/testing/ControllerLogger.java
@@ -0,0 +1,36 @@
+import java.io.IOException;
+import java.net.Socket;
+
+public class ControllerLogger extends Logger {
+	
+	private static final String LOG_FILE_SUFFIX = "controller";
+	
+	private static ControllerLogger instance = null;
+	
+	public static void init(LoggingType loggingType) throws IOException {
+		if (instance == null)
+			instance = new ControllerLogger(loggingType);
+		else
+			throw new IOException("ControllerLogger already initialised");
+	}
+	
+	public static ControllerLogger getInstance() {
+		if (instance == null)
+			throw new RuntimeException("ControllerLogger has not been initialised yet");
+		return instance;
+	}
+
+	protected ControllerLogger(LoggingType loggingType) throws IOException {
+		super(loggingType);
+	}
+
+	@Override
+	protected String getLogFileSuffix() {
+		return LOG_FILE_SUFFIX;
+	}
+	
+	public void dstoreJoined(Socket socket, int dstorePort) {
+		log("[New Dstore " + dstorePort + " " + socket.getLocalPort() + "<-" + socket.getPort() + "]");
+	}
+
+}
diff --git a/testing/DstoreLogger.java b/testing/DstoreLogger.java
new file mode 100644
index 0000000000000000000000000000000000000000..18fd389e37cba037efd09a4dfb5cc7d61f2d80db
--- /dev/null
+++ b/testing/DstoreLogger.java
@@ -0,0 +1,34 @@
+import java.io.IOException;
+
+public class DstoreLogger extends Logger {
+
+private static final String LOG_FILE_SUFFIX = "dstore";
+	
+	private static DstoreLogger instance = null;
+	
+	private final String logFileSuffix;
+	
+	public static void init(LoggingType loggingType, int port) throws IOException {
+		if (instance == null)
+			instance = new DstoreLogger(loggingType, port);
+		else
+			throw new IOException("DstoreLogger already initialised");
+	}
+	
+	public static DstoreLogger getInstance() {
+		if (instance == null)
+			throw new RuntimeException("DstoreLogger has not been initialised yet");
+		return instance;
+	}
+
+	protected DstoreLogger(LoggingType loggingType, int port) throws IOException {
+		super(loggingType);
+		logFileSuffix = LOG_FILE_SUFFIX + "_" + port;			
+	}
+
+	@Override
+	protected String getLogFileSuffix() {
+		return logFileSuffix;
+	}
+
+}
diff --git a/testing/Logger.java b/testing/Logger.java
new file mode 100644
index 0000000000000000000000000000000000000000..c8a97d107918e1071f6178c60964581bcd23ab5c
--- /dev/null
+++ b/testing/Logger.java
@@ -0,0 +1,52 @@
+import java.io.IOException;
+import java.io.PrintStream;
+import java.net.Socket;
+
+public abstract class Logger {
+
+	public enum LoggingType {
+		NO_LOG, // no log at all
+		ON_TERMINAL_ONLY, // log to System.out only 
+		ON_FILE_ONLY, // log to file only
+		ON_FILE_AND_TERMINAL // log to both System.out and file
+	}
+	
+	protected final LoggingType loggingType;
+	protected PrintStream ps;
+	
+	protected Logger(LoggingType loggingType) {
+		this.loggingType = loggingType;
+	}
+	
+	protected abstract String getLogFileSuffix();
+	
+	protected synchronized PrintStream getPrintStream() throws IOException {
+		if (ps == null)
+			ps = new PrintStream(getLogFileSuffix() + "_" + System.currentTimeMillis() + ".log");
+		return ps;
+	}
+	
+	protected boolean logToFile() {
+		return loggingType == LoggingType.ON_FILE_ONLY || loggingType == LoggingType.ON_FILE_AND_TERMINAL;
+	}
+	
+	protected boolean logToTerminal() {
+		return loggingType == LoggingType.ON_TERMINAL_ONLY || loggingType == LoggingType.ON_FILE_AND_TERMINAL;
+	}
+	
+	protected void log(String message) {
+		if (logToFile())
+			try { getPrintStream().println(message); } catch(Exception e) { e.printStackTrace(); }
+		if (logToTerminal())
+			System.out.println(message);
+	}
+	
+	public void messageSent(Socket socket, String message) {
+		log("[" + socket.getLocalPort() + "->" + socket.getPort() + "] " + message);
+	}
+	
+	public void messageReceived(Socket socket, String message) {
+		log("[" + socket.getLocalPort() + "<-" + socket.getPort() + "] " + message);
+	}
+	
+}
diff --git a/testing/Protocol.java b/testing/Protocol.java
new file mode 100644
index 0000000000000000000000000000000000000000..53ae5fb9d540a65ea1aec266bd63f9beefe4c44d
--- /dev/null
+++ b/testing/Protocol.java
@@ -0,0 +1,30 @@
+
+public class Protocol {
+
+	// messages from Clients
+	public final static String LIST_TOKEN = "LIST"; // also from Controller and Dstores
+	public final static String STORE_TOKEN = "STORE"; // also from Dstores
+	public final static String LOAD_TOKEN = "LOAD";
+	public final static String LOAD_DATA_TOKEN = "LOAD_DATA";
+	public final static String RELOAD_TOKEN = "RELOAD";
+	public final static String REMOVE_TOKEN = "REMOVE"; // also from Controller
+	
+	// messages from Controller
+	public final static String STORE_TO_TOKEN = "STORE_TO";
+	public final static String STORE_COMPLETE_TOKEN = "STORE_COMPLETE";
+	public final static String LOAD_FROM_TOKEN = "LOAD_FROM";
+	public final static String REMOVE_COMPLETE_TOKEN = "REMOVE_COMPLETE";
+	public final static String REBALANCE_TOKEN = "REBALANCE";
+	public final static String ERROR_FILE_DOES_NOT_EXIST_TOKEN = "ERROR_FILE_DOES_NOT_EXIST"; // also from Dstores
+	public final static String ERROR_FILE_ALREADY_EXISTS_TOKEN = "ERROR_FILE_ALREADY_EXISTS";
+	public final static String ERROR_NOT_ENOUGH_DSTORES_TOKEN = "ERROR_NOT_ENOUGH_DSTORES";
+	public final static String ERROR_LOAD_TOKEN = "ERROR_LOAD";
+	
+	// messages from Dstores
+	public final static String ACK_TOKEN = "ACK";
+	public final static String STORE_ACK_TOKEN = "STORE_ACK";
+	public final static String REMOVE_ACK_TOKEN = "REMOVE_ACK";
+	public final static String JOIN_TOKEN = "JOIN";
+	public final static String REBALANCE_STORE_TOKEN = "REBALANCE_STORE";
+	public final static String REBALANCE_COMPLETE_TOKEN = "REBALANCE_COMPLETE";
+}
diff --git a/testingWithClient/client-1.0.2.jar b/testing/client-1.0.2.jar
similarity index 100%
rename from testingWithClient/client-1.0.2.jar
rename to testing/client-1.0.2.jar
diff --git a/testing/test.txt b/testing/test.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d800886d9c86731ae5c4a62b0b77c437015e00d2
--- /dev/null
+++ b/testing/test.txt
@@ -0,0 +1 @@
+123
\ No newline at end of file
diff --git a/testingWithClient/ClientMain$1.class b/testingWithClient/ClientMain$1.class
deleted file mode 100644
index 53a1221baa0100c9288b15b60f1d09b6482d223c..0000000000000000000000000000000000000000
Binary files a/testingWithClient/ClientMain$1.class and /dev/null differ
diff --git a/testingWithClient/ClientMain.class b/testingWithClient/ClientMain.class
deleted file mode 100644
index c8862cc8d28264f849861078ec69d6b72dcedf4b..0000000000000000000000000000000000000000
Binary files a/testingWithClient/ClientMain.class and /dev/null differ
diff --git a/testingWithClient/Controller.java b/testingWithClient/Controller.java
deleted file mode 100644
index 04da24d427b1aa300731ba8c58131761a6d31a1e..0000000000000000000000000000000000000000
--- a/testingWithClient/Controller.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package ftp;
-
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.nio.ByteBuffer;
-import java.nio.channels.*;
-import java.util.*;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-public class Controller extends Server {
-
-    int r;
-    int rbPeriod;
-
-    private ArrayList<DstoreConnection> index;
-
-
-    /**
-     * @desc constructs a controller
-     * @param cport to listen on
-     * @param r replication factor
-     * @param timeout timeout (ms)
-     * @param rbPeriod rebalance period (ms)
-     */
-    public Controller(int cport, int r, int timeout, int rbPeriod) throws IOException {
-        this.port = cport;
-        this.r = r;
-        this.timeout = timeout;
-        this.rbPeriod = rbPeriod;
-
-        start();
-    }
-
-
-    public static void main(String args[]) {
-        Stream<String> str = Arrays.stream(args);
-
-        List<Integer> intArgs = str.map(x -> {return Integer.parseInt(x);})
-                .collect(Collectors.toList());
-
-        try {
-            Controller ctrl = new Controller(intArgs.get(0), intArgs.get(1), intArgs.get(2), intArgs.get(3));
-        } catch (IOException e) {
-            System.out.println("IOException " + e.getMessage());
-        }
-    }
-
-
-    @Override
-    protected void handleRequest(String request, Socket socket) {
-        String args[] = request.split(" ");
-
-        switch(args[0]) {
-            case "JOIN":
-                new DstoreConnection(new Index(), Integer.parseInt(args[1]));
-
-                try { send("LIST",socket); }
-                catch (Exception e) {
-                    System.err.println("Error: " + e);
-                }
-
-                break;
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/testingWithClient/Dstore.java b/testingWithClient/Dstore.java
deleted file mode 100644
index 9c031e372a53840af15356303d41aa1a34c99272..0000000000000000000000000000000000000000
--- a/testingWithClient/Dstore.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package ftp;
-
-import ftp.DstoreConnection;
-import ftp.Index;
-import ftp.Server;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketException;
-import java.nio.ByteBuffer;
-import java.nio.channels.SelectionKey;
-import java.nio.channels.SocketChannel;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-public class Dstore extends Server {
-
-    int cport;
-    String file_folder;
-
-    private static SocketChannel toController;
-
-
-    /**
-     * @desc constructs a client
-     * @param port port to listen on
-     * @param cport controller port to talk to
-     * @param timeout timeout (ms)
-     * @param file_folder where to store data locally
-     */
-    public Dstore(int port, int cport, int timeout, String file_folder) throws IOException{
-        this.port = port;
-        this.cport = cport;
-        this.timeout = timeout;
-        this.file_folder = file_folder;
-
-        Socket ctrlSocket = new Socket("localhost",cport);
-
-        try {send("JOIN " + port, ctrlSocket);}
-        catch (Exception e) {
-            System.err.println("Error: " + e);
-        }
-
-        start();
-    }
-
-
-    public static void main(String args[]) {
-        String numberArgs[] = Arrays.copyOf(args, args.length-1);
-        Stream<String> str = Arrays.stream(numberArgs);
-
-        List<Integer> intArgs = str.map(x -> {return Integer.parseInt(x);})
-                .collect(Collectors.toList());
-
-        try {
-            Dstore dstore = new Dstore(intArgs.get(0), intArgs.get(1), intArgs.get(2), args[3]);
-        } catch (IOException e) {
-            System.out.println("IOException " + e.getMessage());
-        }
-    }
-
-
-//    /**
-//     * @desc lists the files of the datastore
-//     * @return
-//     */
-//    private File[] list() {
-//        File folder = new File("./storage");
-//        return folder.listFiles();
-//    }
-
-
-    @Override
-    protected void handleRequest(String request, Socket socket) {
-        String args[] = request.split(" ");
-
-        switch(args[0]) {
-            case "LIST":
-                File folder = new File("storage");
-                String[] files = folder.list();
-
-                String fileNames = Arrays.stream(files)
-                        .reduce("", (file1, file2) -> file1 + " " + file2);
-
-                try {send(fileNames, socket);}
-                catch (Exception e) {
-                    System.err.println("Error: " + e);
-                }
-
-                break;
-        }
-    }
-
-}
diff --git a/testingWithClient/DstoreConnection.java b/testingWithClient/DstoreConnection.java
deleted file mode 100644
index fbc3f2ec70cd3a84a98050966919ddb29254d47d..0000000000000000000000000000000000000000
--- a/testingWithClient/DstoreConnection.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package ftp;
-
-public class DstoreConnection {
-
-    private Index file_index;
-    private int port;
-
-
-    public DstoreConnection(Index file_index, int port) {
-        this.file_index = file_index;
-        this.port = port;
-    }
-
-}
diff --git a/testingWithClient/DstoreFile.java b/testingWithClient/DstoreFile.java
deleted file mode 100644
index 2d79a776368e3761320119a5774360630d782a95..0000000000000000000000000000000000000000
--- a/testingWithClient/DstoreFile.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package ftp;
-
-public class DstoreFile {
-    private String filename;
-    private int filesize;
-
-    public DstoreFile(String filename, int filesize) {
-        this.filename = filename;
-        this.filesize = filesize;
-    }
-}
diff --git a/testingWithClient/Index.java b/testingWithClient/Index.java
deleted file mode 100644
index 7537564a4da24e10e2a66825b11c396c964ed67c..0000000000000000000000000000000000000000
--- a/testingWithClient/Index.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package ftp;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class Index {
-
-    private ArrayList<DstoreFile> files = new ArrayList<DstoreFile>();
-
-
-    public Index() {}
-
-    public Index(List<DstoreFile> files) {
-        this.files = new ArrayList<DstoreFile>(files);
-    }
-
-
-    public void addFile(String filename, int filesize) {
-        files.add(new DstoreFile(filename,filesize));
-    }
-
-    public ArrayList<DstoreFile> getIndex() {
-        return files;
-    }
-
-}
diff --git a/testingWithClient/Server.java b/testingWithClient/Server.java
deleted file mode 100644
index aa93c5a8311e049b9ad1286e7a58142ce1261a48..0000000000000000000000000000000000000000
--- a/testingWithClient/Server.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package ftp;
-
-import java.io.*;
-import java.net.*;
-
-public abstract class Server {
-
-    protected int port;
-    protected int timeout;
-
-
-    protected void start() {
-        try {
-            ServerSocket ss = new ServerSocket(port);
-            while (true) {
-                try {
-                    final Socket client = ss.accept();
-                    new Thread(new Runnable() {
-                        public void run() {
-                            try {
-                                BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
-                                String request = in.readLine();
-                                System.out.println("Recieved: " + request);
-                                handleRequest(request, client);
-                                client.close();
-                            } catch (Exception e) {}
-                        }
-                    }).start();
-                } catch (Exception e) {
-                    System.out.println("error " + e);
-                }
-            }
-        } catch (Exception e) {
-            System.out.println("error " + e);
-        }
-    }
-
-
-    protected abstract void handleRequest(String request, Socket socket);
-
-
-    protected void send(String msg, Socket socket) throws Exception {
-        PrintWriter out = new PrintWriter(socket.getOutputStream());
-        out.println(msg);
-        out.flush();
-        System.out.println("Sent: " + msg);
-    }
-
-}
\ No newline at end of file
diff --git a/testingWithClient/client_1619560664620.log b/testingWithClient/client_1619560664620.log
deleted file mode 100644
index ceb63889bad0a2b8550137caa56cfe586fc1c05d..0000000000000000000000000000000000000000
--- a/testingWithClient/client_1619560664620.log
+++ /dev/null
@@ -1,4 +0,0 @@
-Cannot connect to the Controller on port 12345
-Cannot connect to the Controller on port 12345
-Cannot connect to the Controller on port 12345
-Cannot connect to the Controller on port 12345
diff --git a/testingWithClient/comp2207-2021-client-1.0.2.zip b/testingWithClient/comp2207-2021-client-1.0.2.zip
deleted file mode 100644
index af6470c8b37454213bc6d1c05122a3ec6e3f38da..0000000000000000000000000000000000000000
Binary files a/testingWithClient/comp2207-2021-client-1.0.2.zip and /dev/null differ