diff --git a/src/clientP2P/ClientDownload.java b/src/clientP2P/ClientDownload.java index 2f039eb..8774c88 100644 --- a/src/clientP2P/ClientDownload.java +++ b/src/clientP2P/ClientDownload.java @@ -335,7 +335,7 @@ public abstract class ClientDownload extends ServeErrors implements Runnable { protected void setSize() throws InternalError { ProtocolP2PPacket d = createProtocolP2PPacket(new SizeRequest(filename)); try { - d.sendRequest(getHostItemSocket(hostList.get(0))); + d.sendRequest(getHostItemSocket(tracker)); try { Payload p = d.receiveResponse().getPayload(); assert p instanceof SizeResponse : "This payload must be instance of SizeResponse"; @@ -449,6 +449,8 @@ public abstract class ClientDownload extends ServeErrors implements Runnable { // get size setSize(); + // close tracker socket + closeHostItemSocket(tracker); // get hashsum from 1st server in list hash512 = getHashSum512(hostList.get(0)); diff --git a/src/clientP2P/ClientInterfaceCLI.java b/src/clientP2P/ClientInterfaceCLI.java index b961e64..779abeb 100644 --- a/src/clientP2P/ClientInterfaceCLI.java +++ b/src/clientP2P/ClientInterfaceCLI.java @@ -32,6 +32,7 @@ import java.net.SocketException; */ public class ClientInterfaceCLI extends ClientInterface { private Scanner scanner; + private String[] list; /** Constructor with clientManagement, logger and scanner. * @param clientManagement ClientManagement used @@ -53,7 +54,9 @@ public class ClientInterfaceCLI extends ClientInterface { SearchFile searchEngine = new SearchFile(); int optionSearch = 0; String searchInput = ""; - String[] list = clientManagement.listDirectory(); + if (!initFileList()) { + break; + } String[] resultArray = {}; boolean searchChoice = false; while (!searchChoice) { @@ -65,7 +68,7 @@ public class ClientInterfaceCLI extends ClientInterface { optionSearch = Integer.parseInt(scanner.nextLine()); } catch (NumberFormatException e) { System.out.println("Wrong input, try again"); - break; + continue; } switch(optionSearch) { case 1: @@ -146,8 +149,6 @@ public class ClientInterfaceCLI extends ClientInterface { writeLog("File " + f + " unsucessfully downloaded, wrong number", LogLevel.Error); } } - } catch (EmptyDirectory e) { - writeLog("Server has no file in directory", LogLevel.Error); } catch (InternalError e) { writeLog("Client internal error", LogLevel.Error); } catch (UnknownHostException e) { @@ -187,7 +188,7 @@ public class ClientInterfaceCLI extends ClientInterface { while (!contacted && !stop) { try { if (!firstLoop) { - writeLog("Cannot contact tracker. Try again [Y/n] ?", LogLevel.Error); + writeLog("Cannot contact tracker. Try again [Y/n]?", LogLevel.Error); String tryAgain = scanner.nextLine(); if (tryAgain.equals("n") || tryAgain.equals("N")) { stop = true; @@ -205,4 +206,33 @@ public class ClientInterfaceCLI extends ClientInterface { } return !stop; } + + /** Initialize file list + * @return true if successfully initialized + */ + private boolean initFileList() { + boolean contacted = false; + boolean firstLoop = true; + boolean stop = false; + while (!contacted && !stop) { + try { + if (!firstLoop) { + String tryAgain = scanner.nextLine(); + if (tryAgain.equals("n") || tryAgain.equals("N")) { + stop = true; + } + } + firstLoop = false; + list = clientManagement.listDirectory(); + contacted = true; + } catch(EmptyDirectory e) { + writeLog("Tracker has no file registered. Try again [Y/n]?", LogLevel.Error); + } catch(InternalError e) { + writeLog("Internal error while fetching tracked files. Try again [Y/n]?", LogLevel.Error); + } catch(Exception e) { + writeLog("Cannot contact tracker. Try again [Y/n]?", LogLevel.Error); + } + } + return !stop; + } } diff --git a/src/tracker/TrackerManagement.java b/src/tracker/TrackerManagement.java index 1b90610..183be21 100644 --- a/src/tracker/TrackerManagement.java +++ b/src/tracker/TrackerManagement.java @@ -18,6 +18,8 @@ import protocolP2P.RequestResponseCode; import protocolP2P.RatioRequest; import protocolP2P.RatioResponse; import protocolP2P.UpdateRatio; +import protocolP2P.SizeRequest; +import protocolP2P.SizeResponse; import localException.InternalError; import remoteException.EmptyDirectory; import exception.LocalException; @@ -37,6 +39,7 @@ public abstract class TrackerManagement extends ServeErrors implements Runnable protected Map ratioUp = new HashMap<>(); protected Map ratioDown = new HashMap<>(); protected Map> fileList = new HashMap<>(); + protected Map fileSize = new HashMap<>(); protected volatile boolean stop; protected AtomicBoolean writeLock; protected AtomicInteger readLock; @@ -154,6 +157,22 @@ public abstract class TrackerManagement extends ServeErrors implements Runnable List emptyH = new ArrayList<>(); emptyH.add(host); fileList.put(file, emptyH); + try { + writeLog("Registering new file : " + file + ". Sending size request ", LogLevel.Debug); + ProtocolP2PPacket pSReq = createProtocolP2PPacket(new SizeRequest(file)); + pSReq.sendRequest(getHostItemSocket(host)); + SizeResponse pSResp = (SizeResponse)pSReq.receiveResponse().getPayload(); + if (!pSResp.getFilename().equals(file)) { + writeLog("Wrong filename for size response of " + file, LogLevel.Debug); + throw new InternalError(); + } else { + writeLog("Registering size of file " + file, LogLevel.Debug); + fileSize.put(file, Long.valueOf(pSResp.getTotalSize())); + } + } catch (Exception e) { + writeLog("Error while asking for size of " + file, LogLevel.Error); + fileList.remove(file); + } } } writeLock.getAndSet(false); @@ -192,6 +211,7 @@ public abstract class TrackerManagement extends ServeErrors implements Runnable fileList.get(f).remove(host); if(fileList.get(f).isEmpty()) { fileList.remove(f); + fileSize.remove(f); } } writeLock.getAndSet(false); @@ -370,6 +390,45 @@ public abstract class TrackerManagement extends ServeErrors implements Runnable } } + /** Handle Size request + * @param pd Received request + * @throws InternalError + */ + protected < T extends ProtocolP2PPacket > void handleSizeRequest(T pd) throws InternalError { + Payload p = pd.getPayload(); + assert p instanceof SizeRequest : "payload must be an instance of SizeRequest"; + if (!(p instanceof SizeRequest)) { + throw new InternalError(); + } + String f = ((SizeRequest)p).getFilename(); + try { + Long s; + synchronized (this) { + while(writeLock.get()) { + this.wait(); + } + readLock.incrementAndGet(); + s = fileSize.get(f); + readLock.decrementAndGet(); + this.notify(); + } + if (s == null) { + writeLog("Sending NOT FOUND for file " + f + " to " + pd.getHostItem(), LogLevel.Action); + sendNotFound(pd); + } else if (s.equals(Long.valueOf(0))) { + writeLog("Sending EMPTY FILE for file " + f + " to " + pd.getHostItem(), LogLevel.Action); + sendEmptyFile(pd); + } else { + writeLog("Sending SIZE RESPONSE for file " + f + " to " + pd.getHostItem(), LogLevel.Action); + pd.sendResponse(createProtocolP2PPacket(new SizeResponse(f, s.longValue()))); + } + } catch (InterruptedException e) { + throw new InternalError(); + } catch (Exception e) { + writeLog(e, LogLevel.Error); + } + } + /** Handle requests * @throws LocalException @@ -409,6 +468,10 @@ public abstract class TrackerManagement extends ServeErrors implements Runnable writeLog("Received UPDATE RATIO from host " + pd.getHostItem(), LogLevel.Action); handleUpdateRatio(pd); break; + case SIZE_REQUEST: + writeLog("Received SIZE REQUEST from host " + pd.getHostItem(), LogLevel.Action); + handleSizeRequest(pd); + break; default: writeLog("Received grabbage from host " + pd.getHostItem(), LogLevel.Action); sendInternalError(pd);