Project

General

Profile

Revision 1

Final upload

View differences:

demo_backup_big_rd20.sh
1
#!/bin/bash
2
java TestApp "$1" BACKUP big.zip 20
0 3

  
demo_backup_small_rd20.sh
1
#!/bin/bash
2
java TestApp "$1" BACKUP small.zip 20
0 3

  
demo_backupenh_small.sh
1
#!/bin/bash
2
java TestApp "$1" BACKUPENH small.zip 1
0 3

  
demo_delete_small.sh
1
#!/bin/bash
2
java TestApp "$1" DELETE small.zip
0 3

  
demo_restore_big.sh
1
#!/bin/bash
2
java TestApp "$1" RESTORE big.zip
0 3

  
RemovedTask.java
1
import java.io.IOException;
2
import java.net.DatagramPacket;
3
import java.net.DatagramSocket;
4
import java.util.Random;
5

  
6
/**
7
 * RemovedTask
8
 */
9
public class RemovedTask implements Runnable {
10
    private static final String CRLF = Integer.toHexString(0xD) + Integer.toHexString(0xA);
11

  
12
    private Peer peer;
13
    private String fileId;
14
    private int chunkNo;
15
    private MCListener mc;
16

  
17
    private String version;
18

  
19
    // REMOVED <Version> <SenderId> <FileId> <ChunkNo> <CRLF><CRLF>
20
    RemovedTask(Peer peer, String[] args, MCListener mc) {
21
        this.peer = peer;
22
        this.fileId = args[3];
23
        this.version = args[1];
24
        this.chunkNo = Integer.parseInt(args[4]);
25
        this.mc = mc;
26

  
27
        this.mc.print("starting REMOVED protocol: [fileId] " + fileId + "[chunkNo] " + chunkNo);
28
    }
29

  
30
    @Override
31
    public void run() {
32
        this.peer.repDegMap.get(this.fileId).put(this.chunkNo, this.peer.repDegMap.get(this.fileId).get(this.chunkNo)-1);
33

  
34
        try{
35
        if(this.peer.repDegMap.get(this.fileId).get(chunkNo) < this.peer.chunksMap.get(fileId).getDesiredReplicationDegree()){
36
            
37
            Random random = new Random();
38

  
39
            //Random delay between [0-400] ms to avoid overlapping messages
40
            Thread.sleep(random.nextInt(401));
41
            
42
            if(this.peer.repDegMap.get(this.fileId).get(chunkNo) >= this.peer.chunksMap.get(fileId).getDesiredReplicationDegree()){
43
                return; //já outro peer tem o chunk
44
            }
45
            byte[] chunk = this.peer.chunksMap.get(fileId).getChunksMap().get(chunkNo).getData();
46

  
47
            String message = "PUTCHUNK " + version + " " + peer.getSenderId() + " " + fileId + " " + chunkNo + " "
48
                    + this.peer.chunksMap.get(fileId).getDesiredReplicationDegree() + " " + CRLF + CRLF;
49

  
50
            byte[] packetData = new byte[message.getBytes().length + chunk.length];
51
            System.arraycopy(message.getBytes(), 0, packetData, 0, message.getBytes().length);
52
            System.arraycopy(chunk, 0, packetData, message.getBytes().length, chunk.length);
53
            
54
            DatagramSocket socket = new DatagramSocket();
55

  
56
            DatagramPacket packet = new DatagramPacket(packetData, packetData.length, this.peer.getMDBaddress(), this.peer.getMDBport());
57
            int interval = 1000;
58
            while (interval <= 31000) { //31 = 1+2+4+8+16
59
                this.peer.print("sending PUTCHUNK message");
60
                socket.send(packet);
61
                Thread.sleep(interval);
62
                if (this.peer.repDegMap.containsKey(fileId) && this.peer.repDegMap.get(fileId).get(chunkNo) >= this.peer.chunksMap.get(fileId).getDesiredReplicationDegree())
63
                    break;
64
                interval *= 2;
65
            }
66
            socket.close();
67

  
68
        }
69

  
70
        this.mc.print("REMOVED protocol finished");
71
    }
72
    catch (InterruptedException | IOException e)
73
    {
74
        e.printStackTrace();
75
    }
76
	    
77
    }    
78
}
scripts/script_backup.sh
1
#!/bin/bash
2
java TestApp "$1" BACKUP  "$2" "$3"
demo_restoreenh_small.sh
1
#!/bin/bash
2
java TestApp "$1" RESTOREENH small.zip
0 3

  
scripts/script_backupenh.sh
1
#!/bin/bash
2
java TestApp "$1" BACKUPENH  "$2" "$3"
RestoreTask.java
1
import java.io.File;
2
import java.io.IOException;
3
import java.net.DatagramPacket;
4
import java.net.DatagramSocket;
5
import java.net.InetAddress;
6
import java.security.NoSuchAlgorithmException;
7

  
8
/**
9
 * BackupTask
10
 */
