Projet_JAVA_P2P_STRI2A/src/tracker/TrackerManagement.java
Louis 1355ef14b1
All checks were successful
flavien's git/Projet_JAVA_P2P_STRI2A/pipeline/head This commit looks good
flavien's git/Projet_JAVA_P2P_STRI2A/pipeline/pr-master This commit looks good
Fix #40
2020-03-22 16:55:05 +01:00

202 lines
6.2 KiB
Java

package tracker;
import tools.ServeErrors;
import tools.HostItem;
import tools.Logger;
import tools.LogLevel;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.List;
import protocolP2P.ProtocolP2PPacket;
import protocolP2P.Payload;
import protocolP2P.DiscoverRequest;
import protocolP2P.DiscoverResponse;
import protocolP2P.FileList;
import protocolP2P.Unregister;
import protocolP2P.Register;
import protocolP2P.RequestResponseCode;
import localException.InternalError;
import remoteException.EmptyDirectory;
import exception.LocalException;
/** Tracker management implementation
* @author Louis Royer
* @author Flavien Haas
* @author JS Auge
* @version 1.0
*/
public abstract class TrackerManagement extends ServeErrors implements Runnable {
protected HostItem tracker;
protected Logger logger;
protected List<HostItem> hostList = new ArrayList<>();
protected Map<String, List<HostItem>> fileList = new HashMap<>();
protected volatile boolean stop;
/** Constructor
* @param tracker Tracker HostItem
* @param logger Logger
*/
public TrackerManagement(HostItem tracker, Logger logger) {
stop = false;
this.tracker = tracker;
this.logger = logger;
}
/** Handle Discover request
* @param pd Received request
* @throws InternalError
*/
protected < T extends ProtocolP2PPacket<?> > void handleDiscover(T pd) throws InternalError {
Payload p = pd.getPayload();
assert p instanceof DiscoverRequest : "payload must be an instance of DiscoverRequest";
if (!(p instanceof DiscoverRequest)) {
sendInternalError(pd);
} else {
String filename = ((DiscoverRequest)p).getFilename();
try {
pd.sendResponse(createProtocolP2PPacket(new DiscoverResponse(filename, fileList.getOrDefault(filename, hostList))));
} catch (Exception e) {
writeLog(e, LogLevel.Error);
}
}
}
/** Handle List Responses
* @param pd Received response
* @throws InternalError
*/
protected <T extends ProtocolP2PPacket<?> > void handleListResponse(T pd, HostItem host) throws InternalError {
Payload p = pd.getPayload();
assert p instanceof FileList: "payload must be an instance of FileList";
if (!(p instanceof FileList)) {
throw new InternalError();
} else {
String[] f = ((FileList)p).getFileList();
for (String file: f) {
List<HostItem> h = fileList.get(file);
if (h != null) {
if (!h.contains(host)) {
h.add(host);
}
} else {
List<HostItem> emptyH = new ArrayList<>();
emptyH.add(host);
fileList.put(file, emptyH);
}
}
}
}
/** Handle Unregistering
* @param pd Request received
* @throws InternalError
*/
protected < T extends ProtocolP2PPacket<?> > void handleUnregister(T pd) throws InternalError {
Payload p = pd.getPayload();
assert p instanceof Unregister : "payload must be an instance of Unregister";
if (!(p instanceof Unregister)) {
sendInternalError(pd);
throw new InternalError();
}
HostItem host = ((Unregister)p).getHostItem();
writeLog("Received UNREGISTER from host " + pd.getHostItem() + ". Removing host " + host, LogLevel.Action);
hostList.remove(host);
for(String f: fileList.keySet()) {
fileList.get(f).remove(host);
if(fileList.get(f).isEmpty()) {
fileList.remove(f);
}
}
}
/** Getter for HostItem socket
* @param hostItem HostItem
*/
protected abstract Object getHostItemSocket(HostItem hostItem);
/** Close HostItem socket
* @param hostItem HostItem
*/
protected abstract void closeHostItemSocket(HostItem hostItem);
/** Handle Registering
* @param pd Received request
* @throws InternalError
*/
protected < T extends ProtocolP2PPacket<?> > void handleRegister(T pd) throws InternalError {
Payload p = pd.getPayload();
assert p instanceof Register : "payload must be an instance of Register";
if (!(p instanceof Register)) {
throw new InternalError();
}
// add host to known host list
HostItem host = ((Register)p).getHostItem();
if (!hostList.contains(host)) {
hostList.add(host);
}
// send a list request
try {
ProtocolP2PPacket<?> pLReq = createProtocolP2PPacket(new Payload(RequestResponseCode.LIST_REQUEST));
pLReq.sendRequest(getHostItemSocket(host));
writeLog("Received REGISTER from host " + pd.getHostItem() + ". Adding host " + host + " to list. Sending List request", LogLevel.Action);
handleListResponse(pLReq.receiveResponse(), host);
writeLog("Received LIST RESPONSE from host " + pd.getHostItem(), LogLevel.Action);
closeHostItemSocket(host);
} catch (EmptyDirectory e) {
writeLog("Empty Directory", LogLevel.Debug);
hostList.remove(host);
writeLog("Received EMPTY DIRECTORY from host " + pd.getHostItem() + ". Aborting.", LogLevel.Action);
} catch (Exception e) {
// remove from list because list request could not be send
hostList.remove(host);
writeLog("Aborting the add of host " + host, LogLevel.Action);
writeLog(e, LogLevel.Error);
}
}
/** Handle requests
* @throws LocalException
*/
protected <T extends ProtocolP2PPacket<?> > void handleRequest(T pd) throws LocalException {
Payload p = pd.getPayload();
switch (p.getRequestResponseCode()) {
case LOAD_REQUEST:
writeLog("Received LOAD_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action);
sendNotFound(pd);
break;
case LIST_REQUEST:
writeLog("Received LIST_REQUEST from host " + pd.getHostItem() + ", sending EMPTY_DIRECTORY", LogLevel.Action);
sendEmptyDirectory(pd);
break;
case HASH_REQUEST:
writeLog("Received HASH_REQUEST from host " + pd.getHostItem() + ", sending NOT_FOUND", LogLevel.Action);
sendNotFound(pd);
break;
case REGISTER:
writeLog("Received REGISTER from host " + pd.getHostItem(), LogLevel.Debug);
handleRegister(pd);
break;
case UNREGISTER:
writeLog("Received UNREGISTER from host " + pd.getHostItem(), LogLevel.Debug);
handleUnregister(pd);
break;
case DISCOVER_REQUEST:
writeLog("Received DISCOVER REQUEST from host " + pd.getHostItem(), LogLevel.Action);
handleDiscover(pd);
break;
default:
writeLog("Received grabbage from host " + pd.getHostItem(), LogLevel.Action);
sendInternalError(pd);
break;
}
}
/** Stop the thread */
public void setStop() {
stop = true;
}
}