Projet_JAVA_P2P_STRI2A/src/serverP2P/RatioWatcher.java
2020-04-02 02:30:39 +02:00

179 lines
4.8 KiB
Java

package serverP2P;
import tools.Logger;
import tools.LogLevel;
import tools.HostItem;
import java.util.Map;
import java.util.HashMap;
import java.io.IOException;
import exception.RemoteException;
import exception.LocalException;
import protocolP2P.RatioRequest;
import protocolP2P.RatioResponse;
import protocolP2P.Payload;
import protocolP2P.ProtocolP2PPacket;
import remoteException.UnknownHost;
import remoteException.NotATracker;
import localException.InternalError;
/** Class allowing to keep the tracker informed about ratios
* @author Louis Royer
* @author Flavien Haas
* @author JS Auge
* @version 1.0
*/
public abstract class RatioWatcher implements Runnable {
final static double punishmentFactor = 1.2;
protected Logger logger;
protected volatile boolean stop;
protected long time;
protected boolean force;
protected HostItem tracker;
protected Thread thread;
protected Map<HostItem, Double> cachePunishmentProbability = new HashMap<>();
protected boolean lock;
/** Constructor
* @param logger Logger
* @param millis Time interval before recheck
* @param tracker HostItem for the tracker
*/
public RatioWatcher(Logger logger, long millis, HostItem tracker) {
assert logger != null : "Logger is null";
assert tracker != null : "Tracker is null";
this.logger = logger;
time = millis;
this.tracker = tracker;
lock = false;
}
/** Runnable implementation */
public void run() {
writeLog("Ratio watcher started : delay " + time + " milliseconds.", LogLevel.Info);
while(!stop) {
try {
clean();
Thread.sleep(time);
} catch(InterruptedException e) {
writeLog("Ratio watcher interrupted", LogLevel.Info);
setStop();
}
}
writeLog("Ratio watcher end of loop", LogLevel.Debug);
}
/** Invalidate the cache by cleaning all hashmaps
* @throws InterruptedException
*/
protected synchronized void clean() throws InterruptedException{
while(lock) {
this.wait();
}
lock = true;
cachePunishmentProbability.clear();
lock = false;
this.notifyAll();
}
/** Get Up-ratio for an applications
* @param application HostItem of the application
* @return Punishment Probability
* @throws UnknownHost
*/
protected synchronized double getPunishmentProbability(HostItem application) throws InternalError, UnknownHost {
try {
while(lock) {
this.wait();
}
lock = true;
if (!cachePunishmentProbability.containsKey(application)) {
// update if not in cache
try {
ProtocolP2PPacket<?> p = createProtocolP2PPacket(new RatioRequest(application));
p.sendRequest(getTrackerSocket());
Payload resp = p.receiveResponse().getPayload();
if (!(resp instanceof RatioResponse)) {
throw new InternalError();
}
RatioResponse rresp = (RatioResponse)resp;
if (!rresp.getHostItem().equals(application)) {
writeLog("Ratio response host is not the expected one. Expected : "
+ application + ". Received : " + rresp.getHostItem(), LogLevel.Debug);
throw new InternalError();
}
long up = rresp.getTotalUp();
long down = rresp.getTotalDown();
assert punishmentFactor > 1 : "The punishment factor must be greater than 1";
if (down == 0 || (punishmentFactor * up) >= down) {
cachePunishmentProbability.put(application, Double.valueOf(0));
} else {
cachePunishmentProbability.put(application, Double.valueOf((down - up)/(down * punishmentFactor)));
}
} catch (UnknownHost e) {
throw e;
} catch (IOException e) {
throw new InternalError();
} catch (LocalException e) {
writeLog(e, LogLevel.Error);
throw new InternalError();
} catch (RemoteException e) {
writeLog(e, LogLevel.Error);
throw new InternalError();
}
}
double ret = cachePunishmentProbability.get(application);
lock = false;
this.notifyAll();
return ret;
} catch (InterruptedException e) {
throw new InternalError();
}
}
/** Ask the thread to stop
*/
public void setStop() {
stop = true;
if (thread != null) {
thread.interrupt();
}
}
/** Implementation of writeLog
* @param text Text to log
* @param logLevel level of logging
*/
protected abstract void writeLog(String text, LogLevel logLevel);
/** Implementation of writeLog
* @param e exception to log
* @param logLevel level of logging
*/
protected abstract void writeLog(Exception e, LogLevel logLevel);
/** Set thread
* @param thread Thread
*/
public void setThread(Thread thread) {
this.thread = thread;
}
/** Create packets
* @param payload Payload
*/
protected abstract < T extends Payload > ProtocolP2PPacket<?> createProtocolP2PPacket(T payload);
/** Tracker socket getter
* @return tracker socket
*/
protected abstract Object getTrackerSocket();
/** Closes tracker socket
*/
protected abstract void closeTrackerSocket();
}