11
public class RestoreTask implements Runnable {
12
    private static final int MAX_CHUNK_SIZE = 64000; // 64KBytes
13
    private static final String CRLF = Integer.toHexString(0xD) + Integer.toHexString(0xA);
14

  
15
    private String filePath;
16
    private InetAddress MCaddress;
17
    private int MCport;
18

  
19
    private Peer peer;
20
    private String version;
21

  
22
    RestoreTask(String pathname, String version, Peer peer) {
23
        this.filePath = pathname;
24
        this.MCaddress = peer.getMCaddress();
25
        this.MCport = peer.getMCport();
26
        this.version = version;
27
        this.peer = peer;
28
    }
29
    
30
    @Override
31
    public void run() {
32
        File file = new File(this.filePath);
33
        try {
34
            String fileId = BackupFile.generateFileId(this.filePath, file.lastModified());
35
            long interval;
36
            RestoreFile restoreFile = new RestoreFile(new File("Peer-" + this.peer.getSenderId() + File.separator + "Backups" + File.separator + this.filePath), fileId, file.length()/MAX_CHUNK_SIZE + 1);
37
            this.peer.restoreMap.put(fileId, restoreFile);
38
            DatagramSocket socket = new DatagramSocket();
39

  
40
            //GETCHUNK <Version> <SenderId> <FileId> <ChunkNo> <CRLF><CRLF>
41
            for (int i = 0; i <= file.length()/MAX_CHUNK_SIZE; i++) {
42
                interval = 1000;
43
                String message = "GETCHUNK " + this.version + " " + peer.getSenderId() + " " + fileId + " " + i + " " + CRLF + CRLF;
44
                
45
                DatagramPacket packet = new DatagramPacket(message.getBytes(), message.length(), this.MCaddress, this.MCport);
46

  
47
                while (interval <= 31000) { //31 = 1+2+4+8+16
48
                    this.peer.print("sending GETCHUNK message");
49
                    socket.send(packet);
50
                    Thread.sleep(interval);
51
                    if (this.peer.restoreMap.get(fileId).hasChunk(i)){
52
                        break;
53
                    }
54
                    interval *= 2;
55
                }
56
				if(interval > 31000) {
57
					this.peer.print("Couldn't get all chunks");
58
					return;
59
				}
60
            }
61
            
62
            if (!restoreFile.restoreFile(file)) {
63
                this.peer.print("The file couldn't be restored due to lack of chunks");
64
            } else {
65
                this.peer.print("The file was restored successfully");
66
            }
67
            
68
            socket.close();
69
            this.peer.print("RESTORE protocol finished");
70
        } catch (IOException | NoSuchAlgorithmException | InterruptedException e) {
71
            e.printStackTrace();
72
        }
73
    }
74
}
scripts/script_compile.sh
1
#!/bin/bash
2
javac *.java
StoredTask.java
1
import java.util.concurrent.ConcurrentHashMap;
2

  
3
/**
4
 * StoredTask
5
 */
6
public class StoredTask implements Runnable {
7

  
8
    private Peer peer;
9
    private String fileId;
10
    private int chunkNo;
11
    private MCListener mc;
12

  
13
    StoredTask(Peer peer, String fileId, String version, int chunkNo, MCListener mc) {
14
        this.peer = peer;
15
        this.fileId = fileId;
16
        this.chunkNo = chunkNo;
17
        this.mc = mc;
18
    }
19

  
20
    @Override
21
    public void run() {
22
	//Update the perceived replication degree for this chunk
23
	if (!this.peer.repDegMap.containsKey(this.fileId))
24
	    this.peer.repDegMap.put(this.fileId, new ConcurrentHashMap<>());
25

  
26
	if(!this.peer.repDegMap.get(this.fileId).containsKey(this.chunkNo))
27
	    this.peer.repDegMap.get(this.fileId).put(this.chunkNo, 0);
28

  
29
	this.peer.repDegMap.get(this.fileId).put(this.chunkNo, this.peer.repDegMap.get(this.fileId).get(this.chunkNo)+1);
30
	this.mc.print("RepDegMap("+chunkNo+") = "+this.peer.repDegMap.get(fileId).get(chunkNo));
31

  
32
	this.mc.print("STORED protocol finished");
33
    }    
34
}
scripts/script_delete.sh
1
#!/bin/bash
2
java TestApp "$1" DELETE "$2"
TestAppRemote.java
1
import java.rmi.Remote;
2
import java.rmi.RemoteException;
3

  
4
public interface TestAppRemote extends Remote {
5
    void backup(String pathname, int replicationDeg, boolean enhanced) throws RemoteException;
6
    void restore(String pathname, boolean enhanced) throws RemoteException;
7
    void delete(String pathname, boolean enhanced) throws RemoteException;
8
    void reclaim(int diskspace) throws RemoteException;
9
    void state() throws RemoteException;
10
    void chunk(String fileId, byte[] chunk) throws RemoteException;
11
}
scripts/script_deleteenh.sh
1
#!/bin/bash
2
java TestApp "$1" DELETEENH "$2"
demo_backup_big_rd1.sh
1
#!/bin/bash
2
java TestApp "$1" BACKUP big.zip 1
0 3

  
scripts/script_peer.sh
1
#!/bin/bash
2
java Peer "$1" "$2" "$3" "$4"
demo_backup_small_rd1.sh
1
#!/bin/bash
2
java TestApp "$1" BACKUP small.zip 1
0 3

  
scripts/script_reclaim.sh
1
#!/bin/bash
2
java TestApp "$1" RECLAIM "$2"
demo_backupenh_big.sh
1
#!/bin/bash
2
java TestApp "$1" BACKUPENH big.zip 1
0 3

  
scripts/script_restore.sh
1
#!/bin/bash
2
java TestApp "$1" RESTORE "$2"
demo_delete_big.sh
1
#!/bin/bash
2
java TestApp "$1" DELETE big.zip
0 3

  
scripts/script_restoreenh.sh
1
#!/bin/bash
2
java TestApp "$1" RESTOREENH "$2"
demo_reclaim.sh
1
#!/bin/bash
2
java TestApp "$1" RECLAIM "$2"
0 3

  
scripts/script_state.sh
1
#!/bin/bash
2
java TestApp "$1" STATE
demo_restoreenh_big.sh
1
#!/bin/bash
2
java TestApp "$1" RESTOREENH big.zip
0 3

  
BackupFile.java
1
import java.io.File;
2
import java.nio.charset.StandardCharsets;
3
import java.security.MessageDigest;
4
import java.security.NoSuchAlgorithmException;
5
import java.util.concurrent.ConcurrentHashMap;
6

  
7
/**
8
 * BackupFile
9
 */
