Revision 2
Upload Project
src/chunk/Chunk.java | ||
---|---|---|
1 |
package chunk; |
|
2 |
|
|
3 |
import java.io.File; |
|
4 |
import java.io.FileOutputStream; |
|
5 |
import java.io.RandomAccessFile; |
|
6 |
import java.io.UnsupportedEncodingException; |
|
7 |
import java.security.MessageDigest; |
|
8 |
import java.security.NoSuchAlgorithmException; |
|
9 |
|
|
10 |
import javax.xml.bind.DatatypeConverter; |
|
11 |
|
|
12 |
public class Chunk { |
|
13 |
public static final int CHUNK_MAX_SIZE = 64000; |
|
14 |
|
|
15 |
private int chunkNo; |
|
16 |
private String fileID; |
|
17 |
|
|
18 |
private int repDegree; |
|
19 |
|
|
20 |
private byte[] data; |
|
21 |
|
|
22 |
public Chunk(String fileID, int chunkNo, int repDegree, byte[] data) { |
|
23 |
this.chunkNo = chunkNo; |
|
24 |
this.fileID = fileID; |
|
25 |
this.data = data; |
|
26 |
this.repDegree = repDegree; |
|
27 |
} |
|
28 |
|
|
29 |
/** |
|
30 |
* @return The chunk's file ID |
|
31 |
*/ |
|
32 |
public String getFileID() { |
|
33 |
return fileID; |
|
34 |
} |
|
35 |
|
|
36 |
/** |
|
37 |
* @return The chunk number |
|
38 |
*/ |
|
39 |
public int getChunkNo() { |
|
40 |
return chunkNo; |
|
41 |
} |
|
42 |
|
|
43 |
/** |
|
44 |
* @return The chunk replication degree |
|
45 |
*/ |
|
46 |
public int getRepDegree() { |
|
47 |
return repDegree; |
|
48 |
} |
|
49 |
|
|
50 |
/** |
|
51 |
* @return The chunk data byte array |
|
52 |
*/ |
|
53 |
public byte[] getData() { |
|
54 |
return data; |
|
55 |
} |
|
56 |
|
|
57 |
public static Chunk[] splitFile(String path, int repDegree) { |
|
58 |
File file = new File(path); |
|
59 |
return splitFile(file, repDegree); |
|
60 |
} |
|
61 |
|
|
62 |
public static int getNumberOfFileChunks(File file) { |
|
63 |
long nFileBytes = file.length(); |
|
64 |
return (int) ((nFileBytes - 1) / CHUNK_MAX_SIZE + 1); |
|
65 |
} |
|
66 |
|
|
67 |
public static Chunk[] splitFile(File file, int repDegree) { |
|
68 |
if (!file.isFile()) { |
|
69 |
return null; |
|
70 |
} |
|
71 |
long nFileBytes = file.length(); |
|
72 |
int nChunks = getNumberOfFileChunks(file); |
|
73 |
Chunk[] chunks = new Chunk[nChunks]; |
|
74 |
String fileId = generateFileId(file); |
|
75 |
try (RandomAccessFile data = new RandomAccessFile(file, "r")) { |
|
76 |
int nReadBytes = 0; |
|
77 |
for (int i = 0; i < nChunks; i++) { |
|
78 |
int nBytesToRead; |
|
79 |
int nBytesMissing = (int) (nFileBytes - nReadBytes); |
|
80 |
if (nBytesMissing < CHUNK_MAX_SIZE) { |
|
81 |
nBytesToRead = nBytesMissing; |
|
82 |
} else { |
|
83 |
nBytesToRead = CHUNK_MAX_SIZE; |
|
84 |
} |
|
85 |
byte[] newData = new byte[nBytesToRead]; |
|
86 |
data.readFully(newData); |
|
87 |
Chunk newChunk = new Chunk(generateFileId(file), i + 1, repDegree, newData); |
|
88 |
chunks[i] = newChunk; |
|
89 |
nReadBytes += CHUNK_MAX_SIZE; |
|
90 |
} |
|
91 |
} catch (Exception e) { |
|
92 |
e.printStackTrace(); |
|
93 |
} |
|
94 |
return chunks; |
|
95 |
} |
|
96 |
|
|
97 |
public static String generateFileId(File file) { |
|
98 |
MessageDigest digest; |
|
99 |
try { |
|
100 |
digest = MessageDigest.getInstance("SHA-256"); |
|
101 |
} catch (NoSuchAlgorithmException e) { |
|
102 |
e.printStackTrace(); |
|
103 |
return null; |
|
104 |
} |
|
105 |
String toEncode = file.getName() + Long.toString(file.length()); |
|
106 |
byte[] encodedhash; |
|
107 |
try { |
|
108 |
encodedhash = digest.digest(toEncode.getBytes("UTF-8")); |
|
109 |
return DatatypeConverter.printBase64Binary(encodedhash); |
|
110 |
} catch (UnsupportedEncodingException e) { |
|
111 |
e.printStackTrace(); |
|
112 |
} |
|
113 |
return "invalid"; |
|
114 |
} |
|
115 |
|
|
116 |
public static void sortChunkArray(Chunk[] chunks) { |
|
117 |
for (int i = 0; i < chunks.length; i++) { |
|
118 |
Chunk currChunk = chunks[i]; |
|
119 |
int nCurrChunk = currChunk.getChunkNo(); |
|
120 |
if (nCurrChunk != i + 1) { |
|
121 |
Chunk tempChunk = chunks[i]; |
|
122 |
chunks[i] = chunks[nCurrChunk - 1]; |
|
123 |
chunks[nCurrChunk - 1] = tempChunk; |
|
124 |
} |
|
125 |
} |
|
126 |
} |
|
127 |
|
|
128 |
public static void restoreFile(Chunk[] chunks, String filePath) { |
|
129 |
sortChunkArray(chunks); |
|
130 |
try (FileOutputStream fos = new FileOutputStream(filePath)) { |
|
131 |
for (int i = 0; i < chunks.length; i++) { |
|
132 |
fos.write(chunks[i].getData()); |
|
133 |
} |
|
134 |
} catch (Exception e) { |
|
135 |
e.printStackTrace(); |
|
136 |
} |
|
137 |
} |
|
138 |
|
|
139 |
@Override |
|
140 |
public boolean equals(Object obj) { |
|
141 |
if (obj == null) { |
|
142 |
return false; |
|
143 |
} |
|
144 |
final Chunk c = (Chunk) obj; |
|
145 |
return (c.chunkNo == chunkNo && c.fileID.equals(fileID) && c.repDegree == repDegree); |
|
146 |
} |
|
147 |
} |
compile.bat | ||
---|---|---|
1 |
javac .\src\utils\*.java .\src\chunk\*.java .\src\disk\*.java .\src\message\*.java .\src\peer\*.java .\src\peer\channels\*.java .\src\peer\protocols\backup\*.java .\src\peer\protocols\reclaim\*.java .\src\peer\protocols\restore\*.java .\src\peer\protocols\delete\*.java .\src\client\*.java -d .\bin |
src/client/TestApp.java | ||
---|---|---|
1 |
package client; |
|
2 |
|
|
3 |
import utils.Utils; |
|
4 |
|
|
5 |
import java.lang.Integer; |
|
6 |
import java.rmi.NotBoundException; |
|
7 |
import java.rmi.RemoteException; |
|
8 |
import java.rmi.registry.LocateRegistry; |
|
9 |
import java.rmi.registry.Registry; |
|
10 |
|
|
11 |
import peer.PeerInterface; |
|
12 |
|
|
13 |
import java.lang.Float; |
|
14 |
|
|
15 |
/** |
|
16 |
* TestApp |
|
17 |
*/ |
|
18 |
public class TestApp { |
|
19 |
|
|
20 |
private String peer_ap; |
|
21 |
private String operation; |
|
22 |
private String filePath; |
|
23 |
private float diskSpace; |
|
24 |
private int replicationDeg; |
|
25 |
private PeerInterface pInterface; |
|
26 |
|
|
27 |
public static void main(String[] args){ |
|
28 |
TestApp app = new TestApp(args); |
|
29 |
app.processRequest(); |
|
30 |
} |
|
31 |
|
|
32 |
public TestApp(String[] args) { |
|
33 |
if (!handleInputs(args)) { |
|
34 |
usage(); |
|
35 |
return; |
|
36 |
} |
|
37 |
|
|
38 |
connect(); |
|
39 |
} |
|
40 |
|
|
41 |
public void processRequest(){ |
|
42 |
switch (operation) { |
|
43 |
case "BACKUP": |
|
44 |
System.out.println("BACKUP:\n\tFile: " + filePath + "\n\tReplication Degree: " + replicationDeg); |
|
45 |
try { |
|
46 |
pInterface.backup(filePath, replicationDeg); |
|
47 |
} catch (RemoteException e) { |
|
48 |
System.out.println("BACKUP ERROR!"); |
|
49 |
e.printStackTrace(); |
|
50 |
} |
|
51 |
System.out.println("BACKUP SUCCESSFUL!"); |
|
52 |
break; |
|
53 |
case "RESTORE": |
|
54 |
System.out.println("RESTORE:\n\tFile: " + filePath); |
|
55 |
try { |
|
56 |
pInterface.restore(filePath); |
|
57 |
} catch (RemoteException e) { |
|
58 |
System.out.println("RESTORE ERROR!"); |
|
59 |
e.printStackTrace(); |
|
60 |
} |
|
61 |
System.out.println("RESTORE SUCCESSFUL!"); |
|
62 |
break; |
|
63 |
case "DELETE": |
|
64 |
System.out.println("DELETE:\n\tFile: " + filePath); |
|
65 |
try { |
|
66 |
pInterface.delete(filePath); |
|
67 |
} catch (RemoteException e) { |
|
68 |
System.out.println("DELETE ERROR!"); |
|
69 |
e.printStackTrace(); |
|
70 |
} |
|
71 |
System.out.println("DELETE SUCCESSFUL!"); |
|
72 |
break; |
|
73 |
case "RECLAIM": |
|
74 |
System.out.println("RECLAIM:\n\tDisk Space: " + diskSpace); |
|
75 |
try { |
|
76 |
pInterface.reclaim(diskSpace); |
|
77 |
} catch (RemoteException e) { |
|
78 |
System.out.println("RECLAIM ERROR!"); |
|
79 |
e.printStackTrace(); |
|
80 |
} |
|
81 |
System.out.println("RECLAIM SUCCESSFUL!"); |
|
82 |
break; |
|
83 |
case "STATE": |
|
84 |
System.out.println("STATE:"); |
|
85 |
try { |
|
86 |
pInterface.state(); |
|
87 |
} catch (RemoteException e) { |
|
88 |
System.out.println("STATE ERROR!"); |
|
89 |
e.printStackTrace(); |
|
90 |
} |
|
91 |
System.out.println("STATE SUCCESSFUL!"); |
|
92 |
break; |
|
93 |
default: |
|
94 |
break; |
|
95 |
} |
|
96 |
} |
|
97 |
|
|
98 |
|
|
99 |
|
|
100 |
private boolean handleInputs(String[] args) { |
|
101 |
if (args.length < 2) { |
|
102 |
System.out.println("Error: Invalid number of arguments!"); |
|
103 |
return false; |
|
104 |
} |
|
105 |
|
|
106 |
this.peer_ap = args[0]; |
|
107 |
|
|
108 |
this.operation = args[1].toUpperCase(); |
|
109 |
switch (operation) { |
|
110 |
case "BACKUP": |
|
111 |
if (args.length != 4) { |
|
112 |
System.out.println(operation + " error: Invalid number of arguments!"); |
|
113 |
return false; |
|
114 |
} |
|
115 |
if (!Utils.fileExists(args[2])) { |
|
116 |
System.out.println(operation + " error: File doesn't exist!"); |
|
117 |
return false; |
|
118 |
} |
|
119 |
this.filePath = args[2]; |
|
120 |
if (!Utils.isInteger(args[3])) { |
|
121 |
System.out.println(operation + " error: Replication Degree invalid!"); |
|
122 |
return false; |
|
123 |
} |
|
124 |
this.replicationDeg = Integer.parseInt(args[3]); |
|
125 |
break; |
|
126 |
case "RESTORE": |
|
127 |
if (args.length != 3) { |
|
128 |
System.out.println(operation + " error: Invalid number of arguments!"); |
|
129 |
return false; |
|
130 |
} |
|
131 |
if (!Utils.fileExists(args[2])) { |
|
132 |
System.out.println(operation + " error: File doesn't exist!"); |
|
133 |
return false; |
|
134 |
} |
|
135 |
this.filePath = args[2]; |
|
136 |
break; |
|
137 |
case "DELETE": |
|
138 |
if (args.length != 3) { |
|
139 |
System.out.println(operation + " error: Invalid number of arguments!"); |
|
140 |
return false; |
|
141 |
} |
|
142 |
if (!Utils.fileExists(args[2])) { |
|
143 |
System.out.println(operation + " error: File doesn't exist!"); |
|
144 |
return false; |
|
145 |
} |
|
146 |
this.filePath = args[2]; |
|
147 |
break; |
|
148 |
case "RECLAIM": |
|
149 |
if (args.length != 3) { |
|
150 |
System.out.println(operation + " error: Invalid number of arguments!"); |
|
151 |
return false; |
|
152 |
} |
|
153 |
if (!Utils.isFloat(args[2])) { |
|
154 |
System.out.println(operation + " error: Maximum amount of disk space invalid!"); |
|
155 |
return false; |
|
156 |
} |
|
157 |
this.diskSpace = Float.parseFloat(args[2]); |
|
158 |
break; |
|
159 |
case "STATE": |
|
160 |
if (args.length != 2) { |
|
161 |
System.out.println(operation + " error: Invalid number of arguments!"); |
|
162 |
return false; |
|
163 |
} |
|
164 |
break; |
|
165 |
default: |
|
166 |
System.out.println("Error: Invalid operation!"); |
|
167 |
return false; |
|
168 |
} |
|
169 |
return true; |
|
170 |
} |
|
171 |
|
|
172 |
private static void usage() { |
|
173 |
System.out.println( |
|
174 |
"Usage:\n\tjava TestApp <peer_ap> <operation> <opnd_1> <opnd2>\n\t\t<peer_app>: Peer's access point;\n\t\t<operation>: Operation the peer of backup service must execute. It must be one of: BACKUP, RESTORE, DELETE, RECLAIM, STATE;\n\t\t<opnd_1>: Path Name of the file in case of operations BACKUP, RESTORE or DELETE or maximum amount of disk space (in KByte) in case of operation RECLAIM\n\t\t<opnd_2>: Integer that specifies the desired replication degree for operation BACKUP"); |
|
175 |
return; |
|
176 |
} |
|
177 |
|
|
178 |
public void connect() { |
|
179 |
try { |
|
180 |
Registry rmiReg = LocateRegistry.getRegistry(Registry.REGISTRY_PORT); |
|
181 |
this.pInterface = (PeerInterface) rmiReg.lookup(this.peer_ap); |
|
182 |
} catch (RemoteException | NotBoundException e) { |
|
183 |
e.printStackTrace(); |
|
184 |
} |
|
185 |
} |
|
186 |
} |
src/disk/ChunkManagement.java | ||
---|---|---|
1 |
package disk; |
|
2 |
|
|
3 |
import java.util.HashMap; |
|
4 |
import java.util.HashSet; |
|
5 |
import java.util.Map; |
|
6 |
import java.util.concurrent.BlockingQueue; |
|
7 |
import java.util.concurrent.LinkedBlockingDeque; |
|
8 |
|
|
9 |
import chunk.Chunk; |
|
10 |
import javafx.util.Pair; |
|
11 |
|
|
12 |
/** |
|
13 |
* ChunkManagement |
|
14 |
*/ |
|
15 |
public class ChunkManagement { |
|
16 |
|
|
17 |
private static ChunkManagement chunkManagementInstance = null; |
|
18 |
|
|
19 |
private Map<String, Map<Integer, Integer>> storesCounter; |
|
20 |
|
|
21 |
private BlockingQueue<Chunk> restoreChunks; |
|
22 |
|
|
23 |
private ChunkManagement() { |
|
24 |
storesCounter = new HashMap<String, Map<Integer, Integer>>(); |
|
25 |
restoreChunks = new LinkedBlockingDeque<Chunk>(); |
|
26 |
} |
|
27 |
|
|
28 |
public static ChunkManagement getInstance() { |
|
29 |
if (chunkManagementInstance == null) { |
|
30 |
chunkManagementInstance = new ChunkManagement(); |
|
31 |
} |
|
32 |
return chunkManagementInstance; |
|
33 |
} |
|
34 |
|
|
35 |
public int getStores(String fileId, int chunkNo) { |
|
36 |
if (!storesCounter.containsKey(fileId)){ |
|
37 |
return 0; |
|
38 |
} |
|
39 |
if (!storesCounter.get(fileId).containsKey(chunkNo)){ |
|
40 |
return 0; |
|
41 |
} |
|
42 |
return storesCounter.get(fileId).get(chunkNo); |
|
43 |
} |
|
44 |
|
|
45 |
public int registerStored(String fileId, int chunkNo) { |
|
46 |
if (!storesCounter.containsKey(fileId)) { |
|
47 |
storesCounter.put(fileId, new HashMap<Integer, Integer>()); |
|
48 |
} |
|
49 |
if (!storesCounter.get(fileId).containsKey(chunkNo)) { |
|
50 |
storesCounter.get(fileId).put(chunkNo, 1); |
|
51 |
} else { |
|
52 |
int nStores = storesCounter.get(fileId).get(chunkNo); |
|
53 |
storesCounter.get(fileId).put(chunkNo, nStores + 1); |
|
54 |
} |
|
55 |
return storesCounter.get(fileId).get(chunkNo); |
|
56 |
} |
|
57 |
|
|
58 |
public int registerRemoved(String fileId, int chunkNo) { |
|
59 |
if (!storesCounter.containsKey(fileId)) { |
|
60 |
return 0; |
|
61 |
} |
|
62 |
if (!storesCounter.get(fileId).containsKey(chunkNo)) { |
|
63 |
return 0; |
|
64 |
} else { |
|
65 |
int nStores = storesCounter.get(fileId).get(chunkNo); |
|
66 |
storesCounter.get(fileId).put(chunkNo, nStores - 1); |
|
67 |
return storesCounter.get(fileId).get(chunkNo); |
|
68 |
} |
|
69 |
} |
|
70 |
|
|
71 |
public void deleteStores(String fileId) { |
|
72 |
storesCounter.remove(fileId); |
|
73 |
} |
|
74 |
|
|
75 |
public void addRestoreChunk(Chunk chunk) { |
|
76 |
restoreChunks.add(chunk); |
|
77 |
} |
|
78 |
|
|
79 |
/** |
|
80 |
* @return the restoreChunks |
|
81 |
*/ |
|
82 |
public BlockingQueue<Chunk> getRestoreChunks() { |
|
83 |
return restoreChunks; |
|
84 |
} |
|
85 |
|
|
86 |
} |
src/disk/Disk.java | ||
---|---|---|
1 |
package disk; |
|
2 |
|
|
3 |
import chunk.*; |
|
4 |
import utils.Utils; |
|
5 |
|
|
6 |
import java.io.File; |
|
7 |
import java.io.FileOutputStream; |
|
8 |
import java.io.FileInputStream; |
|
9 |
import java.io.IOException; |
|
10 |
|
|
11 |
/** |
|
12 |
* Disk |
|
13 |
*/ |
|
14 |
public class Disk { |
|
15 |
|
|
16 |
public static final String fileSeparator = System.getProperty("file.separator"); |
|
17 |
public static final String filesPath = "." + fileSeparator + "files" + fileSeparator; |
|
18 |
public static final String resourcesPath = filesPath + "resources" + fileSeparator; |
|
19 |
public static final String defaultDiskLocation = filesPath + "peers" + fileSeparator; |
|
20 |
public static final long defaultDiskSize = 10000000; /* Disk size in KBytes */ |
|
21 |
|
|
22 |
private long size; /* Disk size in bytes */ |
|
23 |
private String diskLocation; |
|
24 |
private File directory; |
|
25 |
private File backupDirectory, restoredDirectory; |
|
26 |
|
|
27 |
public void restoreFile(Chunk[] chunks, String fileName) { |
|
28 |
Chunk.restoreFile(chunks, getRestoredDirectoryPath() + fileSeparator + fileName); |
|
29 |
} |
|
30 |
|
|
31 |
public Disk(String diskName) { |
|
32 |
this(diskName, defaultDiskSize); |
|
33 |
} |
|
34 |
|
|
35 |
public Disk(String diskName, float size) { |
|
36 |
this.diskLocation = defaultDiskLocation + diskName; |
|
37 |
this.size = (long) (size * 1000); |
|
38 |
createDiskDirectory(); |
|
39 |
} |
|
40 |
|
|
41 |
/** |
|
42 |
* @return the backupDirectory |
|
43 |
*/ |
|
44 |
public File getBackupDirectory() { |
|
45 |
return backupDirectory; |
|
46 |
} |
|
47 |
|
|
48 |
/** |
|
49 |
* @return the defaultDiskLocation |
|
50 |
*/ |
|
51 |
public static String getDefaultDiskLocation() { |
|
52 |
return defaultDiskLocation; |
|
53 |
} |
|
54 |
|
|
55 |
/** |
|
56 |
* @return the directory |
|
57 |
*/ |
|
58 |
public File getDirectory() { |
|
59 |
return directory; |
|
60 |
} |
|
61 |
|
|
62 |
/** |
|
63 |
* @return the restoredDirectory |
|
64 |
*/ |
|
65 |
public File getRestoredDirectory() { |
|
66 |
return restoredDirectory; |
|
67 |
} |
|
68 |
|
|
69 |
public String getRestoredDirectoryPath() { |
|
70 |
return restoredDirectory.getAbsolutePath(); |
|
71 |
} |
|
72 |
|
|
73 |
public boolean createDiskDirectory() { |
|
74 |
directory = new File(this.diskLocation); |
|
75 |
directory.mkdirs(); |
|
76 |
createBackupDirectory(); |
|
77 |
createRestoredDirectory(); |
|
78 |
return true; |
|
79 |
} |
|
80 |
|
|
81 |
public boolean createBackupDirectory() { |
|
82 |
backupDirectory = new File(this.diskLocation + fileSeparator + "backup"); |
|
83 |
if (backupDirectory.mkdirs()) { |
|
84 |
return true; |
|
85 |
} |
|
86 |
return false; |
|
87 |
} |
|
88 |
|
|
89 |
public boolean createRestoredDirectory() { |
|
90 |
restoredDirectory = new File(this.diskLocation + fileSeparator + "restored"); |
|
91 |
if (restoredDirectory.mkdirs()) { |
|
92 |
return true; |
|
93 |
} |
|
94 |
return false; |
|
95 |
} |
|
96 |
|
|
97 |
public String getDiskLocation() { |
|
98 |
return diskLocation; |
|
99 |
} |
|
100 |
|
|
101 |
public long getSize() { |
|
102 |
return size; |
|
103 |
} |
|
104 |
|
|
105 |
public long getOccupiedSpace() { |
|
106 |
return folderSize(this.directory); |
|
107 |
} |
|
108 |
|
|
109 |
public long getFreeSpace() { |
|
110 |
return size - getOccupiedSpace(); |
|
111 |
} |
|
112 |
|
|
113 |
public static long folderSize(File directory) { |
|
114 |
long length = 0; |
|
115 |
for (File file : directory.listFiles()) { |
|
116 |
if (file.isFile()) |
|
117 |
length += file.length(); |
|
118 |
else |
|
119 |
length += folderSize(file); |
|
120 |
} |
|
121 |
return length; |
|
122 |
} |
|
123 |
|
|
124 |
public File createFileFolder(String fileId) { |
|
125 |
File fileFolder = new File(backupDirectory.getPath() + fileSeparator + fileId); |
|
126 |
fileFolder.mkdirs(); |
|
127 |
return fileFolder; |
|
128 |
} |
|
129 |
|
|
130 |
public boolean storeChunk(Chunk chunk) { |
|
131 |
String fileName = chunk.getChunkNo() + "-" + chunk.getRepDegree(); |
|
132 |
|
|
133 |
File folder = createFileFolder(chunk.getFileID()); |
|
134 |
|
|
135 |
File chunkFile = new File(folder.getPath() + fileSeparator + fileName); |
|
136 |
|
|
137 |
if (chunkFile.exists()) { |
|
138 |
return false; |
|
139 |
} |
|
140 |
|
|
141 |
try (FileOutputStream fos = new FileOutputStream(chunkFile)) { |
|
142 |
fos.write(chunk.getData()); |
|
143 |
} catch (Exception e) { |
|
144 |
e.printStackTrace(); |
|
145 |
return false; |
|
146 |
} |
|
147 |
|
|
148 |
return true; |
|
149 |
} |
|
150 |
|
|
151 |
public File[] getFileChunkFiles(String fileId) { |
|
152 |
File fileChunkDirectory = getFileChunkDirectory(fileId); |
|
153 |
return fileChunkDirectory.listFiles(); |
|
154 |
} |
|
155 |
|
|
156 |
public Chunk[] getFileChunks(String fileId) { |
|
157 |
File chunkFiles[] = getFileChunkFiles(fileId); |
|
158 |
|
|
159 |
Chunk[] chunks = new Chunk[chunkFiles.length]; |
|
160 |
|
|
161 |
for (int i = 0; i < chunkFiles.length; i++) { |
|
162 |
chunks[i] = parseFileToChunk(fileId, chunkFiles[i]); |
|
163 |
} |
|
164 |
|
|
165 |
return chunks; |
|
166 |
} |
|
167 |
|
|
168 |
public File getChunkFile(String fileId, int chunkId) { |
|
169 |
File chunkFiles[] = getFileChunkFiles(fileId); |
|
170 |
for (File chunkFile : chunkFiles) { |
|
171 |
if (chunkFile.getName().startsWith(chunkId + "-")) { |
|
172 |
return chunkFile; |
|
173 |
} |
|
174 |
} |
|
175 |
return null; |
|
176 |
} |
|
177 |
|
|
178 |
public Chunk getChunk(String fileId, int chunkId) { |
|
179 |
Chunk[] chunks = getFileChunks(fileId); |
|
180 |
|
|
181 |
for (Chunk chunk : chunks) { |
|
182 |
if (chunk.getChunkNo() == chunkId) { |
|
183 |
return chunk; |
|
184 |
} |
|
185 |
} |
|
186 |
return null; |
|
187 |
} |
|
188 |
|
|
189 |
public File getFileChunkDirectory(String fileId) { |
|
190 |
return new File(backupDirectory.getPath() + fileSeparator + fileId); |
|
191 |
} |
|
192 |
|
|
193 |
public static Chunk parseFileToChunk(String fileId, File chunkFile) { |
|
194 |
String fileName = chunkFile.getName(); |
|
195 |
String parsedName[] = fileName.split("-"); |
|
196 |
|
|
197 |
int chunkId = Integer.parseInt(parsedName[0]); |
|
198 |
int repDegree = Integer.parseInt(parsedName[1]); |
|
199 |
|
|
200 |
byte[] data = new byte[(int) chunkFile.length()]; |
|
201 |
|
|
202 |
try (FileInputStream fis = new FileInputStream(chunkFile)) { |
|
203 |
fis.read(data); |
|
204 |
} catch (Exception e) { |
|
205 |
|
|
206 |
} |
|
207 |
|
|
208 |
Chunk chunk = new Chunk(fileId, chunkId, repDegree, data); |
|
209 |
|
|
210 |
return chunk; |
|
211 |
} |
|
212 |
|
|
213 |
public void deleteFileDirectory(String fileId) { |
|
214 |
//File fileDir = getFileChunkDirectory(fileId); |
|
215 |
/*try { |
|
216 |
Utils.deleteDirectoryRecursively(fileDir); |
|
217 |
} catch (IOException e) { |
|
218 |
e.printStackTrace(); |
|
219 |
return false; |
|
220 |
} |
|
221 |
return true; |
|
222 |
*/ |
|
223 |
File fileDir = new File(backupDirectory + "\\" + fileId); |
|
224 |
System.out.println("FileDir: \"" + fileDir + "\""); |
|
225 |
Utils.deleteDirectoryRecursively(fileDir); |
|
226 |
} |
|
227 |
|
|
228 |
public boolean deleteChunk(String fileId, int chunkId) { |
|
229 |
File chunkFile = getChunkFile(fileId, chunkId); |
|
230 |
if (!chunkFile.delete()) { |
|
231 |
System.out.println("Failed to delete " + chunkFile); |
|
232 |
return false; |
|
233 |
} |
|
234 |
return true; |
|
235 |
} |
|
236 |
|
|
237 |
} |
src/disk/DiskFailedToInitialize.java | ||
---|---|---|
1 |
package disk; |
|
2 |
|
|
3 |
/** |
|
4 |
* DiskFailedToInitialize |
|
5 |
*/ |
|
6 |
public class DiskFailedToInitialize extends Exception { |
|
7 |
|
|
8 |
public DiskFailedToInitialize() { |
|
9 |
super(); |
|
10 |
} |
|
11 |
|
|
12 |
} |
src/message/InvalidHeaderParameters.java | ||
---|---|---|
1 |
package message; |
|
2 |
|
|
3 |
/** |
|
4 |
* InvalidHeaderParameters |
|
5 |
*/ |
|
6 |
public class InvalidHeaderParameters extends Exception { |
|
7 |
|
|
8 |
private static final long serialVersionUID = -1129574923771068119L; |
|
9 |
|
|
10 |
|
|
11 |
} |
src/message/InvalidSenderProtocolVersion.java | ||
---|---|---|
1 |
package message; |
|
2 |
|
|
3 |
public class InvalidSenderProtocolVersion extends Exception { |
|
4 |
|
|
5 |
private static final long serialVersionUID = -6896672292724504010L; |
|
6 |
|
|
7 |
} |
src/message/Message.java | ||
---|---|---|
1 |
package message; |
|
2 |
|
|
3 |
import chunk.Chunk; |
|
4 |
import peer.Peer; |
|
5 |
|
|
6 |
import java.io.ByteArrayOutputStream; |
|
7 |
import java.io.IOException; |
|
8 |
|
|
9 |
public class Message { |
|
10 |
|
|
11 |
public static final int MESSAGE_PACKET_MAX_SIZE = Chunk.CHUNK_MAX_SIZE + MessageHeader.MESSAGE_HEADER_MAX_SIZE; |
|
12 |
|
|
13 |
private MessageHeader header; |
|
14 |
private byte[] body; |
|
15 |
|
|
16 |
public Message(byte[] data) { |
|
17 |
String rawMessage = new String(data); |
|
18 |
int index = rawMessage.indexOf(MessageHeader.CRLF) + 4; |
|
19 |
byte[] rawHeader = new byte[index+1]; |
|
20 |
System.arraycopy(data, 0, rawHeader, 0, index - 4); |
|
21 |
header = new MessageHeader(new String(rawHeader)); |
|
22 |
int bodyLength = data.length - index; |
|
23 |
body = new byte[bodyLength]; |
|
24 |
System.arraycopy(data, index, body, 0, bodyLength); |
|
25 |
} |
|
26 |
|
|
27 |
public Message(MessageHeader header, byte[] body) { |
|
28 |
this.header = header; |
|
29 |
this.body = body; |
|
30 |
} |
|
31 |
|
|
32 |
public byte[] toBytes() throws IOException { |
|
33 |
byte[] result; |
|
34 |
ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
|
35 |
bos.write(header.toString().getBytes()); |
|
36 |
if (body != null) |
|
37 |
bos.write(body); |
|
38 |
result = bos.toByteArray(); |
|
39 |
return result; |
|
40 |
} |
|
41 |
|
|
42 |
public MessageHeader getHeader() { |
|
43 |
return header; |
|
44 |
} |
|
45 |
|
|
46 |
public byte[] getBody() { |
|
47 |
return body; |
|
48 |
} |
|
49 |
|
|
50 |
/* |
|
51 |
* public static boolean isValid(String message) { String myString = |
|
52 |
* message.substring(0,message.indexOf("\r\n\r\n")); |
|
53 |
* |
|
54 |
* return |
|
55 |
* myString.matches(".* [0-9].[0-9] [0-9]+ .{32} .{6} [0-9]\r\n\r\n(.*)?"); } |
|
56 |
*/ |
|
57 |
|
|
58 |
public static Message parsePutChunkMessage(Chunk chunk, Peer peer) { |
|
59 |
MessageHeader header = new MessageHeader("PUTCHUNK", peer.getpVersion(), peer.getPeerId(), chunk.getFileID(), chunk.getChunkNo(), |
|
60 |
chunk.getRepDegree()); |
|
61 |
Message message = new Message(header, chunk.getData()); |
|
62 |
|
|
63 |
return message; |
|
64 |
} |
|
65 |
|
|
66 |
public static Message parseStoredMessage(Chunk chunk, Peer peer) { |
|
67 |
try { |
|
68 |
MessageHeader header = new MessageHeader("STORED", peer.getpVersion(), peer.getPeerId(), chunk.getFileID(), chunk.getChunkNo()); |
|
69 |
Message message = new Message(header, null); |
|
70 |
return message; |
|
71 |
} catch (InvalidHeaderParameters e) { |
|
72 |
e.printStackTrace(); |
|
73 |
} |
|
74 |
return null; |
|
75 |
} |
|
76 |
|
|
77 |
public static Message parseDeleteMessage(String fileId, Peer peer) { |
|
78 |
try { |
|
79 |
MessageHeader header = new MessageHeader("DELETE", peer.getpVersion(), peer.getPeerId(), fileId); |
|
80 |
Message message = new Message(header, null); |
|
81 |
return message; |
|
82 |
} catch (InvalidHeaderParameters e) { |
|
83 |
e.printStackTrace(); |
|
84 |
} |
|
85 |
return null; |
|
86 |
} |
|
87 |
|
|
88 |
public static Message parseGetChunkMessage(String fileId, int chunkNo, Peer peer) { |
|
89 |
try { |
|
90 |
MessageHeader header = new MessageHeader("GETCHUNK", peer.getpVersion(), peer.getPeerId(), fileId, chunkNo); |
|
91 |
Message message = new Message(header, null); |
|
92 |
return message; |
|
93 |
} catch (InvalidHeaderParameters e) { |
|
94 |
e.printStackTrace(); |
|
95 |
} |
|
96 |
return null; |
|
97 |
} |
|
98 |
|
|
99 |
public static Message parseChunkMessage(Chunk chunk, Peer peer) { |
|
100 |
try { |
|
101 |
MessageHeader header = new MessageHeader("CHUNK", peer.getpVersion(), peer.getPeerId(), chunk.getFileID(), chunk.getChunkNo()); |
|
102 |
Message message = new Message(header, chunk.getData()); |
|
103 |
return message; |
|
104 |
} catch (InvalidHeaderParameters e) { |
|
105 |
e.printStackTrace(); |
|
106 |
} |
|
107 |
return null; |
|
108 |
} |
|
109 |
|
|
110 |
} |
src/message/MessageHeader.java | ||
---|---|---|
1 |
package message; |
|
2 |
|
|
3 |
public class MessageHeader { |
|
4 |
|
|
5 |
public static final String CRLF = "\r\n\r\n"; |
|
6 |
public static final int MESSAGE_HEADER_MAX_SIZE = 1000; |
|
7 |
|
|
8 |
private String messageType, version, fileId; |
|
9 |
private int senderId, chunkNo, replicaDeg; |
|
10 |
|
|
11 |
public MessageHeader(String rawHeader) { |
|
12 |
System.out.println("Messageheader: " + rawHeader); |
|
13 |
String[] sArray = rawHeader.trim().split(" "); |
|
14 |
this.messageType = sArray[0]; |
|
15 |
this.version = sArray[1]; |
|
16 |
this.senderId = Integer.parseInt(sArray[2]); |
|
17 |
this.fileId = sArray[3]; |
|
18 |
System.out.println("fileid: " + fileId); |
|
19 |
if (this.messageType.equals("PUTCHUNK") || this.messageType.equals("STORED") |
|
20 |
|| this.messageType.equals("GETCHUNK") || this.messageType.equals("REMOVED") |
|
21 |
|| this.messageType.equals("CHUNK")) { |
|
22 |
String cn = sArray[4].replaceAll("[^\\d]", ""); |
|
23 |
this.chunkNo = Integer.parseInt(cn); |
|
24 |
} |
|
25 |
if (this.messageType.equals("PUTCHUNK")) { |
|
26 |
String rep = sArray[5].replaceAll("[^\\d]", ""); |
|
27 |
this.replicaDeg = Integer.parseInt(rep); |
|
28 |
} |
|
29 |
} |
|
30 |
|
|
31 |
public MessageHeader(String messageType, String version, int senderId, String fileId, int chunkNo) |
|
32 |
throws InvalidHeaderParameters { |
|
33 |
this.messageType = messageType; |
|
34 |
if (this.messageType.equals("PUTCHUNK")) { |
|
35 |
throw new InvalidHeaderParameters(); |
|
36 |
} |
|
37 |
this.version = version; |
|
38 |
this.senderId = senderId; |
|
39 |
this.fileId = fileId; |
|
40 |
this.chunkNo = chunkNo; |
|
41 |
} |
|
42 |
|
|
43 |
public MessageHeader(String messageType, String version, int senderId, String fileId, int chunkNo, int replicaDeg) { |
|
44 |
this.messageType = messageType; |
|
45 |
this.version = version; |
|
46 |
this.senderId = senderId; |
|
47 |
this.fileId = fileId; |
|
48 |
this.chunkNo = chunkNo; |
|
49 |
this.replicaDeg = replicaDeg; |
|
50 |
} |
|
51 |
|
|
52 |
public MessageHeader(String messageType, String version, int senderId, String fileId) |
|
53 |
throws InvalidHeaderParameters { |
|
54 |
this.messageType = messageType; |
|
55 |
if (!this.messageType.equals("DELETE")) { |
|
56 |
throw new InvalidHeaderParameters(); |
|
57 |
} |
|
58 |
this.version = version; |
|
59 |
this.senderId = senderId; |
|
60 |
this.fileId = fileId; |
|
61 |
} |
|
62 |
|
|
63 |
public String getMessageType() { |
|
64 |
return this.messageType; |
|
65 |
} |
|
66 |
|
|
67 |
public String getVersion() { |
|
68 |
return this.version; |
|
69 |
} |
|
70 |
|
|
71 |
public int getSenderId() { |
|
72 |
return this.senderId; |
|
73 |
} |
|
74 |
|
|
75 |
public String getFileId() { |
|
76 |
return this.fileId; |
|
77 |
} |
|
78 |
|
|
79 |
public int getChunkNo() { |
|
80 |
return this.chunkNo; |
|
81 |
} |
|
82 |
|
|
83 |
public int getReplicaDeg() { |
|
84 |
return this.replicaDeg; |
|
85 |
} |
|
86 |
|
|
87 |
@Override |
|
88 |
public String toString() { |
|
89 |
switch (messageType) { |
|
90 |
case "GETCHUNK": |
|
91 |
return this.messageType + " " + this.version + " " + Integer.toString(this.senderId) + " " + this.fileId |
|
92 |
+ " " + Integer.toString(this.chunkNo) + CRLF; |
|
93 |
case "PUTCHUNK": |
|
94 |
return this.messageType + " " + this.version + " " + Integer.toString(this.senderId) + " " + this.fileId |
|
95 |
+ " " + Integer.toString(this.chunkNo) + " " + Integer.toString(this.replicaDeg) + CRLF; |
|
96 |
case "STORED": |
|
97 |
return this.messageType + " " + this.version + " " + Integer.toString(this.senderId) + " " + this.fileId |
|
98 |
+ " " + Integer.toString(this.chunkNo) + CRLF; |
|
99 |
case "CHUNK": |
|
100 |
return this.messageType + " " + this.version + " " + Integer.toString(this.senderId) + " " + this.fileId |
|
101 |
+ " " + Integer.toString(this.chunkNo) + CRLF; |
|
102 |
case "DELETE": |
|
103 |
return this.messageType + " " + this.version + " " + Integer.toString(this.senderId) + " " + this.fileId |
|
104 |
+ CRLF; |
|
105 |
case "REMOVED": |
|
106 |
return this.messageType + " " + this.version + " " + Integer.toString(this.senderId) + " " + this.fileId |
|
107 |
+ " " + Integer.toString(this.chunkNo) + CRLF; |
|
108 |
default: |
|
109 |
return ""; |
|
110 |
|
|
111 |
} |
|
112 |
} |
|
113 |
} |
src/peer/channels/Handler.java | ||
---|---|---|
1 |
package peer.channels; |
|
2 |
|
|
3 |
import java.net.DatagramPacket; |
|
4 |
|
|
5 |
import chunk.Chunk; |
|
6 |
import disk.ChunkManagement; |
|
7 |
import peer.Peer; |
|
8 |
import peer.protocols.backup.Store; |
|
9 |
import peer.protocols.reclaim.Reclaim; |
|
10 |
import peer.protocols.restore.GetChunk; |
|
11 |
import message.*; |
|
12 |
|
|
13 |
public class Handler implements Runnable { |
|
14 |
|
|
15 |
Peer peer; |
|
16 |
DatagramPacket packet; |
|
17 |
Message msg; |
|
18 |
MessageHeader msgHeader; |
|
19 |
|
|
20 |
public Handler(Peer peer, DatagramPacket packet) { |
|
21 |
this.peer = peer; |
|
22 |
this.packet = packet; |
|
23 |
} |
|
24 |
|
|
25 |
public void parsePacket() { |
|
26 |
int packetLength = packet.getLength(); |
|
27 |
byte[] rawData = new byte[packetLength]; |
|
28 |
byte[] packetData = this.packet.getData(); |
|
29 |
System.arraycopy(packetData, packet.getOffset(), rawData, 0, packetLength); |
|
30 |
this.msg = new Message(rawData); |
|
31 |
this.msgHeader = msg.getHeader(); |
|
32 |
} |
|
33 |
|
|
34 |
@Override |
|
35 |
public void run() { |
|
36 |
|
|
37 |
parsePacket(); |
|
38 |
|
|
39 |
if (this.peer.getPeerId() != this.msgHeader.getSenderId()) |
|
40 |
switch (this.msgHeader.getMessageType()) { |
|
41 |
case "PUTCHUNK": |
|
42 |
handlePUTCHUNK(); |
|
43 |
break; |
|
44 |
case "GETCHUNK": |
|
45 |
handleGETCHUNK(); |
|
46 |
break; |
|
47 |
case "CHUNK": |
|
48 |
handleCHUNK(); |
|
49 |
break; |
|
50 |
case "DELETE": |
|
51 |
handleDELETE(); |
|
52 |
break; |
|
53 |
case "REMOVED": |
|
54 |
handleREMOVED(); |
|
55 |
break; |
|
56 |
default: |
|
57 |
break; |
|
58 |
} |
|
59 |
} |
|
60 |
|
|
61 |
private void handleREMOVED() { |
|
62 |
String fileId = this.msgHeader.getFileId(); |
|
63 |
int chunkNo = this.msgHeader.getChunkNo(); |
|
64 |
ChunkManagement.getInstance().registerRemoved(fileId, chunkNo); |
|
65 |
|
|
66 |
Thread t = new Thread(new Reclaim(peer, fileId, chunkNo)); |
|
67 |
t.start(); |
|
68 |
try { |
|
69 |
t.join(); |
|
70 |
} catch (InterruptedException e) { |
|
71 |
e.printStackTrace(); |
|
72 |
} |
|
73 |
} |
|
74 |
|
|
75 |
public void handlePUTCHUNK() { |
|
76 |
if (this.peer.getDisk().getFreeSpace() < (packet.getLength())) { |
|
77 |
System.out.println("Peer " + this.peer.getPeerId() + "- PUTCHUNK request: Not enough space to store chunk"); |
|
78 |
return; |
|
79 |
} |
|
80 |
|
|
81 |
Chunk chunk = new Chunk(this.msgHeader.getFileId(), this.msgHeader.getChunkNo(), this.msgHeader.getReplicaDeg(), |
|
82 |
this.msg.getBody()); |
|
83 |
|
|
84 |
Thread t = new Thread(new Store(peer, chunk)); |
|
85 |
t.start(); |
|
86 |
try { |
|
87 |
t.join(); |
|
88 |
} catch (InterruptedException e) { |
|
89 |
e.printStackTrace(); |
|
90 |
} |
|
91 |
|
|
92 |
} |
|
93 |
|
|
94 |
public void handleGETCHUNK() { |
|
95 |
String fileId = this.msgHeader.getFileId(); |
|
96 |
int chunkNo = this.msgHeader.getChunkNo(); |
|
97 |
Thread t = new Thread(new GetChunk(peer, fileId, chunkNo)); |
|
98 |
t.start(); |
|
99 |
try { |
|
100 |
t.join(); |
|
101 |
} catch (InterruptedException e) { |
|
102 |
e.printStackTrace(); |
|
103 |
} |
|
104 |
} |
|
105 |
|
|
106 |
public void handleCHUNK() { |
|
107 |
Chunk chunk = new Chunk(this.msgHeader.getFileId(), this.msgHeader.getChunkNo(), this.msgHeader.getReplicaDeg(), |
|
108 |
this.msg.getBody()); |
|
109 |
|
|
110 |
ChunkManagement.getInstance().addRestoreChunk(chunk); |
|
111 |
} |
|
112 |
|
|
113 |
public void handleDELETE() { |
|
114 |
String fileID = msgHeader.getFileId(); |
|
115 |
this.peer.getDisk().deleteFileDirectory(fileID); |
|
116 |
ChunkManagement.getInstance().deleteStores(fileID); |
|
117 |
} |
|
118 |
} |
src/peer/channels/Listener.java | ||
---|---|---|
1 |
package peer.channels; |
|
2 |
|
|
3 |
import peer.Peer; |
|
4 |
import peer.channels.Handler; |
|
5 |
|
|
6 |
import java.io.IOException; |
|
7 |
import java.net.InetAddress; |
|
8 |
import java.net.MulticastSocket; |
|
9 |
import java.net.UnknownHostException; |
|
10 |
|
|
11 |
import message.Message; |
|
12 |
|
|
13 |
import java.net.DatagramPacket; |
|
14 |
|
|
15 |
public class Listener implements Runnable { |
|
16 |
|
|
17 |
private MulticastSocket socket; |
|
18 |
private InetAddress address; |
|
19 |
private int port; |
|
20 |
|
|
21 |
private Peer peer; |
|
22 |
|
|
23 |
public Listener(Peer peer, String address, int port) { |
|
24 |
try { |
|
25 |
this.address = InetAddress.getByName(address); |
|
26 |
} catch (UnknownHostException e) { |
|
27 |
e.printStackTrace(); |
|
28 |
} |
|
29 |
this.port = port; |
|
30 |
this.peer = peer; |
|
31 |
} |
|
32 |
|
|
33 |
@Override |
|
34 |
public void run() { |
|
35 |
try { |
|
36 |
this.socket = new MulticastSocket(port); |
|
37 |
socket.setTimeToLive(1); |
|
38 |
socket.joinGroup(address); |
|
39 |
} catch (IOException e) { |
|
40 |
e.printStackTrace(); |
|
41 |
System.exit(1); |
|
42 |
} |
|
43 |
|
|
44 |
while (true) { |
|
45 |
byte[] buf = new byte[Message.MESSAGE_PACKET_MAX_SIZE]; |
|
46 |
|
|
47 |
DatagramPacket packet = new DatagramPacket(buf, buf.length); |
|
48 |
try { |
|
49 |
socket.receive(packet); |
|
50 |
} catch (IOException e) { |
|
51 |
e.printStackTrace(); |
|
52 |
} |
|
53 |
System.out.println("MC Listener: Packet Received!"); |
|
54 |
Thread handler = new Thread(new Handler(peer, packet)); |
|
55 |
handler.start(); |
|
56 |
try { |
|
57 |
handler.join(); |
|
58 |
} catch (InterruptedException e) { |
|
59 |
e.printStackTrace(); |
|
60 |
} |
|
61 |
} |
|
62 |
|
|
63 |
} |
|
64 |
|
|
65 |
/** |
|
66 |
* @return the socket |
|
67 |
*/ |
|
68 |
public MulticastSocket getSocket() { |
|
69 |
return socket; |
|
70 |
} |
|
71 |
|
|
72 |
/** |
|
73 |
* @return the address |
|
74 |
*/ |
|
75 |
public InetAddress getAddress() { |
|
76 |
return address; |
|
77 |
} |
|
78 |
|
|
79 |
/** |
|
80 |
* @return the port |
|
81 |
*/ |
|
82 |
public int getPort() { |
|
83 |
return port; |
|
84 |
} |
|
85 |
|
|
86 |
/** |
|
87 |
* @return the peer |
|
88 |
*/ |
|
89 |
public Peer getPeer() { |
|
90 |
return peer; |
|
91 |
} |
|
92 |
} |
|
93 |
|
src/peer/channels/Sender.java | ||
---|---|---|
1 |
package peer.channels; |
|
2 |
|
|
3 |
import java.net.InetAddress; |
|
4 |
|
|
5 |
/** |
|
6 |
* Sender |
|
7 |
*/ |
|
8 |
public interface Sender { |
|
9 |
|
|
10 |
public void send(byte[] message); |
|
11 |
|
|
12 |
public void init(InetAddress address, int port); |
|
13 |
|
|
14 |
public void destroy(); |
|
15 |
} |
src/peer/channels/SenderTCP.java | ||
---|---|---|
1 |
package peer.channels; |
|
2 |
|
|
3 |
import java.io.IOException; |
|
4 |
import java.net.InetAddress; |
|
5 |
import java.net.Socket; |
|
6 |
|
|
7 |
/** |
|
8 |
* SenderTCP |
|
9 |
*/ |
|
10 |
public class SenderTCP implements Sender { |
|
11 |
|
|
12 |
private Socket socket; |
|
13 |
|
|
14 |
public SenderTCP() { |
|
15 |
|
|
16 |
} |
|
17 |
|
|
18 |
@Override |
|
19 |
public void send(byte[] message) { |
|
20 |
|
|
21 |
} |
|
22 |
|
|
23 |
@Override |
|
24 |
public void init(InetAddress address, int port) { |
|
25 |
try { |
|
26 |
socket = new Socket(address, port); |
|
27 |
} catch (IOException e) { |
|
28 |
e.printStackTrace(); |
|
29 |
} |
|
30 |
} |
|
31 |
|
|
32 |
@Override |
|
33 |
public void destroy() { |
|
34 |
|
|
35 |
} |
|
36 |
|
|
37 |
|
|
38 |
} |
src/peer/channels/SenderUDP.java | ||
---|---|---|
1 |
package peer.channels; |
|
2 |
|
|
3 |
import java.io.IOException; |
|
4 |
import java.net.DatagramPacket; |
|
5 |
import java.net.DatagramSocket; |
|
6 |
import java.net.InetAddress; |
|
7 |
import java.net.SocketException; |
|
8 |
|
|
9 |
/** |
|
10 |
* SenderUDP |
|
11 |
*/ |
|
12 |
public class SenderUDP implements Sender { |
|
13 |
|
|
14 |
private DatagramSocket socket; |
|
15 |
|
|
16 |
public SenderUDP() { |
|
17 |
} |
|
18 |
|
|
19 |
@Override |
|
20 |
public void send(byte[] message) { |
|
21 |
DatagramPacket packet = new DatagramPacket(message, message.length); |
|
22 |
try { |
|
23 |
socket.send(packet); |
|
24 |
} catch (IOException e) { |
|
25 |
e.printStackTrace(); |
|
26 |
} |
|
27 |
} |
|
28 |
|
|
29 |
@Override |
|
30 |
public void init(InetAddress address, int port) { |
|
31 |
try { |
|
32 |
socket = new DatagramSocket(port, address); |
|
33 |
} catch (SocketException e) { |
|
34 |
e.printStackTrace(); |
|
35 |
} |
|
36 |
} |
|
37 |
|
|
38 |
@Override |
|
39 |
public void destroy() { |
|
40 |
socket.disconnect(); |
|
41 |
} |
|
42 |
|
|
43 |
|
|
44 |
|
|
45 |
} |
src/peer/protocols/backup/Backup.java | ||
---|---|---|
1 |
package peer.protocols.backup; |
|
2 |
|
|
3 |
import java.io.File; |
|
4 |
|
|
5 |
import chunk.Chunk; |
|
6 |
import peer.Peer; |
|
7 |
|
|
8 |
/** |
|
9 |
* Backup |
|
10 |
*/ |
|
11 |
public class Backup implements Runnable { |
|
12 |
|
|
13 |
private Peer peer; |
|
14 |
private File file; |
|
15 |
private int repDegree; |
|
16 |
|
|
17 |
public Backup(Peer peer, String path, int repDegree) { |
|
18 |
file = new File(path); |
|
19 |
this.peer = peer; |
|
20 |
this.repDegree = repDegree; |
|
21 |
} |
|
22 |
|
|
23 |
public void backupFile() { |
|
24 |
Chunk[] chunks = Chunk.splitFile(file, repDegree); |
|
25 |
for (int i = 0;i<chunks.length;i++){ |
|
26 |
BackupChunk backupChunk = new BackupChunk(peer, chunks[i]); |
|
27 |
Thread bThread = new Thread(backupChunk); |
|
28 |
bThread.start(); |
|
29 |
} |
|
30 |
} |
|
31 |
|
|
32 |
@Override |
|
33 |
public void run() { |
|
34 |
backupFile(); |
|
35 |
} |
|
36 |
} |
src/peer/protocols/backup/BackupChunk.java | ||
---|---|---|
1 |
package peer.protocols.backup; |
|
2 |
|
|
3 |
import java.io.IOException; |
|
4 |
|
|
5 |
import chunk.Chunk; |
|
6 |
import disk.ChunkManagement; |
|
7 |
import message.Message; |
|
8 |
import peer.Peer; |
|
9 |
|
|
10 |
/** |
|
11 |
* BackupChunk |
|
12 |
*/ |
|
13 |
public class BackupChunk implements Runnable { |
|
14 |
|
|
15 |
public static final int backupTries = 10; |
|
16 |
|
|
17 |
private Chunk chunk; |
|
18 |
private Peer peer; |
|
19 |
|
|
20 |
public BackupChunk(Peer peer, Chunk chunk) { |
|
21 |
this.chunk = chunk; |
|
22 |
this.peer = peer; |
|
23 |
} |
|
24 |
|
|
25 |
public void sendPutChunk() { |
|
26 |
Message message = Message.parsePutChunkMessage(chunk, peer); |
|
27 |
try { |
|
28 |
peer.sendToMdb(message); |
|
29 |
} catch (IOException e) { |
|
30 |
e.printStackTrace(); |
|
31 |
} |
|
32 |
} |
|
33 |
|
|
34 |
public boolean backupChunk() { |
|
35 |
sendPutChunk(); |
|
36 |
try { |
|
37 |
Thread.sleep(400); |
|
38 |
} catch (InterruptedException e) { |
|
39 |
e.printStackTrace(); |
|
40 |
} |
|
41 |
if (ChunkManagement.getInstance().getStores(chunk.getFileID(), chunk.getChunkNo()) >= chunk.getRepDegree()) { |
|
42 |
return true; |
|
43 |
} |
|
44 |
return false; |
|
45 |
} |
|
46 |
|
|
47 |
@Override |
|
48 |
public void run() { |
|
49 |
try { |
|
50 |
Thread.sleep(400 * chunk.getChunkNo()); |
|
51 |
} catch (InterruptedException e) { |
|
52 |
// TODO Auto-generated catch block |
|
53 |
e.printStackTrace(); |
|
54 |
} |
|
55 |
boolean done = false; |
|
56 |
int tries = 0; |
|
57 |
while(!done) { |
|
58 |
done = backupChunk(); |
|
59 |
if (!done) { |
|
60 |
tries++; |
|
61 |
if (tries > backupTries) { |
|
62 |
break; |
|
63 |
} |
|
64 |
} |
|
65 |
} |
|
66 |
} |
|
67 |
} |
src/peer/protocols/backup/Store.java | ||
---|---|---|
1 |
package peer.protocols.backup; |
|
2 |
|
|
3 |
import java.io.IOException; |
|
4 |
|
|
5 |
import chunk.Chunk; |
|
6 |
import disk.ChunkManagement; |
|
7 |
import message.Message; |
|
8 |
import peer.Peer; |
|
9 |
|
|
10 |
/** |
|
11 |
* Store |
|
12 |
*/ |
|
13 |
public class Store implements Runnable { |
|
14 |
|
|
15 |
private Peer peer; |
|
16 |
private Chunk chunk; |
|
17 |
|
|
18 |
public Store(Peer peer, Chunk chunk) { |
|
19 |
this.peer = peer; |
|
20 |
this.chunk = chunk; |
|
21 |
} |
|
22 |
|
|
23 |
public void sendStored() { |
|
24 |
Message storedMessage = Message.parseStoredMessage(chunk, peer); |
|
25 |
try { |
|
26 |
peer.sendToMc(storedMessage); |
|
27 |
} catch (IOException e) { |
|
28 |
e.printStackTrace(); |
|
29 |
} |
|
30 |
} |
|
31 |
|
|
32 |
public boolean storeChunk() { |
|
33 |
try { |
|
34 |
Thread.sleep((long) (Math.random() * 400 + 1)); |
|
35 |
} catch (InterruptedException e) { |
|
36 |
e.printStackTrace(); |
|
37 |
} |
|
38 |
if (ChunkManagement.getInstance().getStores(chunk.getFileID(), chunk.getChunkNo()) < chunk.getRepDegree()) { |
|
39 |
if (peer.getDisk().storeChunk(chunk)) { |
|
40 |
sendStored(); |
|
41 |
return true; |
|
42 |
} |
|
43 |
} |
|
44 |
return false; |
|
45 |
} |
|
46 |
|
|
47 |
@Override |
|
48 |
public void run() { |
|
49 |
storeChunk(); |
|
50 |
} |
|
51 |
|
|
52 |
} |
src/peer/protocols/delete/Delete.java | ||
---|---|---|
1 |
package peer.protocols.delete; |
|
2 |
|
|
3 |
import java.io.File; |
|
4 |
import java.io.IOException; |
|
5 |
|
|
6 |
import chunk.Chunk; |
|
7 |
import message.Message; |
|
8 |
import peer.Peer; |
|
9 |
|
|
10 |
/** |
|
11 |
* Delete |
|
12 |
*/ |
|
13 |
public class Delete implements Runnable { |
|
14 |
|
|
15 |
private Peer peer; |
|
16 |
private String fileId; |
|
17 |
|
|
18 |
public Delete(Peer peer, String fileId) { |
|
19 |
this.peer = peer; |
Also available in: Unified diff