package se.chalmers.gdcn.control;
import se.chalmers.gdcn.demo.WorkerNames;
import se.chalmers.gdcn.network.WorkerID;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Leif on 2014-03-31.
*
* Class to keep track of what peers are registered as workers.
*
*/
public class WorkerReputationManager implements Serializable{
public static enum DisciplinaryAction{
REMOVE,
DEMOTE
}
private final DisciplinaryAction standardAction;
private final int removeSoManyPoints;
private final WorkerID myWorkerID;
private final Map<WorkerID, Integer> registeredWorkers = new HashMap<>();
/**
* Create new WorkerReputationManager with default action REMOVE.
*/
public WorkerReputationManager(WorkerID myWorkerID){
this(myWorkerID, 3, DisciplinaryAction.REMOVE);
}
/**
* @param myWorkerID This node's workerID, used for reputation
* @param removeSoManyPoints So many points are withdrawn from a workers reputation when it misbehaves.
* @param standardAction Default action to do when reporting
*/
public WorkerReputationManager(WorkerID myWorkerID, int removeSoManyPoints, DisciplinaryAction standardAction) {
this.standardAction = standardAction;
this.removeSoManyPoints = removeSoManyPoints;
//The job owner trusts himself
this.registeredWorkers.put(myWorkerID, 100);
this.myWorkerID = myWorkerID;
}
/**
* Registers worker as a worker node to remember
* @param worker Worker node
* @return true if worker was added, false if existed already
*/
public synchronized boolean registerWorker(WorkerID worker){
if(registeredWorkers.keySet().contains(worker)){
return false;
}
registeredWorkers.put(worker, 0);
WorkerNames.getInstance().registerName(worker);
return true;
}
public WorkerID getMyWorkerID() {
return myWorkerID;
}
/**
*
* @param worker Worker node
* @return true if and only if worker is registered and has reputation.
*/
public synchronized boolean hasWorkerReputation(WorkerID worker){
if(!registeredWorkers.keySet().contains(worker)){
return false;
}
Integer rep = registeredWorkers.get(worker);
return rep != null && rep > 0;
}
/**
* Worker misbehaved. Perhaps it is a Sybil node? Apply standard action.
* @param worker Worker node
*/
public void reportWorker(WorkerID worker){
reportWorker(worker, standardAction);
}
/**
* Worker misbehaved. Perhaps it is a Sybil node?
* @param worker Worker node
* @param action Action to take on misbehavior
*/
public synchronized void reportWorker(WorkerID worker, DisciplinaryAction action){
if(!registeredWorkers.containsKey(worker)){
//This can happen when a Worker is reported for not computing the registration task properly.
return;
// throw new IllegalArgumentException("Worker doesn't exist");
}
switch (action){
case REMOVE:
registeredWorkers.remove(worker);
break;
case DEMOTE:
if(removeSoManyPoints <= 0){
throw new IllegalArgumentException("If use REMOVE, one must subtract points, not give points, on failure.");
}
Integer reputation = registeredWorkers.get(worker);
registeredWorkers.put(worker, reputation-removeSoManyPoints);
break;
}
}
/**
* Worker finished some task nicely. Promote the worker.
* @param worker Worker node
*/
public synchronized void promoteWorker(WorkerID worker){
if(!registeredWorkers.containsKey(worker)){
throw new IllegalArgumentException("Worker doesn't exist");
}
Integer reputation = registeredWorkers.get(worker);
registeredWorkers.put(worker, reputation+1);
}
/**
*
* @param worker Worker node
* @return Current reputation or zero if not registered
*/
public synchronized int getReputation(WorkerID worker){
if(!registeredWorkers.containsKey(worker)){
return 0;
// throw new IllegalArgumentException("Worker doesn't exist");
}
return registeredWorkers.get(worker);
}
}