10
public class BackupFile {
11
    private File file;
12
    private String fileId;
13
    private int desiredReplicationDegree;
14
    private ConcurrentHashMap<Integer, Chunk> chunksMap = new ConcurrentHashMap<>();
15
    
16
    public BackupFile(String fileId) {
17
        this.fileId = fileId;
18
    }
19

  
20
    public void addChunk(int chunkNo, Chunk chunk) {
21
        this.chunksMap.put(chunkNo, chunk);
22
    }
23

  
24
    public BackupFile(String pathname, int desiredReplicationDegree)
25
            throws NoSuchAlgorithmException {
26
        this.file = new File(pathname);
27
        this.desiredReplicationDegree = desiredReplicationDegree;
28
        this.fileId = generateFileId(this.getPathname(), this.file.lastModified());
29

  
30
    }
31

  
32
    //Generates a unique FileId with the combined pathname & last modified info
33
    public static String generateFileId(String pathname, long lastModified) throws NoSuchAlgorithmException {
34
        String str = pathname + lastModified;
35

  
36
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
37
        byte[] hash = digest.digest(str.getBytes(StandardCharsets.UTF_8));
38

  
39
        StringBuffer hexString = new StringBuffer();
40
        for (int i = 0; i < hash.length; i++) {
41
            String hex = Integer.toHexString(0xff & hash[i]);
42
            if (hex.length() == 1)
43
                hexString.append('0');
44
            hexString.append(hex);
45
        }
46
        return hexString.toString();
47
    }
48

  
49
    /**
50
     * @return the desiredReplicationDegree
51
     */
52
    public int getDesiredReplicationDegree() {
53
        return desiredReplicationDegree;
54
    }
55

  
56
    /**
57
     * @return the pathname
58
     */
59
    public String getPathname() {
60
        return this.file.getPath();
61
    }
62

  
63
    /**
64
     * @return the fileId
65
     */
66
    public String getFileId() {
67
        return fileId;
68
    }
69

  
70
    public File getFile() {
71
        return this.file;
72
    }
73

  
74
    public ConcurrentHashMap<Integer, Chunk> getChunksMap() {
75
		return this.chunksMap;
76
    }
77

  
78
    public void removeChunk(int chunkNo, Peer peer){
79
        this.chunksMap.remove(chunkNo);
80
        File chunk = new File("Peer-" + peer.getSenderId() + File.separator + "Chunks" + File.separator + this.fileId + File.separator + chunkNo);
81
        peer.removeStorage(chunk.length());
82
	chunk.delete();
83
    }
84
    
85
    
86
}
BackupTask.java
1
import java.io.File;
2
import java.io.FileInputStream;
3
import java.io.IOException;
4
import java.net.DatagramPacket;
5
import java.net.DatagramSocket;
6
import java.net.InetAddress;
7
import java.security.NoSuchAlgorithmException;
8
import java.util.ArrayList;
9
import java.util.Arrays;
10

  
11
/**
12
 * BackupTask
13
 */
14
public class BackupTask implements Runnable {
15
    private static final int MAX_CHUNK_SIZE = 64000; // 64KBytes
16
    private static final String CRLF = Integer.toHexString(0xD) + Integer.toHexString(0xA);
17

  
18
    private String filePath;
19
    private String version;
20
    private int replicationDeg;
21
    private InetAddress MDBaddress;
22
    private int MDBport;
23

  
24
    private Peer peer;
25

  
26
    BackupTask(String pathname, int replicationDeg, String version, Peer peer) {
27
        this.filePath = pathname;
28
        this.version = version;
29
        this.replicationDeg = replicationDeg;
30
        this.MDBaddress = peer.getMDBaddress();
31
        this.MDBport = peer.getMDBport();
32
        this.peer = peer;
33
    }
34

  
35
    @Override
36
    public void run() {
37
        File file = new File(this.filePath);
38
        try {
39
            BackupFile backupFile;
40
            FileInputStream stream = new FileInputStream(file);
41
            byte[] data = new byte[(int) file.length()];
42
            stream.read(data);
43
            stream.close();
44

  
45
            ArrayList<Chunk> chunks = new ArrayList<>();
46
            String fileId = BackupFile.generateFileId(this.filePath, file.lastModified());
47
            DatagramSocket socket = new DatagramSocket();
48
            long interval;
49

  
50
            backupFile = new BackupFile(this.filePath, this.replicationDeg);
51
            
52
            int i;
53
            for (i = 0; i < data.length / MAX_CHUNK_SIZE; i++) {
54
                chunks.add(new Chunk(backupFile, i, Arrays.copyOfRange(data, i * MAX_CHUNK_SIZE, (i + 1) * MAX_CHUNK_SIZE)));
55
                backupFile.addChunk(i, new Chunk(backupFile, i, Arrays.copyOfRange(data, i * MAX_CHUNK_SIZE, (i + 1) * MAX_CHUNK_SIZE)));
56
            }
57
            chunks.add(new Chunk(backupFile, i, Arrays.copyOfRange(data, i * MAX_CHUNK_SIZE, data.length)));
58
            backupFile.addChunk(i, new Chunk(backupFile, i, Arrays.copyOfRange(data, i * MAX_CHUNK_SIZE, data.length)));
59
	    this.peer.addToFileMap(backupFile.getPathname(), backupFile);
60

  
61
            for (i = 0; i < chunks.size(); i++) {
62
                interval = 1000;
63
                byte[] chunk = chunks.get(i).getData();
64
                String message = "PUTCHUNK " + version + " " + peer.getSenderId() + " " + fileId + " " + i + " "
65
                        + this.replicationDeg + " " + CRLF + CRLF;
66

  
67
                byte[] packetData = new byte[message.getBytes().length + chunk.length];
68
                System.arraycopy(message.getBytes(), 0, packetData, 0, message.getBytes().length);
69
                System.arraycopy(chunk, 0, packetData, message.getBytes().length, chunk.length);
70

  
71
                DatagramPacket packet = new DatagramPacket(packetData, packetData.length, MDBaddress, MDBport);
72

  
73
                while (interval <= 31000) { //31 = 1+2+4+8+16
74
                    this.peer.print("sending PUTCHUNK message");
75
                    socket.send(packet);
76
                    Thread.sleep(interval);
77
                    if (this.peer.repDegMap.containsKey(fileId) && this.peer.repDegMap.get(fileId).get(i) >= this.replicationDeg)
78
                        break;
79
                    interval *= 2;
80
                }
81
		if(interval > 31000) {
82
			this.peer.print("Couldn't achieve the desired replication degree.");
83
			this.peer.fileMap.remove(this.filePath);
84
			return;
85
		}
86
            }
87
            socket.close();
88
            this.peer.print("BACKUP protocol finished");
89
            
90
        } catch (IOException | NoSuchAlgorithmException | InterruptedException e) {
91
            e.printStackTrace();
92
        }
93
    }
94
}
Chunk.java
1
/**
2
 * Chunk
3
 */
