Revision 1
Final upload
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 |
|
Also available in: Unified diff