/src/Client.java
https://bitbucket.org/cairomax/labreti-broker · Java · 239 lines · 103 code · 29 blank · 107 comment · 1 complexity · e5869a3de1c420a5b13902cc2ce637a1 MD5 · raw file
- import java.lang.Thread.UncaughtExceptionHandler;
- import java.net.InetAddress;
- import java.net.UnknownHostException;
- import java.rmi.Naming;
- import java.rmi.RemoteException;
- import java.util.concurrent.atomic.AtomicInteger;
- /**
- * Classe eseguibile che lancia un client che mette a disposizione e richiede
- * risorse a un pool.
- *
- * @see #start()
- */
- public class Client {
- /** Numero totali di risorse presenti su un client */
- private static final int MAX_RESOURCES = 100;
- /** Porta su cui il broker è in ascolto con Java RMI */
- private static final int BROKER_PORT = 1111;
- /** Il broker remoto che gestisce l'allocazione di risorse */
- private final Broker broker;
- /**
- * Numero di risorse attualmente disponibili su questo client.
- * <p>
- * Si usa {@link AtomicInteger} per supportare incrementi e decrementi
- * atomici, senza ricorrere ai lock.
- */
- private final AtomicInteger availableResources = new AtomicInteger();
- /**
- * Identificativo di questo client.
- * <p>
- * Contiene l'indirizzo IP dell'host su cui gira il client.
- */
- private final String user;
- /**
- * Costruttore di default.
- *
- * @param broker
- * il broker che implementa il pool di risorse
- */
- public Client(Broker broker) {
- this.broker = broker;
- try {
- user = InetAddress.getLocalHost().getHostAddress();
- } catch (UnknownHostException e) {
- throw new RuntimeException(e);
- }
- }
- /**
- * Avvia il client.
- * <p>
- * Questo metodo inizializza i thread necessari al funzionamento del client.
- * In particolare:
- * <ul>
- * <li>un thread che ascolta le richieste di riservare risorse (
- * {@link ReserveProcessorThread})
- * <li>un thread che simula la liberazioni di risorse precedentemente
- * allocate ({@link ResourceFreeingSimulatorThread})
- * <li>un thread che simula le richieste di nuove risorse (
- * {@link ResourceTakingSimulatorThread})
- * </ul>
- * <p>
- * Prima di avviare la simulazione, questo metodo notifica il broker che
- * tutte le risorse su questo client sono disponibili, tramite una chiamata
- * a {@link #give(int)}.
- */
- public void start() {
- System.err.println(String.format("Client %s: starting", user));
- Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
- @Override
- public void uncaughtException(Thread t, Throwable e) {
- e.printStackTrace();
- System.exit(0);
- }
- });
- final ReserveProcessorThread reserveProcessorThread = new ReserveProcessorThread(
- this);
- final ResourceFreeingSimulatorThread resourceFreeingSimulator = new ResourceFreeingSimulatorThread(
- this);
- final ResourceTakingSimulatorThread resourceTakingSimulatorThread = new ResourceTakingSimulatorThread(
- this);
- reserveProcessorThread.start();
- give(getTotalResources());
- resourceFreeingSimulator.start();
- resourceTakingSimulatorThread.start();
- }
- /**
- * Riserva un dato numero di risorse, in seguito a una richiesta ricevuta
- * dal server.
- * <p>
- * L'operazione è implementata decrementando atomicamente
- * {@link #availableResources}.
- *
- * @param resourcesToReserve
- * il numero di risorse da riservare
- * @throws InsufficientResourcesException
- * se vengono riservate più risorse di quelle disponibili
- */
- public void reserve(final int resourcesToReserve)
- throws InsufficientResourcesException {
- final int remainingResources = availableResources
- .addAndGet(-resourcesToReserve);
- System.err.println(String.format("Client %s: reserving %d resources",
- user, resourcesToReserve));
- System.out.println(String.format("Client %s: now I have %d resources",
- user, remainingResources));
- if (remainingResources < 0) {
- availableResources.addAndGet(resourcesToReserve);
- throw new InsufficientResourcesException();
- }
- }
- /**
- * Notifica il server della liberazione di un dato numero di risorse.
- * <p>
- * L'operazione è implementata incrementando atomicamente
- * {@link #availableResources} e invocando {@link Broker#give(String, int)}
- * con l'identificativo di questo client come primo argomento.
- *
- * @param resourcesToGive
- * il numero di risorse liberate
- */
- public void give(int resourcesToGive) {
- try {
- System.err.println(String
- .format("Client %s: giving %d resources... ", user,
- resourcesToGive));
- availableResources.addAndGet(resourcesToGive);
- broker.give(user, resourcesToGive);
- System.err.println(String.format(
- "Client %s: giving %d resources... done!", user,
- resourcesToGive));
- System.out.println(String.format(
- "Client %s: now I have %d resources", user,
- availableResources.get()));
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
- /**
- * Richiede al server di allocare un dato numero di risorse.
- * <p>
- * L'operazione viene effettuata decrementando atomicamente
- * {@link #availableResources} e invocando {@link Broker#take(String, int)}
- * con l'identificativo di questo client come primo argomento.
- *
- * @param resources
- * il numero di risorse da allocare
- */
- public void take(int resources) {
- System.err.println(String.format("Client %s: taking %d resources... ",
- user, resources));
- try {
- final boolean wereTaken = broker.take(user, resources);
- System.err.println(String.format(
- "Client %s: taking %d resources... %s", user, resources,
- wereTaken ? "taken!" : "NOT available!"));
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
- /**
- * Restituisce il numero totale di risorse (disponibili o allocate) su
- * questo client.
- * <p>
- * Restituisce sempre il valore di {@link #MAX_RESOURCES}.
- *
- * @return il numero totale di risorse su questo client.
- */
- public int getTotalResources() {
- return MAX_RESOURCES;
- }
- /**
- * Restituisce il numero di risorse disponibili (non allocate) su questo
- * client.
- * <p>
- * Restituisce il valore attuale di {@link #availableResources}.
- *
- * @return il numero di risorse disponibili su questo client.
- */
- public int getAvailableResources() {
- return availableResources.get();
- }
- /**
- * Metodo principale del client.
- * <p>
- * Esegue le seguenti operationi:
- * <ol>
- * <li>ottiene un'implementazione remota di {@link Broker}, tramite una
- * chiamata a {@link Naming#lookup(String)}
- * <li>costruisce un'istanza di {@link Client}, passando al costruttore il
- * broker appena inizializzato
- * <li>invoca {@link Client#start()}
- * </ol>
- *
- * @param args
- * argomenti da linea di comando, ignorati
- */
- public static void main(String[] args) {
- String server = args[0];
- final String url = "rmi://" + server + ":" + BROKER_PORT
- + "/ResourceBroker";
- System.err.println("Client: looking up broker at URL: " + url);
- Broker broker;
- try {
- broker = (Broker) Naming.lookup(url);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- Client client = new Client(broker);
- client.start();
- }
- }