4
public class Chunk {
5
    private BackupFile file;
6
    private int chunkNo;
7
    private int size;
8
    private byte[] data;
9
    private boolean recentlyRequested;
10

  
11
    public Chunk(BackupFile file, int chunkNo) {
12
        this.file = file;
13
        this.chunkNo = chunkNo;
14

  
15
        this.size = 0;
16
        this.recentlyRequested = false;
17
    }
18

  
19
    public Chunk(BackupFile file, int chunkNo, byte[] data) {
20
        this.file = file;
21
        this.chunkNo = chunkNo;
22
        this.data = data;
23

  
24
        this.size = this.data.length;
25
        this.recentlyRequested = false;
26
    }
27

  
28
    public boolean getRecentlyRequested() {
29
        return this.recentlyRequested;
30
    }
31

  
32
    public void setRecentlyRequested() {
33
        this.recentlyRequested = true;
34
    }
35

  
36
    /**
37
     * @return the data
38
     */
39
    public byte[] getData() {
40
        return data;
41
    }
42

  
43
    /**
44
     * @return the size
45
     */
46
    public int getSize() {
47
        return size;
48
    }
49

  
50
    /**
51
     * @return the chunkNo
52
     */
53
    public int getChunkNo() {
54
        return chunkNo;
55
    }
56

  
57
    /**
58
     * @return the file
59
     */
60
    public BackupFile getFile() {
61
        return file;
62
    }
63

  
64
    public String getPath() {
65
        return this.getDir()+"\\"+this.chunkNo;
66
    }
67

  
68
    public String getDir() {
69
        return "Chunks\\"+this.file.getFileId();
70
    }
71

  
72
	public void setData(byte[] body) {
73
		this.data = body;
74
	}
75
}
ChunkTask.java
1
/**
2
 * PutChunkTask
3
 */
4
public class ChunkTask implements Runnable {
5
    private String fileId;
6
    private byte[] body;
7

  
8
    private Peer peer;
9
    private MDRListener mdr;
10

  
11
    ChunkTask(String[] args, Peer peer, MDRListener mdr, byte[] body) {
12
        //CHUNK <Version> <SenderId> <FileId> <ChunkNo> <CRLF><CRLF><Body>
13
        this.fileId = args[3];
14
        this.body = body;
15

  
16
        this.peer = peer;
17
        this.mdr = mdr;
18
    }
19

  
20
    @Override
21
    public void run() {
22
        this.peer.restoreMap.get(fileId).getChunks().add(this.body);
23
        this.mdr.print("CHUNK protocol finished");
24
    }
25
}
DeleteFile.java
1
import java.io.File;
2
import java.util.ArrayList;
3

  
4
/**
5
 * DeleteFile
6
 */
7
public class DeleteFile {
8
    private File file;
9
    private String fileId;
10
    private ArrayList<byte[]> chunks = new ArrayList<>();
11

  
12
    public DeleteFile(String fileId) {
13
        this.fileId = fileId;
14
    }
15

  
16
    public DeleteFile(String path, String fileId) {
17
        this.fileId = fileId;
18
	this.file = new File(path);
19
    }
20

  
21
    /**
22
     * @return the chunks
23
     */
24
    public ArrayList<byte[]> getChunks() {
25
        return chunks;
26
    }
27

  
28
    /**
29
     * @return the fileId
30
     */
31
    public String getFileId() {
32
        return fileId;
33
    }
34

  
35
    public File getFile() {
36
        return this.file;
37
    }
38

  
39
	public boolean hasChunk(int i) {
40
        try {
41
            this.chunks.get(i);
42
        } catch (Exception e) {
43
            return false;
44
        }
45
		return true;
46
	}
47
}
DeleteTask.java
1
import java.io.File;
2
import java.io.IOException;
3
import java.net.DatagramPacket;
4
import java.net.DatagramSocket;
5
import java.net.InetAddress;
6
import java.security.NoSuchAlgorithmException;
7

  
8
/**
9
 * DeleteTask
10
 */
11
public class DeleteTask implements Runnable {
12
    private static final String CRLF = Integer.toHexString(0xD) + Integer.toHexString(0xA);
13

  
14
    private String filePath;
15
    private InetAddress MCaddress;
16
    private int MCport;
17

  
18
    private Peer peer;
19
    private String version;
20

  
21
    DeleteTask(String pathname, String version, Peer peer) {
22
        this.filePath = pathname;
23
        this.MCaddress = peer.getMCaddress();
24
        this.MCport = peer.getMCport();
25
        this.version = version;
26
        this.peer = peer;
27
    }
28
    
29
    @Override
30
    public void run() {
31
        File file = new File(this.filePath);
32
        try {
33
            String fileId = BackupFile.generateFileId(this.filePath, file.lastModified());
34
            DeleteFile deleteFile = new DeleteFile(fileId);
35
            this.peer.deleteMap.put(fileId, deleteFile);
36
            DatagramSocket socket = new DatagramSocket();
37

  
38
            //DELETE <Version> <SenderId> <FileId> <CRLF><CRLF>
39
            String message = "DELETE " + this.version + " " + peer.getSenderId() + " " + fileId + " " + CRLF + CRLF;
40

  
41
            DatagramPacket packet = new DatagramPacket(message.getBytes(), message.length(), this.MCaddress, this.MCport);
42
            this.peer.print("sending DELETE message");
43
            socket.send(packet);
44

  
45
            
46

  
47
            
48
            socket.close();
49
            this.peer.print("DELETE protocol finished");
50
        } catch (IOException | NoSuchAlgorithmException e) {
51
            e.printStackTrace();
52
        }
53
    }
54
}
GetchunkTask.java
1
import java.io.File;
2
import java.io.FileInputStream;
3
import java.io.IOException;
4
import java.net.DatagramPacket;
5
import java.net.DatagramSocket;
6
import java.rmi.NotBoundException;
7
import java.rmi.registry.LocateRegistry;
8
import java.rmi.registry.Registry;
9
import java.util.Random;
10

  
11
/**
12
 * GetchunkTask
13
 */
