pcd-assignment-03

PCD Assignment 03

Componenti:

Part 1 - Actors

L’implementazione della soluzione è stata realizzata mediante il linguaggio Scala, in particolare utilizzando la libreria Akka, con attori tipizzati e behaviors.

CLI

La soluzione proposta per la versione CLI è ispirata alla strategia divide et impera, esplorando la directory in modo ricorsivo. Vengono utilizzati i seguenti attori:

CLI schema

GUI

La soluzione proposta per la versione GUI estende quella precedentemente descritta nell’approccio CLI. Dal momento che si vogliono osservare le statistiche in tempo reale e una leaderboard dei file più grandi, sono state aggiunte altre tipologie di attori. Inoltre, gli attori già descritti, cambiano la modalità di aggregazione dei risultati, non utilizzato più una strategia divide et impera.

Vengono utilizzati i seguenti attori:

Manager_GUI schema

SourceAnalyzer_GUI schema

Leaderboard_GUI schema

Schema d’interazione (versione con GUI):

GUI schema

Part 2 - Distributed Programming with Asynchronous Message Passing

La soluzione proposta si basa sull’utilizzo di un Message Oriented Middleware, in particolare è stato utilizzato RabbitMQ.

Vi sono diversi eventi che richiedono uno scambio di messagi tra peers. Per ciascuno di essi ogni client possiede una coda di ricezione. Tali code sono collegate ad un exchange (specifico di un particolare tipo di evento). Sono stati utilizzati exchange di tipo fanout, in modo che, ogni qualvolta un client invia un messaggio relativo ad un evento su quell’exchange, tutti gli altri utenti collegati ad esso possono riceverne una copia. Inoltre, anche il client stesso riceve il proprio evento: questo garatisce uno stato consistente tra i vari client.

exchanges

Gli exchange, con i rispettivi tipi di messaggi, sono:

Join di un utente

L’implentazione di questa funzionalità si basa sul pattern RPC. In particolare, un utente intenzionato a unirsi alla sessione, invia un messaggio di richiesta di join su una coda dedicata, sulla quale, tutti gli utenti che già partecipano alla sessione, sono in ascolto. Dato che, in generale, la ricezione di un messaggio da parte di un client su una coda, fa sì che il messaggio venga consumato, la richiesta di join verrà presa in carico da un solo utente (in particolare RabbitMQ, adotta una politica Round-robin, si veda qui). Dunque, l’utente che riceve la richiesta di join, non farà altro che inviare lo stato della propria griglia insieme alla lista degli utenti che partecipano alla sessione.

StateRequest { }

StateReply {
    grid: PixelGrid,
    users: Map<UUID, Int>
}

join and state request

Dato che la richiesta dello stato non comporta lo stop dei processi, è importante per il client che è intenzionato a partecipare alla sessione, collegarsi preventivamente con le proprie code agli exchange degli eventi (in particolare pixel_color e color_change) in modo tale che, quando riceve lo stato della griglia, possa applicare gli eventi ricevuti e bufferizzati, evitanto di trovarsi in uno stato inconsistente.

Riguardo la concorrenza

In RabbitMQ, le callback di ricezione di un messaggio vengono eseguite da un pool di thread. Per questo motivo si è reso necessario l’utilizzo di strutture dati concorrenti (ovvero una TrieMap e una BlockingQueue). Inoltre, la classe PixelGrid è stata resa un monitor. Tutto ciò permette di evitare corse critiche.

Part 3 - Distributed Programming with Distributed Objects

La soluzione proposta è stata implementata utilizzando Java Remote Method Invocation (RMI), mediante il linguaggio Scala.

Architettura del sistema

L’architettura prevede l’interazione tra ogni client e il ModelService, ma anche un collegamento peer-to-peer tra i partecipanti. Il ModelService è l’entità che si occupa di mantenere lo stato consistente della griglia, durante una sessione di disegno.

System architecture

pixel coloring

brush color change

mouse move

Join di un utente

Un client, per poter partecipare alla sessione, deve conoscere un rifertimento ad un altro utente già connesso al sistema. In questo modo, può richiedere a quest’ultuimo l’istanza del ModelService della sessione, che consentirà di ottenere lo stato della griglia e la lista degli utenti connessi. Inoltre, il ModelService notificherà a tutti gli altri client la presenza del nuovo utente.

diagramma di sequenze di join