root / proj / src / Peer.java @ 1
History | View | Annotate | Download (12.7 KB)
1 | 1 | up20160559 | |
---|---|---|---|
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 | } |