14
public class GetchunkTask implements Runnable {
15
    private static final String CRLF = Integer.toHexString(0xD) + Integer.toHexString(0xA);
16

  
17
    private Peer peer;
18
    private String fileId;
19
    private int chunkNo;
20
    private MCListener mc;
21

  
22
    private String version;
23

  
24
    private String senderId;
25

  
26
    // GETCHUNK <Version> <SenderId> <FileId> <ChunkNo> <CRLF><CRLF>
27
    GetchunkTask(Peer peer, String[] args, MCListener mc) {
28
        this.peer = peer;
29
        this.fileId = args[3];
30
        this.version = args[1];
31
        this.senderId = args[2];
32
        this.chunkNo = Integer.parseInt(args[4]);
33
        this.mc = mc;
34

  
35
        this.mc.print("starting GETCHUNK protocol: [fileId] " + fileId + "[chunkNo] " + chunkNo);
36
    }
37

  
38
    @Override
39
    public void run() {
40
        File file = new File("Peer-" + this.peer.getSenderId() + File.separator + "Chunks" + File.separator + fileId
41
                + File.separator + chunkNo);
42
        try {
43
            FileInputStream stream = new FileInputStream(file);
44
            byte[] chunk = new byte[(int) file.length()];
45
            stream.read(chunk);
46
            stream.close();
47
            Random random = new Random();
48
            Thread.sleep(random.nextInt(401)); // [0-400] ms
49

  
50
            if (this.peer.chunksMap.get(fileId).getChunksMap().get(chunkNo).getRecentlyRequested()) {
51
                this.mc.print("Chunk was sent by another peer already");
52
                return;
53
            }
54

  
55
            //Protocol enhancement - 
56
            if (this.version.equals("2.0")) {
57
                Registry registry = LocateRegistry.getRegistry();
58
                TestAppRemote stub = (TestAppRemote) registry.lookup(this.senderId);
59
                stub.chunk(this.fileId, chunk);
60
            } else {
61
                // CHUNK <Version> <SenderId> <FileId> <ChunkNo> <CRLF><CRLF><Body>
62
                String message = "CHUNK " + this.version + " " + this.peer.getSenderId() + " " + fileId + " "
63
                        + chunkNo + " " + CRLF + CRLF;
64

  
65
                byte[] packetData = new byte[message.getBytes().length + chunk.length];
66
                System.arraycopy(message.getBytes(), 0, packetData, 0, message.getBytes().length);
67
                System.arraycopy(chunk, 0, packetData, message.getBytes().length, chunk.length);
68

  
69
                DatagramSocket socket = new DatagramSocket();
70
                DatagramPacket packet = new DatagramPacket(packetData, packetData.length, this.peer.getMDRaddress(),
71
                        this.peer.getMDRport());
72
                socket.send(packet);
73
                socket.close();
74
            }
75

  
76
        } catch (IOException | InterruptedException | NotBoundException e) {
77
			e.printStackTrace();
78
		}
79
        this.mc.print("GETCHUNK protocol finished");
80
    }    
81
}
MCListener.java
1
import java.io.IOException;
2
import java.io.File;
3
import java.net.DatagramPacket;
4
import java.net.InetAddress;
5
import java.net.MulticastSocket;
6
import java.util.Arrays;
7

  
8
/**
9
 * MCListener
10
 */
