Revision 3
Update
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 |
} |
|
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 java.util.Base64; |
|
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 Base64.getEncoder().withoutPadding().encodeToString(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 |
} |
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 |
}
|
|
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 | 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 |
} |
|
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 |
|
|
11 |
/** |
|
12 |
* ChunkManagement |
|
13 |
*/ |
|
14 |
public class ChunkManagement { |
|
15 |
|
|
16 |
private static ChunkManagement chunkManagementInstance = null; |
|
17 |
|
|
18 |
private Map<String, Map<Integer, Integer>> storesCounter; |
|
19 |
|
|
20 |
private BlockingQueue<Chunk> restoreChunks; |
|
21 |
|
|
22 |
private ChunkManagement() { |
|
23 |
storesCounter = new HashMap<String, Map<Integer, Integer>>(); |
|
24 |
restoreChunks = new LinkedBlockingDeque<Chunk>(); |
|
25 |
} |
|
26 |
|
|
27 |
public static ChunkManagement getInstance() { |
|
28 |
if (chunkManagementInstance == null) { |
|
29 |
chunkManagementInstance = new ChunkManagement(); |
|
30 |
} |
|
31 |
return chunkManagementInstance; |
|
32 |
} |
|
33 |
|
|
34 |
public int getStores(String fileId, int chunkNo) { |
|
35 |
if (!storesCounter.containsKey(fileId)){ |
|
36 |
return 0; |
|
37 |
} |
|
38 |
if (!storesCounter.get(fileId).containsKey(chunkNo)){ |
|
39 |
return 0; |
|
40 |
} |
|
41 |
return storesCounter.get(fileId).get(chunkNo); |
|
42 |
} |
|
43 |
|
|
44 |
public int registerStored(String fileId, int chunkNo) { |
|
45 |
if (!storesCounter.containsKey(fileId)) { |
|
46 |
storesCounter.put(fileId, new HashMap<Integer, Integer>()); |
|
47 |
} |
|
48 |
if (!storesCounter.get(fileId).containsKey(chunkNo)) { |
|
49 |
storesCounter.get(fileId).put(chunkNo, 1); |
|
50 |
} else { |
|
51 |
int nStores = storesCounter.get(fileId).get(chunkNo); |
|
52 |
storesCounter.get(fileId).put(chunkNo, nStores + 1); |
|
53 |
} |
|
54 |
return storesCounter.get(fileId).get(chunkNo); |
|
55 |
} |
|
56 |
|
|
57 |
public int registerRemoved(String fileId, int chunkNo) { |
|
58 |
if (!storesCounter.containsKey(fileId)) { |
|
59 |
return 0; |
|
60 |
} |
|
61 |
if (!storesCounter.get(fileId).containsKey(chunkNo)) { |
|
62 |
return 0; |
|
63 |
} else { |
|
64 |
int nStores = storesCounter.get(fileId).get(chunkNo); |
|
65 |
storesCounter.get(fileId).put(chunkNo, nStores - 1); |
|
66 |
return storesCounter.get(fileId).get(chunkNo); |
|
67 |
} |
|
68 |
} |
|
69 |
|
|
70 |
public void deleteStores(String fileId) { |
|
71 |
storesCounter.remove(fileId); |
|
72 |
} |
|
73 |
|
|
74 |
public void addRestoreChunk(Chunk chunk) { |
|
75 |
restoreChunks.add(chunk); |
|
76 |
} |
|
77 |
|
|
78 |
/** |
|
79 |
* @return the restoreChunks |
|
80 |
*/ |
|
81 |
public BlockingQueue<Chunk> getRestoreChunks() { |
|
82 |
return restoreChunks; |
|
83 |
} |
|
84 |
|
|
85 |
} |
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 |
} |
|
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 + fileSeparator + 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 |
|
|
1 |
package disk; |
|
2 |
|
|
3 |
/** |
|
4 |
* DiskFailedToInitialize |
|
5 |
*/ |
|
6 |
public class DiskFailedToInitialize extends Exception { |
|
7 |
|
|
8 |
public DiskFailedToInitialize() { |
|
9 |
super(); |
|
10 |
} |
|
11 |
|
|
12 | 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 |
|
|
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 | 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 |
} |
|
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 { |
Also available in: Unified diff