root / proj / src / Peer.java @ 1
History | View | Annotate | Download (12.7 KB)
1 |
|
---|---|
2 |
import java.io.BufferedInputStream; |
3 |
import java.io.BufferedWriter; |
4 |
import java.io.File; |
5 |
import java.io.FileInputStream; |
6 |
import java.io.FileNotFoundException; |
7 |
import java.io.FileOutputStream; |
8 |
import java.io.FileWriter; |
9 |
import java.io.IOException; |
10 |
import java.io.InputStream; |
11 |
import java.io.ObjectOutputStream; |
12 |
import java.io.OutputStream; |
13 |
import java.net.UnknownHostException; |
14 |
import java.nio.charset.StandardCharsets; |
15 |
import java.nio.file.Files; |
16 |
import java.nio.file.Paths; |
17 |
import java.rmi.registry.LocateRegistry; |
18 |
import java.rmi.registry.Registry; |
19 |
import java.rmi.server.UnicastRemoteObject; |
20 |
import java.security.MessageDigest; |
21 |
import java.util.ArrayList; |
22 |
import java.util.concurrent.TimeUnit; |
23 |
|
24 |
|
25 |
|
26 |
|
27 |
public class Peer implements RMI { |
28 |
|
29 |
|
30 |
//final static int PORT = 8888;
|
31 |
private static String version; |
32 |
private static int server_id; |
33 |
private static int peerID; |
34 |
private static String mcIp = "224.0.0.3"; |
35 |
private static int mcPort = 8888; |
36 |
private static String mdbIp; |
37 |
private static int mdbPort; |
38 |
private static String mdrIp; |
39 |
private static int mdrPort; |
40 |
|
41 |
private static Channel mc; |
42 |
private static Channel mdb; |
43 |
private static Channel mdr; |
44 |
private boolean lastChunk = false; |
45 |
|
46 |
|
47 |
|
48 |
private static StorageSystem storage; |
49 |
|
50 |
private int chunkIterator = 0; |
51 |
private Peer(String mcIp, int mcPort, String mdbIp, int mdbPort, String mdrIp, int mdrPort) throws IOException { |
52 |
mc = new Channel(mcIp, mcPort, this); |
53 |
mdb = new Channel(mdbIp, mdbPort, this); |
54 |
mdr = new Channel(mdrIp,mdrPort, this); |
55 |
|
56 |
new Thread(mc).start(); |
57 |
new Thread(mdb).start(); |
58 |
new Thread(mdr).start(); |
59 |
} |
60 |
|
61 |
|
62 |
public static void main(String[] args) throws UnknownHostException, InterruptedException { |
63 |
|
64 |
setVersion(args[0]);
|
65 |
server_id = Integer.parseInt(args[1]); |
66 |
peerID = Integer.parseInt(args[2]); |
67 |
mcIp = args[3];
|
68 |
mcPort = Integer.parseInt(args[4]); |
69 |
mdbIp = args[5];
|
70 |
mdbPort = Integer.parseInt(args[6]); |
71 |
mdrIp = args[7];
|
72 |
mdrPort = Integer.parseInt(args[8]); |
73 |
|
74 |
storage = new StorageSystem(peerID);
|
75 |
|
76 |
|
77 |
try {
|
78 |
|
79 |
Peer obj = new Peer(mcIp, mcPort, mdbIp, mcPort, mdrIp, mcPort);
|
80 |
|
81 |
RMI stub = (RMI) UnicastRemoteObject.exportObject(obj, 0); |
82 |
|
83 |
// Binding the remote object (stub) in the registry
|
84 |
Registry registry = LocateRegistry.getRegistry(); |
85 |
registry.rebind(args[2], stub);
|
86 |
|
87 |
|
88 |
System.err.println("Peer ready"); |
89 |
|
90 |
|
91 |
|
92 |
|
93 |
} catch (Exception e) { |
94 |
System.err.println("Peer exception: " + e.toString()); |
95 |
e.printStackTrace(); |
96 |
} |
97 |
} |
98 |
|
99 |
|
100 |
public void operation(String operation, String file_path, int rep_degree, double space) { //operator is space for reclaim, rep_degree for back up |
101 |
|
102 |
|
103 |
if(operation.equals("BACKUP")) |
104 |
{ |
105 |
|
106 |
try {
|
107 |
initiateBackup(file_path, rep_degree); |
108 |
} catch (InterruptedException e) { |
109 |
// TODO Auto-generated catch block
|
110 |
e.printStackTrace(); |
111 |
} |
112 |
|
113 |
} |
114 |
else if(operation.equals("RESTORE")) |
115 |
{ |
116 |
try {
|
117 |
initiateRestore(file_path); |
118 |
} catch (IOException e) { |
119 |
// TODO Auto-generated catch block
|
120 |
e.printStackTrace(); |
121 |
} |
122 |
|
123 |
} |
124 |
else if(operation.equals("DELETE")) |
125 |
{ |
126 |
try {
|
127 |
initiateDelete(file_path); |
128 |
} catch (Exception e) { |
129 |
// TODO Auto-generated catch block
|
130 |
e.printStackTrace(); |
131 |
} |
132 |
|
133 |
} |
134 |
else if(operation == "RECLAIM") |
135 |
{ |
136 |
initiateReclaim(space); |
137 |
} |
138 |
|
139 |
|
140 |
} |
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 |
|
147 |
private void initiateReclaim(double space) { |
148 |
|
149 |
|
150 |
|
151 |
for(int i = 0 ; i < storage.getChunks().size();i++) { |
152 |
if(space > 0) { |
153 |
Chunk chunk = storage.getChunks().get(i); |
154 |
space -= chunk.getsize(); |
155 |
|
156 |
Message msg = new Message("REMOVED", getVersion(), this.getPeerID(), chunk.getFileID(), chunk.getChunkN(), 0 , null); |
157 |
byte[] msgByte = msg.sendable(); |
158 |
|
159 |
try {
|
160 |
mc.sendMessage(msgByte); |
161 |
} catch (UnknownHostException e) { |
162 |
// TODO Auto-generated catch block
|
163 |
e.printStackTrace(); |
164 |
} |
165 |
String newfilename = "Peer"+this.getPeerID() + "/"+ chunk.getFileID()+ "/chk" + chunk.getChunkN(); |
166 |
|
167 |
File file = new File(newfilename); |
168 |
file.delete(); |
169 |
storage.deleteChunk(chunk); |
170 |
|
171 |
} |
172 |
} |
173 |
|
174 |
} |
175 |
|
176 |
|
177 |
private void initiateDelete(String file_path) { |
178 |
String hash = storage.lookUp(file_path);
|
179 |
byte[] msgByte = null; |
180 |
Message msg; |
181 |
msg = new Message("DELETE", getVersion(), this.getPeerID(),hash, 0, 0, null); |
182 |
msgByte = msg.sendable(); |
183 |
System.out.println(msg.messageToStringPrintable());
|
184 |
try {
|
185 |
mdr.sendMessage(msgByte); |
186 |
|
187 |
|
188 |
TimeUnit.SECONDS.sleep(1); |
189 |
|
190 |
} catch (Exception e) { |
191 |
// TODO Auto-generated catch block
|
192 |
e.printStackTrace(); |
193 |
} |
194 |
|
195 |
} |
196 |
|
197 |
public void lastChunk() { |
198 |
this.lastChunk = true; |
199 |
System.out.println("LAST CHUNK"); |
200 |
} |
201 |
|
202 |
|
203 |
private void initiateRestore(String file_path) throws IOException { //GETCHUNK <Version> <SenderId> <FileId> <ChunkNo> <CRLF><CRLF> |
204 |
|
205 |
String hash = storage.lookUp(file_path);
|
206 |
int chunkn = 0; |
207 |
byte[] msgByte = null; |
208 |
Message msg; |
209 |
///getChunksFromFile(hash);
|
210 |
while(!this.lastChunk) { |
211 |
|
212 |
chunkn++; |
213 |
|
214 |
msg = new Message("GETCHUNK", getVersion(), this.getPeerID(),hash,chunkn, 0, null); |
215 |
msgByte = msg.sendable(); |
216 |
System.out.println(msg.messageToStringPrintable());
|
217 |
try {
|
218 |
mdr.sendMessage(msgByte); |
219 |
|
220 |
|
221 |
|
222 |
TimeUnit.SECONDS.sleep(1); |
223 |
|
224 |
} catch (Exception e) { |
225 |
// TODO Auto-generated catch block
|
226 |
e.printStackTrace(); |
227 |
} |
228 |
|
229 |
|
230 |
} |
231 |
|
232 |
String newfilename = "Peer"+this.getPeerID() + "/restore/"+file_path; |
233 |
|
234 |
File file = new File(newfilename); |
235 |
|
236 |
|
237 |
|
238 |
if (!file.exists()) {
|
239 |
file.getParentFile().mkdirs(); |
240 |
file.createNewFile(); |
241 |
} |
242 |
|
243 |
FileOutputStream outputStream = new FileOutputStream(newfilename); |
244 |
|
245 |
|
246 |
|
247 |
for(int i = 0; i < storage.getChunks().size(); i++) { |
248 |
if(storage.getChunks().get(i).getFileID().equals(hash)) {
|
249 |
|
250 |
outputStream.write(storage.getChunks().get(i).getContent()); |
251 |
|
252 |
} |
253 |
} |
254 |
|
255 |
|
256 |
|
257 |
outputStream.close(); |
258 |
|
259 |
this.lastChunk = false; |
260 |
} |
261 |
|
262 |
|
263 |
|
264 |
|
265 |
private void initiateBackup(String file_path, int rep_degree) throws InterruptedException { |
266 |
|
267 |
File file = new File(file_path); |
268 |
String fileID = generateFileID(file);
|
269 |
byte[] msgByte = null; |
270 |
Message msg; |
271 |
boolean stored = false; |
272 |
|
273 |
try {
|
274 |
storage.addFile(file_path, file.lastModified(), fileID); |
275 |
storage.serializeFileInfo(); |
276 |
ArrayList<Chunk> chunks = splitIntoChunksExternal(file, fileID, 64000); |
277 |
|
278 |
|
279 |
for(Chunk chunk : chunks) {
|
280 |
|
281 |
System.out.println("CHUNK N: "+ chunk.getChunkN()+ " SIZE: " + chunk.getContent().length); |
282 |
msg = new Message("PUTCHUNK", getVersion(), this.getPeerID(), chunk.getFileID(),chunk.getChunkN(), rep_degree, chunk.getContent()); |
283 |
msgByte = msg.sendable(); |
284 |
System.out.println(msg.messageToStringPrintable());
|
285 |
mdb.sendMessage(msgByte); |
286 |
|
287 |
for(int i = 0; i < 5 && !stored; i++) { |
288 |
|
289 |
TimeUnit.SECONDS.sleep(i);
|
290 |
|
291 |
if(storedCheck(chunk.getChunkN(), chunk.getFileID()) >= rep_degree) {
|
292 |
stored = true;
|
293 |
} |
294 |
else {
|
295 |
mdb.sendMessage(msgByte); |
296 |
System.out.println(msg.messageToStringPrintable());
|
297 |
|
298 |
} |
299 |
} |
300 |
stored = false;
|
301 |
|
302 |
|
303 |
} |
304 |
|
305 |
|
306 |
|
307 |
} catch (IOException e) { |
308 |
System.err.println("IO Exception: " + e.toString()); |
309 |
e.printStackTrace(); |
310 |
} |
311 |
|
312 |
|
313 |
} |
314 |
|
315 |
private int storedCheck(int chunkN, String fileID) { |
316 |
int timesSaved = 0; |
317 |
|
318 |
for(BackUpInfo info : storage.getBackUps()) {
|
319 |
if(chunkN == info.getChunkN() && info.getFileID().equals(fileID))
|
320 |
timesSaved++; |
321 |
} |
322 |
return timesSaved;
|
323 |
} |
324 |
|
325 |
|
326 |
|
327 |
|
328 |
|
329 |
public int getPeerID() { |
330 |
return peerID;
|
331 |
} |
332 |
|
333 |
public Channel getMC() { |
334 |
return mc;
|
335 |
} |
336 |
|
337 |
public Channel getMDB() { |
338 |
return mdb;
|
339 |
} |
340 |
|
341 |
public Channel getMDR() { |
342 |
return mdr;
|
343 |
} |
344 |
|
345 |
|
346 |
|
347 |
|
348 |
public void saveChunks() throws IOException{ |
349 |
|
350 |
for(int i = 0; i < storage.getChunks().size(); i++) { |
351 |
|
352 |
|
353 |
String filename = "Peer"+this.getPeerID() + "/backup/"+storage.getChunks().get(i).getFileID()+"/chk"+storage.getChunks().get(i).getChunkN(); |
354 |
|
355 |
File file = new File(filename); |
356 |
if (!file.exists()) {
|
357 |
file.getParentFile().mkdirs(); |
358 |
file.createNewFile(); |
359 |
} |
360 |
|
361 |
FileOutputStream fileOut = new FileOutputStream(filename); |
362 |
ObjectOutputStream out = new ObjectOutputStream(fileOut); |
363 |
out.writeObject(storage.getChunks().get(i).getContent()); |
364 |
out.close(); |
365 |
fileOut.close(); |
366 |
} |
367 |
|
368 |
} |
369 |
public static String sha256hashing(String base) { |
370 |
try{
|
371 |
MessageDigest md = MessageDigest.getInstance("SHA-256"); |
372 |
byte[] hashed = md.digest(base.getBytes("UTF-8")); |
373 |
StringBuffer hexString = new StringBuffer(); |
374 |
|
375 |
for (int i = 0; i < hashed.length; i++) { |
376 |
String hex = Integer.toHexString(0xff & hashed[i]); |
377 |
if(hex.length() == 1) hexString.append('0'); |
378 |
hexString.append(hex); |
379 |
} |
380 |
|
381 |
return hexString.toString();
|
382 |
} catch(Exception ex){ |
383 |
throw new RuntimeException(ex); |
384 |
} |
385 |
} |
386 |
|
387 |
String generateFileID(File file) { |
388 |
|
389 |
String aux =file.getName() + file.lastModified();
|
390 |
|
391 |
|
392 |
return sha256hashing(aux);
|
393 |
} |
394 |
|
395 |
public void getChunksFromFile(String hash) throws IOException { |
396 |
|
397 |
|
398 |
try{
|
399 |
Files.exists(Paths.get("Peer"+this.getPeerID() + "/backup/"+hash+"/")); |
400 |
File folder = new File("Peer"+this.getPeerID() + "/backup/"+hash+"/"); |
401 |
File[] files = folder.listFiles(); |
402 |
|
403 |
for (File file : files) |
404 |
{ |
405 |
chunkIterator++; |
406 |
byte[] chunkContent = Files.readAllBytes(file.toPath()); |
407 |
storage.addChunk(new Chunk(hash,chunkIterator,chunkContent));
|
408 |
} |
409 |
chunkIterator = 0;
|
410 |
} |
411 |
catch(FileNotFoundException ex){ |
412 |
System.out.println("Chunks not found" + ex.toString()); |
413 |
ex.printStackTrace(); |
414 |
} |
415 |
|
416 |
|
417 |
} |
418 |
|
419 |
|
420 |
public String getVersion() { |
421 |
return version;
|
422 |
} |
423 |
|
424 |
|
425 |
public static void setVersion(String version) { |
426 |
Peer.version = version; |
427 |
} |
428 |
|
429 |
|
430 |
public StorageSystem getStorage() {
|
431 |
return storage;
|
432 |
} |
433 |
|
434 |
public ArrayList<Chunk> splitIntoChunksExternal(File file, String fileID, int chunk_size) throws IOException |
435 |
{ |
436 |
ArrayList<Chunk> filechunks = new ArrayList<Chunk>(); |
437 |
|
438 |
Boolean lastChunk = false; |
439 |
File willBeRead = file;
|
440 |
int FILE_SIZE = (int) willBeRead.length(); |
441 |
|
442 |
|
443 |
System.out.println("Total File Size: "+FILE_SIZE); |
444 |
|
445 |
byte[] temporary = null; |
446 |
|
447 |
try {
|
448 |
InputStream inStream = null; |
449 |
int totalBytesRead = 0; |
450 |
|
451 |
try {
|
452 |
inStream = new BufferedInputStream ( new FileInputStream( willBeRead )); |
453 |
|
454 |
int chunkCount = 0; |
455 |
while ( totalBytesRead < FILE_SIZE )
|
456 |
{ |
457 |
|
458 |
int bytesRemaining = FILE_SIZE-totalBytesRead;
|
459 |
if ( bytesRemaining < chunk_size )
|
460 |
{ |
461 |
chunk_size = bytesRemaining; |
462 |
lastChunk = true;
|
463 |
} |
464 |
|
465 |
temporary = new byte[chunk_size]; //Temporary Byte Array |
466 |
int bytesRead = inStream.read(temporary, 0, chunk_size); |
467 |
String temp = new String(temporary, StandardCharsets.UTF_8); |
468 |
|
469 |
if ( bytesRead > 0) // If bytes read is not empty |
470 |
{ |
471 |
totalBytesRead += bytesRead; |
472 |
chunkCount++; |
473 |
} |
474 |
|
475 |
filechunks.add(new Chunk(fileID,chunkCount, temporary));
|
476 |
|
477 |
if(bytesRemaining == 0 && lastChunk) |
478 |
filechunks.add(new Chunk(fileID,chunkCount, null)); |
479 |
|
480 |
System.out.println("Total Bytes Read: "+ totalBytesRead); |
481 |
} |
482 |
|
483 |
} |
484 |
finally {
|
485 |
inStream.close(); |
486 |
} |
487 |
} |
488 |
catch (NullPointerException ex) |
489 |
{ |
490 |
System.out.println("File not found"+ex.toString()); |
491 |
ex.printStackTrace(); |
492 |
} |
493 |
catch (FileNotFoundException ex) |
494 |
{ |
495 |
ex.printStackTrace(); |
496 |
} |
497 |
catch (IOException ex) |
498 |
{ |
499 |
ex.printStackTrace(); |
500 |
} |
501 |
|
502 |
return filechunks;
|
503 |
} |
504 |
|
505 |
} |