11
public class MCListener implements Runnable {
12
    private static final int PACKET_SIZE = 256;
13

  
14
    private MulticastSocket socket;
15
    private InetAddress address;
16
    private int port;
17
    private int serverId;
18

  
19
    private Peer peer;
20

  
21
    MCListener(InetAddress address, int port, int serverId, Peer peer) throws IOException {
22
        this.address = address;
23
        this.port = port;
24
        this.serverId = serverId;
25
        this.peer = peer;
26
        socket = new MulticastSocket(port);
27
        socket.joinGroup(this.address);
28
    }
29

  
30
    @Override
31
    public void run() {
32
        print("MC-Listener started: Address-"+this.address.getHostName()+" Port-"+this.port);
33
        while (true) {
34
            byte[] buf = new byte[PACKET_SIZE];
35
            DatagramPacket packet = new DatagramPacket(buf, buf.length);
36
            try {
37
                socket.receive(packet);
38
                parseMessage(Arrays.copyOfRange(buf, 0, packet.getLength()));
39
            } catch (IOException e) {
40
                e.printStackTrace();
41
            }
42
        }
43
    }
44

  
45
    private void parseMessage(byte[] data) {
46
        String message = new String(data);
47
        String[] args = message.split(" ");
48

  
49
        switch (args[0]) {
50
            //STORED <Version> <SenderId> <FileId> <ChunkNo> <CRLF><CRLF>
51
            case "STORED":
52
                String fileId = args[3];
53
                String version = args[1];
54
                int chunkNo = Integer.parseInt(args[4]);
55
                new Thread(new StoredTask(this.peer, fileId, version, chunkNo, this)).start();
56
                print("starting "+args[0]+" protocol");
57
                break;
58
            //GETCHUNK <Version> <SenderId> <FileId> <ChunkNo> <CRLF><CRLF>
59
            case "GETCHUNK":
60
                print("received GETCHUNK message");
61
                if (Integer.parseInt(args[2]) == this.peer.getSenderId() ||
62
                    !this.peer.chunksMap.containsKey(args[3]) || 
63
                    !this.peer.chunksMap.get(args[3]).getChunksMap().containsKey(Integer.parseInt(args[4]))) {
64
                    return;
65
                }
66
                new Thread(new GetchunkTask(this.peer, args, this)).start();
67
                break;
68
            //DELETE <Version> <SenderId> <FileId> <CRLF><CRLF>
69
            case "DELETE":
70
                print("received DELETE message");
71
                if (!this.peer.chunksMap.containsKey(args[3])) {
72
                    return;
73
                }
74
                this.peer.chunksMap.remove(args[3]); //remove ficheiro da hashmap
75
		        this.peer.repDegMap.remove(args[3]);
76
                DeleteFile fileToDelete = new DeleteFile("Peer-" + this.peer.getSenderId() + File.separator + "Chunks" + File.separator + args[3], args[3]);
77
		        this.peer.deleteMap.put(args[3], fileToDelete);
78
		        for(File chunk : fileToDelete.getFile().listFiles()){
79
			    this.peer.removeStorage(chunk.length());
80
			    if(!chunk.delete())
81
				    print("Error deleting chunk");
82
		}
83
		if(!fileToDelete.getFile().delete())
84
				print("Error deleting chunks directory");
85

  
86
                break;
87
            //REMOVED <Version> <SenderId> <FileId> <ChunkNo> <CRLF><CRLF>
88
            case "REMOVED":
89
                print("received REMOVED message");
90
		print("SenderID: "+this.peer.getSenderId());
91
		print("args[2]: "+Integer.parseInt(args[2]));
92
                if (this.peer.getSenderId() == Integer.parseInt(args[2]) || !this.peer.chunksMap.containsKey(args[3]) || !this.peer.chunksMap.get(args[3]).getChunksMap().containsKey(Integer.parseInt(args[4])))
93
                    return;
94
                new Thread(new RemovedTask(this.peer, args, this)).start();
95
                break;
96
        
97
            default:
98
                break;
99
        }
100
    }
101

  
102
    public void print(String message) {
103
        System.out.println("[PEER-"+this.serverId+"-MC] "+message);
104
    }
105
}
MDBListener.java
1
import java.io.File;
2
import java.io.IOException;
3
import java.net.DatagramPacket;
4
import java.net.InetAddress;
5
import java.net.MulticastSocket;
6
import java.util.Arrays;
7

  
8
/**
9
 * MDBListener
10
 */
11
public class MDBListener implements Runnable {
12
    private static final int PACKET_SIZE = 65000; //65KBytes, just enough space for the chunk itself
13
    private MulticastSocket socket;
14
    private InetAddress address;
15
    private int port;
16
    private int serverId;
17

  
18
    private InetAddress MCaddress;
19
    private int MCport;
20

  
21
    private Peer peer;
22

  
23
    MDBListener(InetAddress address, int port, int serverId, InetAddress MCaddress, int MCport, Peer peer) throws IOException {
24
        this.address = address;
25
        this.port = port;
26
        this.serverId = serverId;
27
        this.MCaddress = MCaddress;
28
        this.MCport = MCport;
29
        this.peer = peer;
30

  
31
        socket = new MulticastSocket(port);
32
        socket.joinGroup(this.address);
33
    }
34

  
35
    @Override
36
    public void run() {
37
        print("MDB-Listener started: Address-"+this.address.getHostName()+" Port-"+this.port);
38
        while (true) {
39
            byte[] buf = new byte[PACKET_SIZE];
40
            DatagramPacket packet = new DatagramPacket(buf, buf.length);
41
            try {
42
                socket.receive(packet);
43
                parseMessage(Arrays.copyOfRange(buf, 0, packet.getLength()));
44
            } catch (IOException e) {
45
                e.printStackTrace();
46
            }
47
        }
48
    }
49

  
50
    private void parseMessage(byte[] data) {
51
        String message = new String(data);
52
        String[] args = message.split(" ");
53

  
54
        switch (args[0]) {
55
            case "PUTCHUNK":
56
				print("received PUTCHUNK message: <SenderId> "+args[2]+" <FileId> "+args[3]+" <ChunkNo> "+args[4]+" <replicationDeg> "+args[5]);
57
				int headerLength = 0;
58
				
59
				for(int i = 0; i < 6; i++)
60
					headerLength += args[i].length()+1;
61
				
62
				headerLength += 4;
63
                byte[] body = Arrays.copyOfRange(data, headerLength, data.length);
64
                
65
                String fileId = args[3];
66
                int chunkNo = Integer.parseInt(args[4]);
67
                File chunk = new File("Peer-"+this.serverId+File.separator+"Chunks"+File.separator+fileId+File.separator+chunkNo);
68
                if (Integer.parseInt(args[2]) == this.serverId) {
69
                    print("The initiator-peer can't store the chunks himself!");
70
                    return;
71
                }
72
                if(chunk.exists()){
73
                    print("Chunk already exists");
74
                    return;
75
                }
76

  
77
                new Thread(new PutChunkTask(args, this.MCaddress, this.MCport, this, this.peer, body)).start();
78
                print("starting PUTCHUNK protocol");
79
                break;
80
        
81
            default:
82
                break;
83
        }
84
    }
85

  
86
    public void print(String message) {
87
        System.out.println("[PEER-"+this.serverId+"-MDB] "+message);
88
    }
89
}
MDRListener.java
1
import java.io.IOException;
2
import java.net.DatagramPacket;
3
import java.net.InetAddress;
4
import java.net.MulticastSocket;
5
import java.util.Arrays;
6

  
7
/**
8
 * MDBListener
9
 */
