Index: threads/.DS_Store
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: threads/.DS_Store
===================================================================
--- threads/.DS_Store	(nonexistent)
+++ threads/.DS_Store	(revision 15)

Property changes on: threads/.DS_Store
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: threads/ManagePutchunk.java
===================================================================
--- threads/ManagePutchunk.java	(nonexistent)
+++ threads/ManagePutchunk.java	(revision 15)
@@ -0,0 +1,51 @@
+package threads;
+
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import server.Server;
+
+public class ManagePutchunk implements Runnable {
+    
+	private byte[] message;
+    private int time;
+    private String key;
+    private int replicationDegree;
+    private int tries;
+
+    public ManagePutchunk(byte[] message, int time, String fileID, int chunkNr, int replicationDegree) {
+        this.message = message;
+        this.time = time;
+        this.key = fileID + '.' + chunkNr;
+        this.replicationDegree = replicationDegree;
+        this.tries = 1;
+    }
+
+    @Override
+    public void run() {
+
+        int occurrences = Server.getStorage().getStoredTimes().get(this.key);
+
+        if (occurrences < replicationDegree) { 
+            try {
+				Server.getmdb().sendMessage(message);
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+            System.out.println("Sent PUTCHUNK try: " + tries);
+            System.out.println(key);
+            this.time = 2 * this.time;
+            this.tries++;
+            
+            if (this.tries < 5)
+                Server.getThreadLauncher().schedule(this, this.time, TimeUnit.SECONDS);
+              
+            
+            
+            
+        }
+        
+ 
+
+    }
+}
\ No newline at end of file
Index: threads/ManageRestored.java
===================================================================
--- threads/ManageRestored.java	(nonexistent)
+++ threads/ManageRestored.java	(revision 15)
@@ -0,0 +1,73 @@
+package threads;
+import java.io.*;
+import java.util.*;
+import server.Server;
+
+public class ManageRestored implements Runnable {
+
+    private String fileName;
+
+    public ManageRestored(String fileName) {
+        this.fileName = fileName;
+    }
+
+    @Override
+    public void run() {
+
+        if (!Server.getStorage().getRemainingChunks().containsValue("false")) {
+            if (restoreFile())
+                System.out.println("> File restored!\n");
+            else System.out.println("ERROR: File not restored.\n");
+        } else System.out.println("ERROR: File not restored, chunks missing.\n");
+
+        Server.getStorage().getRemainingChunks().clear();
+    }
+
+    private boolean restoreFile() {
+        String filePath = "database/" + Server.getServerId() + "/" + this.fileName;
+        File file = new File(filePath);
+        byte[] body;
+
+        try {
+            FileOutputStream fos = new FileOutputStream(file, true);
+
+            if (!file.exists()) {
+                file.getParentFile().mkdirs();
+                file.createNewFile();
+            }
+
+            List<String> sortedChunkKeys = new ArrayList<>(Server.getStorage().getRemainingChunks().keySet());
+
+            sortedChunkKeys.sort((o1, o2) -> {
+                int chunkNr1 = Integer.valueOf(o1.split(".")[1]);
+                int chunkNr2 = Integer.valueOf(o2.split(".")[1]);
+                return Integer.compare(chunkNr1, chunkNr2);
+            });
+
+            for (String key : sortedChunkKeys) {
+                String chunkPath = Server.getServerId() + "/" + key;
+
+                File chunkFile = new File(chunkPath);
+
+                if (!chunkFile.exists()) {
+                    return false;
+                }
+
+                body = new byte[(int) chunkFile.length()];
+                FileInputStream in = new FileInputStream(chunkFile);
+
+                in.read(body);
+                fos.write(body);
+
+                chunkFile.delete();
+                in.close();
+            }
+           
+            fos.close();
+            return true;
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return false;
+    }
+}
\ No newline at end of file
Index: threads/ReceiveGetChunk.java
===================================================================
--- threads/ReceiveGetChunk.java	(nonexistent)
+++ threads/ReceiveGetChunk.java	(revision 15)
@@ -0,0 +1,70 @@
+
+package threads;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+import chunk.*;
+import server.*;
+
+public class ReceiveGetChunk implements Runnable {
+
+    private String fileId;
+    private int chunkNum;
+
+
+	public ReceiveGetChunk( String fileId, int chunkNr) {
+        this.fileId = fileId;
+        this.chunkNum = chunkNr;
+    }
+
+	@Override
+	public void run() {
+		
+		for (int i = 0; i < Server.getStorage().getSavedChunks().size(); i++) {
+            if (isSameChunk(Server.getStorage().getSavedChunks().get(i).getfileId(), Server.getStorage().getSavedChunks().get(i).getNum()) && !isAbortSend()) {
+                String header = "CHUNK " + "1.0" + " " + Server.getServerId() + " " + this.fileId + " " + this.chunkNum + "\r\n\r\n";
+
+                try {
+                    byte[] asciiHeader = header.getBytes(StandardCharsets.US_ASCII);
+
+                    String chunkPath = "database/" + Server.getServerId() + "/" + fileId + "." + chunkNum;
+
+                    File file = new File(chunkPath);
+                    byte[] body = new byte[(int) file.length()];
+                    FileInputStream in = new FileInputStream(file);
+                    in.read(body);
+
+                    byte[] message = new byte[asciiHeader.length + body.length];
+                    System.arraycopy(asciiHeader, 0, message, 0, asciiHeader.length);
+                    System.arraycopy(body, 0, message, asciiHeader.length, body.length);
+
+                    SendMessage sendThread = new SendMessage(message, "mdr");
+                    System.out.println("Sent" + "CHUNK " + "1.0" + " " + Server.getServerId() + " " + this.fileId + " " + this.chunkNum);
+                    Random random = new Random();
+                    Server.getThreadLauncher().schedule(sendThread, random.nextInt(401), TimeUnit.MILLISECONDS);
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+
+            }
+
+    }
+}
+    private boolean isSameChunk(String fileId, int chunkNr) {
+        return fileId.equals(this.fileId) && chunkNr == this.chunkNum;
+    }
+
+    private boolean isAbortSend() {
+        for (int i = 0; i < Server.getStorage().getReceivedChunks().size(); i++) {
+            if (isSameChunk(Server.getStorage().getReceivedChunks().get(i).getfileId(), Server.getStorage().getReceivedChunks().get(i).getNum()))
+                return true;
+        }
+        return false;
+}
+}
Index: threads/ReceivePutchunk.java
===================================================================
--- threads/ReceivePutchunk.java	(nonexistent)
+++ threads/ReceivePutchunk.java	(revision 15)
@@ -0,0 +1,87 @@
+package threads;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import chunk.*;
+import server.*;
+
+public class ReceivePutchunk implements Runnable {
+
+	private Double version;
+	private String fileId;
+	private int chunkNr;
+	private int replicationDegree;
+	private byte[] content;
+
+	public ReceivePutchunk(double version, String fileId, int chunkNr, int replicationDegree, byte[] content) {
+		this.version = version;
+		this.fileId = fileId;
+		this.chunkNr = chunkNr;
+		this.replicationDegree = replicationDegree;
+		this.content = content;
+	}
+
+	@Override
+	public void run() {
+		
+		String key = fileId + "." + chunkNr;
+
+		for (int i = 0; i < Server.getStorage().getFiles().size(); i++) {
+			if (Server.getStorage().getFiles().get(i).getFileId().equals(fileId))
+				return;
+		}
+
+		if (version == 2.0) {
+			if (Server.getStorage().getStoredTimes().get(key) >= replicationDegree)
+				return;
+
+			if (Server.getStorage().getSpaceAvailable() >= content.length) {
+				Chunk chunk = null;
+				try {
+					chunk = new Chunk(chunkNr, fileId, replicationDegree, content.length);
+				} catch (IOException e1) {
+					e1.printStackTrace();
+				}
+
+				if (!Server.getStorage().addSavedChunk(chunk)) {
+					return;
+				}
+
+				Server.getStorage().decSpaceAvailable(content.length);
+
+            //creates the file and saves the chunk
+            try {
+                String filename = Server.getServerId() + "/" + fileId + "." + chunkNr;
+
+					File file = new File(filename);
+					if (!file.exists()) {
+						file.getParentFile().mkdirs();
+						file.createNewFile();
+					}
+
+					try (FileOutputStream fos = new FileOutputStream(filename)) {
+						fos.write(content);
+					}
+
+				} catch (IOException e) {
+					e.printStackTrace();
+				}
+
+				Server.getStorage().incStoredOccurrences(fileId, chunkNr);
+				String header = "STORED " + "1.0" + " " + Server.getServerId() + " " + fileId + " " + chunkNr
+						+ "\r\n\r\n";
+				System.out.println(
+						"Sent " + "STORED " + "1.0" + " " + Server.getServerId() + " " + fileId + " " + chunkNr);
+				try {
+					Server.getmc().sendMessage(header.getBytes());
+				} catch (IOException e) {
+					e.printStackTrace();
+				}
+			} else {
+				System.out.println("Not enough space in this peer " + fileId + "_" + chunkNr);
+			}
+
+		}
+	}
+}
\ No newline at end of file
Index: threads/SendMessage.java
===================================================================
--- threads/SendMessage.java	(nonexistent)
+++ threads/SendMessage.java	(revision 15)
@@ -0,0 +1,47 @@
+package threads;
+
+import java.io.IOException;
+import server.Server;
+import multicastchannels.*;
+
+public class SendMessage implements Runnable {
+	private byte[] message;
+	private String channel;
+
+	public SendMessage(byte[] message, String channel) {
+		this.message = message;
+		this.channel = channel;
+
+	}
+
+	@Override
+	public void run() {
+		switch (channel) {
+
+		case "mc":
+			try {
+				Server.getmc().sendMessage(message);
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			break;
+
+		case "mdb":
+			try {
+				Server.getmdb().sendMessage(message);
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			break;
+
+		case "mdr":
+			try {
+				Server.getmdr().sendMessage(message);
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			break;
+
+		}
+	}
+}
\ No newline at end of file
Index: threads/messageManagement.java
===================================================================
--- threads/messageManagement.java	(nonexistent)
+++ threads/messageManagement.java	(revision 15)
@@ -0,0 +1,117 @@
+package threads;
+
+import java.util.ArrayList;
+import server.Server;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+public class messageManagement implements Runnable{
+	private byte[] msg;
+
+	public messageManagement(byte[] msg) {
+		this.msg = msg;
+		
+	}
+
+	@Override
+	public void run() {
+		
+		List<byte[]> HB = getHeaderNBody();
+		byte[] header = HB.get(0);
+		byte[] body = HB.get(1);
+		
+		String message = new String(this.msg, 0, this.msg.length);
+		String[] newMessage = message.split(" ");
+		
+		String messageType = newMessage[0];
+		Double version = Double.parseDouble(newMessage[1]);
+		int senderID = Integer.parseInt(newMessage[2]);
+		String fileID = newMessage[3];
+		int chunkNr = Integer.parseInt(newMessage[4]);
+		int replicationDegree = Integer.parseInt(newMessage[5]);
+		
+		
+		//removeBlanks(newMessage);	
+		
+		
+       
+		switch (newMessage[0]) {
+        case "PUTCHUNK":
+            putchunkOperation(version, fileID, chunkNr, replicationDegree, body);
+            break;
+        case "GETCHUNK":
+            getchunkOperation(version, senderID, fileID, chunkNr);
+            break;
+        case "DELETE":
+            deleteOperation(version, senderID, fileID);
+            break;
+        case "REMOVED":
+            removedOperation(version, senderID, fileID, chunkNr);
+            break;
+        case "STORED":
+            storedOperation(version, senderID, fileID, chunkNr);
+            break;
+		
+	}
+
+}
+
+	private void deleteOperation(Double version, int senderID, String fileID) {
+		if (Integer.parseInt(fileID) != senderID) { 
+            Server.getStorage().deleteStoredChunks(fileID);
+            System.out.println("Received DELETE " + version + " " + senderID + " " + fileID);
+        }		
+	}
+
+	private void removedOperation(Double version, int senderID, String fileID, int chunkNr) {
+	}
+
+	private void getchunkOperation(Double version, int senderID, String fileID, int chunkNr) {
+		if (Integer.parseInt(fileID) != senderID) {           
+			Random random = new Random();
+            System.out.println("Received GETCHUNK " + version + " " + senderID + " " + fileID + " " + chunkNr);
+            Server.getThreadLauncher().schedule(new ReceiveGetChunk(fileID, chunkNr), random.nextInt(401), TimeUnit.MILLISECONDS);
+		}
+		
+	}
+
+	private void storedOperation(Double version, int senderID, String fileID, int chunkNr) {
+		if (Integer.parseInt(fileID) != senderID) {           
+            Server.getStorage().incStoredOccurrences(fileID, chunkNr); 
+            System.out.println("Received STORED " + version + " " + senderID + " " + fileID + " " + chunkNr);
+        }
+		
+	}
+
+	private void putchunkOperation(Double version, String fileID, int chunkNr, int replicationDegree, byte[] body) {
+		Random r = new Random();
+		System.out.println("Received PUTCHUNK " + version + " " + fileID + " " + chunkNr);
+		Server.getThreadLauncher().schedule(new ReceivePutchunk(version, fileID, chunkNr, replicationDegree, body), r.nextInt(401), TimeUnit.MILLISECONDS);
+
+	}
+
+	private void removeBlanks(String[] newMessage) {
+		for(int i=0; i<newMessage.length; i++) {
+			newMessage[i] = newMessage[i].replaceAll("\\s","" );
+		}
+		
+	}
+
+	private List<byte[]> getHeaderNBody(){
+		
+		int h = this.msg.length -4;
+		
+		byte[] header = Arrays.copyOfRange(this.msg, 0 ,h);
+		byte[] body = Arrays.copyOfRange(this.msg, h, this.msg.length);
+		
+		List<byte[]> headerNBody = new ArrayList<>();
+
+        headerNBody.add(header);
+        headerNBody.add(body);
+
+        return headerNBody;
+	}
+
+}