10
public class MDRListener implements Runnable {
11
    private static final int PACKET_SIZE = 65000; //65KBytes, just enough space for the chunk itself
12

  
13
    private MulticastSocket socket;
14
    private InetAddress address;
15
    private int port;
16
    private int serverId;
17

  
18
    private Peer peer;
19

  
20
    MDRListener(InetAddress address, int port, int serverId, InetAddress MCaddress, int MCport, Peer peer)
21
            throws IOException {
22
        this.address = address;
23
        this.port = port;
24
        this.serverId = serverId;
25
        this.peer = peer;
26

  
27
        socket = new MulticastSocket(port);
28
        socket.joinGroup(this.address);
29
    }
30

  
31
    @Override
32
    public void run() {
33
        print("MDR-Listener started: Address-"+this.address.getHostName()+" Port-"+this.port);
34
        while (true) {
35
            byte[] buf = new byte[PACKET_SIZE];
36
            DatagramPacket packet = new DatagramPacket(buf, buf.length);
37
            try {
38
                socket.receive(packet);
39
                parseMessage(Arrays.copyOfRange(buf, 0, packet.getLength()));
40
            } catch (IOException e) {
41
                e.printStackTrace();
42
            }
43
        }
44
    }
45

  
46
    private void parseMessage(byte[] data) {
47
        String message = new String(data);
48
        String[] args = message.split(" ");
49
    
50
        switch (args[0]) {
51
            //CHUNK <Version> <SenderId> <FileId> <ChunkNo> <CRLF><CRLF><Body>
52
            case "CHUNK":
53
		print("received CHUNK message: <SenderId> "+args[2]+" <FileId> "+args[3]+" <ChunkNo> "+args[4]);
54
                if (Integer.parseInt(args[2]) != this.peer.getSenderId()) {
55
                    if (this.peer.restoreMap.containsKey(args[3]) && !this.peer.restoreMap.get(args[3]).hasChunk(Integer.parseInt(args[4]))) {
56
                        int headerLength = 0;
57
                        
58
                        for(int i = 0; i < 5; i++)
59
                            headerLength += args[i].length()+1;
60
                        
61
                        headerLength += 4;
62
                        print("headerLength: "+headerLength+" messageLength: "+message.length());
63
                        byte[] body = Arrays.copyOfRange(data, headerLength, data.length);
64
                        new Thread(new ChunkTask(args, this.peer, this, body)).start();
65
                        print("starting CHUNK protocol");
66
                    }
67
                    if (this.peer.chunksMap.get(args[3]) != null &&
68
                        this.peer.chunksMap.get(args[3]).getChunksMap().contains(Integer.parseInt(args[4]))) {
69
                        
70
                            this.peer.chunksMap.get(args[3]).getChunksMap().get(Integer.parseInt(args[4])).setRecentlyRequested();
71
                    }
72
                }
73
                break;
74
        
75
            default:
76
                break;
77
        }
78
    }
79
    
80
    public void print(String message) {
81
        System.out.println("[PEER-"+this.serverId+"-MDR] "+message);
82
    }
83
}
Peer.java
1
import java.io.File;
2
import java.io.FileInputStream;
3
import java.io.FileOutputStream;
4
import java.io.IOException;
5
import java.net.InetAddress;
6
import java.rmi.RemoteException;
7
import java.rmi.registry.LocateRegistry;
8
import java.rmi.registry.Registry;
9
import java.rmi.server.UnicastRemoteObject;
10
import java.util.concurrent.ConcurrentHashMap;
11

  
12
/**
13
 * Peer
14
 */
15
public class Peer extends Thread implements TestAppRemote {
16
    private int serverId;
17
    private String serviceAccessPoint;
18
    private int storageCapacity = 100000000; //100MB
19
    private int storageUsed = 0;
20

  
21
    //HashMap for all the chunks being backed up by this peer
22
    public ConcurrentHashMap<String, BackupFile> chunksMap = new ConcurrentHashMap<>();
23
    //HashMap for all the chunks retrieved to restore a file
24
    public ConcurrentHashMap<String, RestoreFile> restoreMap = new ConcurrentHashMap<>();
25
    //HashMap for all files asked to be deleted
26
    public ConcurrentHashMap<String, DeleteFile> deleteMap = new ConcurrentHashMap<>();
27
    //HashMap for all perceived replication degrees in the network
28
    public ConcurrentHashMap<String, ConcurrentHashMap<Integer, Integer>> repDegMap = new ConcurrentHashMap<>();
29
    //HashMap for all files backed up in the network
30
    public ConcurrentHashMap<String, BackupFile> fileMap = new ConcurrentHashMap<>();
31

  
32

  
33

  
34
    private InetAddress MDRaddress;
35
    private int MDRport;
36
    private InetAddress MDBaddress;
37
    private int MDBport;
38
    private InetAddress MCaddress;
39
    private int MCport;
40

  
41
    public static void main(String[] args) throws NumberFormatException, IOException {
42
        if(!parseInputs(args))
43
            return;
44
        Peer peer = new Peer(args[0], args[1], args[2], args[3]);
45
        Peer obj = peer;
46
        TestAppRemote stub = (TestAppRemote) UnicastRemoteObject.exportObject(obj, 0);
47

  
48
        // Bind the remote object's stub in the registry
49
        Registry registry = LocateRegistry.getRegistry();
50
        registry.rebind(peer.getServiceAccessPoint(), stub);
51
    }
52

  
53
    public Peer(String serverId, String MC, String MDB, String MDR)
54
            throws NumberFormatException, IOException {
55
        this.serverId = Integer.parseInt(serverId);
56
        this.serviceAccessPoint = serverId;
57

  
58
        String[] MCinfo = MC.split("_");
59
        this.MCaddress = InetAddress.getByName(MCinfo[0]);
60
        this.MCport = Integer.parseInt(MCinfo[1]);
61
        MCListener mcListener = new MCListener(InetAddress.getByName(MCinfo[0]), Integer.parseInt(MCinfo[1]),
62
                this.serverId, this);
63
        new Thread(mcListener).start();
64

  
65
        String[] MDBinfo = MDB.split("_");
66
        this.MDBaddress = InetAddress.getByName(MDBinfo[0]);
67
        this.MDBport = Integer.parseInt(MDBinfo[1]);
68
        MDBListener mdbListener = new MDBListener(InetAddress.getByName(MDBinfo[0]), Integer.parseInt(MDBinfo[1]),
69
                this.serverId, InetAddress.getByName(MCinfo[0]), Integer.parseInt(MCinfo[1]), this);
70
        new Thread(mdbListener).start();
71

  
72
        String[] MDRinfo = MDR.split("_");
73
        this.MDRaddress = InetAddress.getByName(MDRinfo[0]);
74
        this.MDRport = Integer.parseInt(MDRinfo[1]);
75
        MDRListener mdrListener = new MDRListener(InetAddress.getByName(MDRinfo[0]), Integer.parseInt(MDRinfo[1]),
76
                this.serverId, InetAddress.getByName(MCinfo[0]), Integer.parseInt(MCinfo[1]), this);
77
        new Thread(mdrListener).start();
78

  
79
        fillChunksMap();
80
        File dir = new File("Peer-" + this.getSenderId() + File.separator + "Backups");
81
        dir.mkdirs();
82
    }
83

  
84
    // Saves the chunk under the correct directory: "Chunks\FILE_ID\CHUNK_ID"
85
    public void saveChunk(Chunk chunk) throws IOException {
86
        // Create the directory if needed
87
        File dir = new File(chunk.getDir());
88
        dir.mkdirs();
89

  
90
        FileOutputStream outputStream = new FileOutputStream(chunk.getPath());
91
        outputStream.write(chunk.getData());
92

  
93
        outputStream.close();
94
    }
95

  
96
    // Get current storage usage in Bytes
97
    public long getCurrentStorageSize(File dir) {
98
        File[] files = dir.listFiles();
99

  
100
        int count = files.length;
101
        long length = 0;
102

  
103
        for (int i = 0; i < count; i++) {
104
            if (files[i].isFile()) {
105
                length += files[i].length();
106
            } else {
107
                length += getCurrentStorageSize(files[i]);
108
            }
109
        }
110
        return length;
111
    }
112

  
113
    private static boolean parseInputs(String[] args) {
114
        try {
115
            Integer.parseInt(args[0]);
116
        } catch (NumberFormatException e) {
117
            System.out.println("Invalid arguments!: serverId must be a valid int");
118
            return false;
119
        }
120

  
121
        String[] MCinfo = args[1].split("_");
122
        if (MCinfo.length != 2) {
123
            System.out.println("Invalid arguments!: MC name must be of the format <ip_address>_<port>");
124
            return false;
125
        }
126
        try {
127
            InetAddress.getByName(MCinfo[0]);
128
        } catch (Exception e) {
129
            System.out.println("Invalid arguments!: MC IP address must be a valid IP");
130
            return false;
131
        }
132
        try {
133
            Integer.parseInt(MCinfo[1]);
134
        } catch (Exception e) {
135
            System.out.println("Invalid arguments!: MC socket must be valid");
136
            return false;
137
        }
138

  
139
        String[] MDBinfo = args[2].split("_");
140
        if (MDBinfo.length != 2) {
141
            System.out.println("Invalid arguments!: MDB name must be of the format <ip_address>_<port>");
142
            return false;
143
        }
144
        try {
145
            InetAddress.getByName(MDBinfo[0]);
146
        } catch (Exception e) {
147
            System.out.println("Invalid arguments!: MDB IP address must be a valid IP");
148
            return false;
149
        }
150
        try {
151
            Integer.parseInt(MDBinfo[1]);
152
        } catch (Exception e) {
153
            System.out.println("Invalid arguments!: MDB socket must be valid");
154
            return false;
155
        }
156

  
157
        String[] MDRinfo = args[3].split("_");
158
        if (MDRinfo.length != 2) {
159
            System.out.println("Invalid arguments!: MDR name must be of the format <ip_address>_<port>");
160
            return false;
161
        }
162
        try {
163
            InetAddress.getByName(MDRinfo[0]);
164
        } catch (Exception e) {
165
            System.out.println("Invalid arguments!: MDR IP address must be a valid IP");
166
            return false;
167
        }
168
        try {
169
            Integer.parseInt(MDRinfo[1]);
170
        } catch (Exception e) {
171
            System.out.println("Invalid arguments!: MDR socket must be valid");
172
            return false;
173
        }
174

  
175
        return true;
176
    }
177

  
178
    @Override
179
    public void backup(String pathname, int replicationDeg, boolean enhanced) throws RemoteException {
180
        print("starting BACKUP protocol");
181
        if (enhanced) {
182
            new Thread(new BackupTask(pathname, replicationDeg, "2.0", this)).start();
183
        } else {
184
            new Thread(new BackupTask(pathname, replicationDeg, "1.0", this)).start();
185
        }
186
    }
187

  
188
    @Override
189
    public void restore(String pathname, boolean enhanced) throws RemoteException {
190
        print("starting RESTORE protocol");
191
        if (enhanced) {
192
            new Thread(new RestoreTask(pathname, "2.0", this)).start();
193
        } else {
194
            new Thread(new RestoreTask(pathname, "1.0", this)).start();
195
        }        
196
    }
197

  
198
    @Override
199
    public void delete(String pathname, boolean enhanced) throws RemoteException {
200
        print("starting DELETE protocol");
201
        if (enhanced) {
202
            new Thread(new DeleteTask(pathname, "2.0", this)).start();
203
        } else {
204
            new Thread(new DeleteTask(pathname, "1.0", this)).start();
205
        }
206
    }
207

  
208
    @Override
209
    public void reclaim(int diskspace) throws RemoteException {
210
        print("starting RECLAIM protocol");
211
        new Thread(new ReclaimTask(diskspace, this)).start();
212
    }
213

  
214
    @Override
215
    public void state() throws RemoteException {
216
        print("starting STATE protocol");
217
        new Thread(new StateTask(this)).start();
218
    }
219

  
220
    @Override
221
    public void chunk(String fileId, byte[] chunk) throws RemoteException {
222
        this.print("Enhanced CHUNK protocol started");
223
        this.restoreMap.get(fileId).getChunks().add(chunk);
224
        this.print("Enhanced CHUNK protocol finished");
225
    }
226

  
227
    public String getServiceAccessPoint() {
228
        return this.serviceAccessPoint;
229
    }
230

  
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff