\documentstyle{article}

% questi parametri sono presi da 'iet.sty'

\oddsidemargin  0mm
\evensidemargin 0mm
% \textwidth    210mm minus 2in minus \oddsidemargin minus \oddsidemargin
\textwidth      159.2mm
\topmargin      -12.7mm
\headheight     8.4mm
\headsep        12.7mm
\textheight     224.9mm
\footskip       12.7mm
\footheight     8.4mm

\def\barra{\noindent\rule{\columnwidth}{0.5pt}}

\title{Struttura del nuovo pcserver}

\author{
	(Preliminary Version - May 6, 1991)\\
	\\
	Luigi Rizzo\thanks{
		Author current address:
		Brown Univ., Comp. Science Dept.,
		Box 1910,
		Providence RI~02912-1910
		Tel.~(401)~863-7600
		Email:~lr@cs.brown.edu}
}

\date{\today}

\begin{document}
\maketitle
% \begin{abstract}
% \end{abstract}

\section{Generalit\`a}

{\tt pcserver} permette di accedere, via Ethernet, a diversi Transputer
indipendenti installati su uno stesso macchina MSDOS. Il programma non
\`e legato ad alcun particolare protocollo.  {\tt pcserver} \`e in
grado di interpetare i protocolli {\tt iserver} e {\tt afserver} (ed
\`e facilmente espandibile per supportare nuovi protocolli), ma \`e
ugualmente in grado di funzionare in presenza di protocolli
sconosciuti, anche se con una efficienza leggermente ridotta.

{\tt pcserver} sfrutta, per le funzioni di rete, le librerie di {\em
NCSA~Telnet}. Tutto il restante codice \`e stato completamente
riscritto e non comprende codice Inmos.

\subsection{Definizioni}

Nel seguito useremo le seguenti definizioni:

\begin{itemize}

\item{\em link} indica l'hardware (link adapter) utilizzato
	per comunicare col Transputer;

\item{\em PC} indica la macchina MSDOS su cui sono fisicamente
	installati i {\em link} collegati ai diversi Transputer;

\item{\tt pcserver} indica il programma {\tt pcserver}, che gira
	sul {\em PC}.

\item{\em server} indica il programma (tipicamente {\tt afserver}
	o {\tt iserver}) che accetta ed esegue le richieste
	provenienti dal sistema a Transputer.

\item{\em host} indica la macchina (tipicamente Unix) su cui gira
	il {\em server}

\item{\em sessione} indica le attivit\`a svolte dal {\tt
	pcserver} per trasferire dati tra un {\em host} e un sistema a 
	Transputer.

\item{\em porta} indica una porta Internet sulla quale \`e
	possibile aprire un circuito virtuale.

\item{\em rete} indica il circuito virtuale su cui avviene la
	comunicazione tra {\em server} e {\tt pcserver}

\end{itemize}

\section{Struttura del programma}

Le varie sessioni host-Transputer vengono gestite in parallelo.  Non
essendo MSDOS multiprogrammato, per ciascuna sessione sono definite
delle variabili che ne indicano lo stato.  Ciclicamente, viene invocata
una procedura che modifica lo stato di ciascuna sessione, in base allo
stato attuale e all'attivit\`a sul circuito virtuale e sul link da essa
utilizzato. La procedura di gestione della sessione \`e non bloccante
in modo da evitare interazioni tra l'attivit\`a delle varie sessioni.
La struttura generale del programma \`e quindi la seguente:

\begin{verbatim}
begin
  <inizializzazione>
  for i:= 1 to numero_sessioni do
     gestisci_sessione(i)
end.
\end{verbatim}

Ciascuna sessione utilizza un link adapter e un circuito virtuale
connesso ad una diversa porta Internet. In questo modo \`e possibile,
per l'host, scegliere un particolare Transputer tra quelli installati
sullo stesso PC.

\subsection{Inizializzazione}

La fase di inizializzazione svolge le seguenti attivit\`a:

\begin{itemize}

\item	analizza la linea di comando per determinare quanto link sono
	attivi e i relativi indirizzi di I/O e numeri di porta;

\item	attiva il software di rete;

\item	inizializza le variabili di stato relative a ciascuna
	sessione, e si mette in ascolto sulle varie porte;

\end{itemize}

Per default {\tt pcserver} assume di operare con un solo link adapter
all'indizzo 0x150. Tramite parametri sulla linea di comando \`e
possibile specificare quanti link adapter sono presenti sul PC e i
relativi indirizzi.

Sulla rete viene usato un numero di porte pari a quello dei link
esistenti, numerate in sequenza a partire dal valore {\tt SERVER\_PORT}
(che attualmente vale 2199). E` ancora da implementare l'opzione per
modificare questo parametro dalla linea di comando.

\section{Gestione delle sessioni}

E` possibilie distinguere tre principali ``superstati'' ({\em modi}) in
cui si pu\`o trovare una sessione:

\begin{itemize}

\item{\em idle} Nessuna richiesta di connessione \`e stata
	effettuata sul socket. Quando arriva una richiesta di
	connessione si passa in modo {\em command}.

\item{\em command} La connessione \`e stata
	aperta, e il {\em server} e il {\tt pcserver} comunicano
	tra loro per negoziare il protocollo da usare ed
	eseguire comandi (es. reset, analyze, peek, poke, boot)
	sul link. Un particolare comando permette di passare in
	modo {\em server}.

\item{\em server} Il {\tt pcserver} \`e
	completamente trasparente e trasferisce i dati fra host e
	Transputer nelle due direzioni. Da questo stato si esce
	solo in caso di errori o di chiusura della connessione da
	parte del server.

\end{itemize}

Per poter avere la massima flessibilit\`a nella scelta del protocollo,
per ciascuna sessione sono utilizzati due buffer, uno per ciascuna
direzione (verso il link e verso la rete). A ciascun buffer sono
associati dei puntatori utilizzati per leggere e scrivere i dati. I
nomi delle variabili usate per gestire il traffico verso il link
iniziano con ``{\tt lio}'' (es. {\tt liobuf, liorptr, liowptr}), mentre
nell'altra direzione (rete) iniziano con ``{\tt nio}'' (es. {\tt
niobuf, niorptr, niowptr}). Lo stato dei due buffer \`e contenuto
rispettivamente in {\tt lbufstat} e {\tt nbufstat}.  Lo stato di una
sessione \`e individuato da queste due variabili.

Lo scopo dei buffer \`e di evitare di trasferire i dati un byte alla
volta. Al contrario, nei buffer vengono accumulati dati che
costituiscono un singolo messaggio, che pu\`o cos\`\i\ essere
trasferito con una singola operazione di I/O in modo efficiente.
L'impacchettamento dei dati, pur se necessario per questioni di
efficienza, non \`e per\`o indispensabile per il funzionamento del {\tt
pcserver}. E` invece indispensabile che il flusso dei dati nelle due
direzioni sia indipendente in modo che non si possano verificare
deadlock. Questo obbliga a utilizzare due buffer invece di uno solo,
anche se la comunicazione tra Transputer e {\em server} solitamente usa
un protocollo cliente-servitore e quindi non utilizza comunicazione
bidirezionale.

\section{Formato dei dati}


La comunicazione tra Transputer e {\em server} \`e fondamentalmente di
tipo datagram. Tuttavia, per questioni di affidabilit\`a, {\em server}
e {\tt pcserver} comunicano usando un circuito virtuale.

\subsection{Formato dei dati in rete}

Per poter identificare esattamente i vari messaggi, questi sono
trasmessi in rete col seguente formato (che \`e anche il formato dei
buffer utilizzati per i trasferimenti dati):

\begin{verbatim}
struct message {
  short len; /* read/written with ntohs() and htons() */
  unsigned char data[IOBUFSIZ];
}
\end{verbatim}

Il campo dati ha lunghezza variabile, che al massimo pu\`o valere {\tt
IOBUFSIZ}. Il campo {\tt len} indica la lunghezza totale del messaggio,
comprende il campo {\tt len}.  Per esempio, trasmettendo 10 bytes di
dati {\tt len} vale 12.  Si noti che questo campo \`e in formato di
rete, quindi va letto/scritto usando le apposite funzioni ({\tt
ntohs()} e {\tt htons()}).  Questa convenzione deve essere rispettata
sia dal {\em server} che dal {\tt pcserver} per qualunque comunicazione
effettuata sulla rete.  Ci\`o consente a chi riceve di determinare
esattamente quando un messaggio \`e completo senza dover interpretare i
dati in esso contenuti, ed evita problemi in caso di frammentazione dei
messaggi causata dal trasferimento attraverso la rete.

\subsection{I/O sulla rete}

Le operazioni di I/O sulla rete sono semplicemente effettuate invocando
le funzioni {\tt netread()} e {\tt netwrite()} fornite da NCSA~Telnet
(dopo aver verificato la possibilit\`a di utilizzare le stesse). La
quantit\`a di dati richiesti in lettura \`e costituita dallo spazio
ancora disponibile nel buffer, mentre in scrittura si inviano al pi\`u
tanti bytes quanti sono quelli non ancora trasmessi. Il fatto di
precedere ogni messaggio dalla sua lunghezza fa s\`\i\ che non ci siano
problemi anche nel caso che vengano trasmessi/ricevuti meno bytes di
quelli richiesti.

Le procedure di I/O in rete sono chiamate all'interno di {\tt
read\_from\_net()} e {\tt write\_to\_net()}, che ritornano {\tt TRUE}
solo se almeno un byte \`e stato letto/scritto.

\subsection{Formato dei dati sul link}

Il formato dei dati sul link dipende dal protocollo utilizzato.  Tutti
i dati trasferiti dal/al link sono caricati nel campo {\tt data} dei
buffer. In questo modo \`e semplice effettuare trasferimenti di blocchi
contigui di memoria con o senza il campo {\tt len} senza dover
effettuare copie dei messaggi.

\subsection{I/O sul link}

Le operazioni di I/O sul link sono fatte tramite due procedure, {\tt
read\_from\_link()} e {\tt write\_to\_link()}.  Contrariamente alla
implementazione nel programma originale Inmos, queste due procedure non
sono bloccanti. La procedura di lettura carica i dati dal link in {\tt
niobuf}, utilizzando {\tt niowptr} come puntatore nel buffer. La
lettura avviene fino a che sono disponibili dati e al pi\`u pu\`o
saturare il buffer. La procedura di scrittura copia i dati da {\tt
liobuf} al link, utilizzando {\tt liorptr} come puntatore. I dati sono
trasferiti fino a quando non si trova il link occupato, oppure fino a
svuotare completamente {\tt liobuf} ({\tt liowptr} indica la prima
locazione vuota dopo i dati).

Si noti che queste due primitive sono particolarmente efficienti:
infatti, il Transputer trasferisce blocchi di dati molto pi\`u
velocemente di quanto non riesca a fare il PC, per cui nel caso di
trasferimenti di blocchi di dati (es. word o slices) le procedure
trasfericono un blocco completo prima di ritornare al chiamante.
D'altra parte, il fatto che i buffer hanno dimensione limitata assicura
che le procedure stesse non restino in esecuzione per un tempo troppo
lungo. E` auspicabile realizzare queste procedure in assembler per
aumentarne ulteriormente l'efficienza.

\section{Gestione dei buffer}

Ciascun buffer pu\`o assumere diversi stati. Le transizioni da uno
stato all'altro sono causate da I/O sulla rete o sul link, esecuzione
di comandi, timeout o condizioni di errore. Anche se i due buffer sono
gestiti indipendentemente, il verificarsi di certe condizioni su un
buffer pu\`o causare cambiamenti di stato dell'altro. Ci\`o accade per
esempio nell'esecuzione di comandi richiesti dal {\em server} (che
possono richiedere una risposta dal {\tt pcserver} o dal Transputer) o
di condizioni di errore.

Nel seguito indichiamo i vari stati e le principali transizioni di
stato.

\subsection{Stati di liobuf}

{\tt liobuf} pu\`o essere nei seguenti stati:

\begin{itemize}

\item{\tt B\_IDLE} Attesa di una connessione dall'host. Quando
	questa arriva si passa in {\tt B\_INIT\_WAIT}.

\item{\tt B\_INIT\_WAIT} Modo comando, buffer
	vuoto. Alla ricezione del primo byte si passa in
	{\tt B\_INIT\_ON}.

\item{\tt B\_INIT\_ON} Si accumula un messaggio, che costituisce un
	comando da eseguire. Se questo \`e completo si chiama la
	routine {\tt interpret\_init()}, che esegue una prima fase
	del comando, e si passa in {\tt B\_INIT\_DONE}.

\item{\tt B\_INIT\_DONE} Invio di un messaggio verso il link, se
	necessario (es. nel caso di boot). Quando il messagio \`e
	terminato si chiama la routine {\tt postinterpret\_init()},
	che esegue eventuali funzioni addizionali per il comando,
	e provvede a cambiare stato (tipicamente torna a {\tt
	B\_INIT\_WAIT}).

\item{\tt B\_EMPTY} Modo server, buffer vuoto.
	Alla ricezione del primo byte dalla rete
	si passa allo stato {\tt B\_RX\_ON}.

\item{\tt B\_RX\_ON} Il messaggio viene accumulato. Quando \`e
	completo si passa nello stato {\tt B\_TX\_ON}.

\item {\tt B\_TX\_ON} In questo stato il solo campo {\tt data} viene
	trasmesso, senza alcuna modifica, al link. Al termine
	della trasmissione si torna allo stato {\tt B\_EMPTY} per
	ricevere il messaggio successivo.

\end{itemize}

Si possono individuare tre gruppi di stati: il primo indica il modo
idle, i successivi tre vengono utilizzati in modo comando, gli altri
tre in modo server.

\subsection{Stati di niobuf}

{\tt niobuf} pu\`o essere nei seguenti stati:

\begin{itemize}

\item{\tt B\_IDLE} La ricezione dal link \`e disabilitata.

\item{\tt B\_SEND\_ACK} Questo stato viene usato per trasferire
	verso la rete un singolo messaggio (solitamente la
	risposta ad un comando), dopo il quale si torna nello
	stato {\tt B\_IDLE}.

\item{\tt B\_EMPTY} Ricezione dal link abilitata, buffer vuoto.
	Alla ricezione del primo byte si passa in {\tt B\_RX\_ON}.

\item{\tt B\_RX\_ON} Il messaggio dal link viene accumulato. Man
	mano che vengono ricevuti dei caratteri si invoca la procedura
	{\tt (*protocol\_complete)()} che \`e diversa a seconda
	del protocollo utilizzato. La procedura ritorna {\tt TRUE} solo se
	il messaggio \`e completo. In questo caso il campo
	{\tt len} viene inizializzato e si passa in {\tt B\_TX\_ON}.

\item {\tt B\_TX\_ON} Il messaggio, preceduto dalla lunghezza, viene
	trasmesso verso la rete. Al termine
	della trasmissione si torna allo stato {\tt B\_EMPTY} per
	ricevere il pacchetto successivo.
\end{itemize}

In questo caso si possono individuare due gruppi di stati, i primi due
relativi al modo idle o comando, gli ultimi tre utilizzati in modo
server.  In modo idle entrambi i buffer sono in stato {\tt B\_IDLE}, e
l'attivit\`a sul link \`e disabilitata.

\section{Comandi}

{\tt pcserver} accetta vari comandi per svolgere funzioni di controllo
sul link e per definire le sue modalit\`a operative. I comandi sono
contenuti nel campo {\tt data} dei messaggi provenienti dalla rete, e
sono costituiti da un byte che indica il comando seguito eventualmente
da parametri addizionali. Ciascun comando comporta una replica inviata
al server. Nel caso pi\`u semplice la replica \`e costituita da un solo
byte, che assume il valore {\tt C\_ACK} (successo) o {\tt C\_NACK}
(errore).  Alcuni comandi possono comportare repliche pi\`u complesse.

\subsection{Comandi disponibili}

\begin{itemize}

\item{\tt C\_RESET} Resetta il link. La risposta \`e sempre
	{\tt C\_ACK} perch\`e non \`e possibile fallire.

\item{\tt C\_ANALYZE} Esegue analyse sul link. La risposta \`e sempre
	{\tt C\_ACK} perch\`e non \`e possibile fallire.

\item{\tt C\_BOOT} E` seguito da un blocco di dati che vengono
	inviati al link. La risposta \`e {\tt C\_ACK}. Non \`e
	ancora implementato il codice per rispondere {\tt C\_NACK}
	in caso di timeout in scrittura.

\item{\tt C\_PROTO} E` seguito da un byte che specifica il tipo
	di protocollo da utilizzare per la comunuicazione. Dopo
	questo comando {\tt pcserver} passa in modo server. La
	risposta \`e {\tt C\_ACK} seguita da un byte che indica il
	protocollo che {\tt pcserver} vuole utilizzare. Se il
	protocollo richiesto dal server \`e noto, questo viene
	accettato, altrimenti si usa il protocollo {\em raw},
	discusso nella sezione~\ref{rawproto}.

\item{\tt C\_POKE} (non ancora implementato)
	Dopo reset o analyse, scrive nella memoria del
	Transputer. Il formato \`e:

\begin{verbatim}
struct c_poke_cmd {
  char cmd;       /* contiene C_POKE               */
  char c;         /* empty                         */
  long add;       /* empty                         */
  long data;      /* empty                         */
  long first;     /* address of first word to poke */
  long len;       /* number of words to poke       */
  long image[];   /* data to poke                  */
}
\end{verbatim}

	Il server prepara il messaggio di POKE come segue: in
	{\tt cmd} scrive {\tt C_POKE}, in {\tt first} l'indirizzo
	della prima cella di memoria in cui scrivere su
	Transputer, in {\tt len} il numero di {\em words} da
	scrivere (ogni word \`e di 4 bytes), in {\tt image}
	scrive i dati da scrivere in memoria, ovvero il contenuto
	di tutte le word scritte a partire dal byte meno
	significativo.

	I campi {\tt c, add, data} sono utilizzati da pcserver,
	per contenere
	ogni volta i dati da scrivere sul link. In pratica, la
	procedura {\tt postinterpret\_init()} riempie questi
	campi per la prossima operazione di poke, modifica i
	puntatori {\tt liorptr, liowptr} e pone {\tt
	lbufstat=B\_INIT\_DONE} in modo da continuare a scrivere
	sul link.
	La risposta \`e la seguente:

\begin{verbatim}
struct c_poke_ans {
  char cmd;       /* contiene C_ACK o C_NACK       */
  long len;       /* numero di word scritte        */
}
\end{verbatim}

\item{\tt C\_PEEK} (non ancora implementato) Legge dalla memoria
	del Transputer. Il formato \`e:

\begin{verbatim}
struct c_peek_cmd {
  char cmd;       /* contiene C_PEEK               */
  char c;         /* empty                         */
  long add;       /* empty                         */
  long first;     /* address of first word to peek */
  long len;       /* number of words to peek       */
}
\end{verbatim}
	Similmente al comando di poke, i campi {\tt c, add}
	vengono preparati dalla procedura {\tt
	postinterpret\_init()} che svolge approssimativamente le
	stesse funzioni del caso del comando poke. In pi\`u,
	viene selezionato un particolare protocollo in ricezione
	in modo da accettare tutti i dati che il Transputer
	transmette sul link.
	La risposta \`e la seguente:

\begin{verbatim}
struct c_poke_ans {
  char cmd;       /* contiene C_ACK o C_NACK       */
  long len;       /* numero di word lette          */
  long image[];   /* dati letti                    */
}
\end{verbatim}

\end{itemize}

\subsection{Esecuzione dei comandi}

L'esecuzione dei comandi \`e effettuata invocando due procedure.
La prima ({\tt interpret\_init()}) viene chiamata non appena
terminata la ricezione del comando, e serve a preparare eventuali
messaggi che vanno mandati al link (es. nel caso di boot e peek).
La seconda procedura ({\tt postinterpret\_init()}) viene comunque
eseguita dopo che il comando \`e stato inviato al link.
Tipicamente a questo punto si prepara il messaggio di ack da
inviare al {\em server} e si modifica in modo opportuno lo stato di 
{\tt niobuf}. Tuttavia, certi comandi (es. peek e poke) possono
anche richiedere azioni pi\`u complesse che comportano un
cambiamento di stato anche di {\tt liobuf}, e la scelta di uno
speciale protocollo di I/O sul link.

\section{Interpretazione del protocollo}

La procedura di interpretazione del protocollo varia a seconda del
protocollo stesso. La particolare procedura \`e scelta mediante il
comando {\tt C\_PROTO}. Ciascun protocollo \`e implementato, in
{\tt pcserver}, mediante ua coppia di procedure. La prima serve a
inizializzare il protocollo ed \`e invocata durante l'esecuzione di
{\tt C\_PROTO}. La seconda costituisce invece la procedura di verifica
del completamento di un messaggio, ed \`e invocata ogni volta che sono
letti nuovi dati dal link.

\subsection{iserver}

Il protocollo {\tt iserver} \`e estremamente semplice: ciascun
messaggio \`e preceduto da un numero (2 bytes) che indica la lunghezza
del campo dati, ovvero il numero di byte {\em che seguono}. La
lunghezza \`e trasmessa inviando per primo il byte meno significativo.

La verifica del completamento di un messaggio \`e quindi estremamente
semplice: una volta letta la lunghezza \`e sufficiente attendere fino a
che tutti i bytes necessari non sono stati ricevuti.

\subsection{afserver}

Il protocollo {\tt afserver} \`e decisamente pi\`u complesso. In questo
protocollo ogni messaggio \`e composto da un tag che indica il tipo di
messaggio, seguito da una serie di campi che rappresentano un {\tt
integer}, un {\tt long}, o un {\tt record}. Il numero e tipo di campi
da cui \`e costituito un messaggio sono definiti univocamente dal tag.
I vari campi possono tuttavia avere lunghezza variabile (questo accade
ad esempio nel caso dei {\tt record}). In generale, essi sono composti
da un tag che ne indica il tipo, e da un campo dati, la cui
lunghezza \`e:

\begin{itemize}

\item{\tt integer} e {\tt long}: 4 bytes
\item{\tt record}: 4 bytes (lunghezza) + n bytes (dati). La
	lunghezza del campo dati \`e rappresentata dai primi 4
	bytes. Un caso speciale \`e rappresentato dai record di
	lunghezza zero, che sono identificati da un tag speciale
	che non \`e seguito da un campo dati.

\end{itemize}

Per l'interpretazione del protocollo {\tt afserver}, si usa la
seguente strategia. Una volta letto il tag del messaggio, si
carica da una tabella la struttura del messaggio e man mano si
ricevono (ovvero si incrementa un puntatore al buffer)
i campi previsti. Una volta ricevuti tutti i campi il
messaggio si pu\`o considerare finito.

Si noti che la lunghezza di un tag \`e di 1 byte.

\subsubsection{Modifiche per Transputer Rev.A}

La vecchia serie di Transputer (tipicamente il T414A) ha un baco
nel trasferimenti di singoli bytes sui link. Questo affligge sia
il trasferimento dei tag che quello di record di un solo
carattere. Pertanto esiste una versione modificata del protocollo
afserver (tipicamente realizzata, sul Transputer, dal processo
``filter'') nel quale i tag sono trasferiti come una word (4~bytes
invece di 1) e i record di 1~byte sono trasferiti come 2~bytes
(il campo lunghezza indica comunque sempre il valore 1). In {\tt
pcserver} le stesse routines sono utilizzate per implementare
entrambe le varianti del protocollo afserver.



\subsection{raw protocol}
\label{rawproto}

Il protocollo ``raw'' viene utilizzato quando il {\tt pcserver}
non conosce il protocollo utilizzato sul link. In questo caso man
mano che i dati vengono ricevuti dal link, questi vengono anche
inviati sulla rete. In questo caso la procedura per verificare
che il messaggio \`e completo \`e estremamente semplice --
ritorna sempre il valore {\tt TRUE}.

Anche se questo protocollo non \`e estremamente efficiente,
bisogna tuttavia notare che il {\em server} pu\`o continuare a
trasmettere i messaggi in un singolo messaggio. Inoltre, per il
modo in cui sono generati i messaggi sul Transputer, e per come
\`e fatto l'I/O sul link, tutti i messaggi provenienti dal link
sono trasferiti, con elevata probabilit\`a, in uno o due
operazioni di I/O. Pertanto, l'utilit\`a 
di gestire protocolli diversi \`e tutta da verificare,
probabilmente in modo sperimentale. Tuttavia il meccanismo dei
diversi protocolli \`e sicuramente utile e flessibile e non
comporta complicazioni implementative.

\subsection{Peek protocol}

Il meccanismo dei protocolli risulta infatti utile
nell'esecuzione dei comandi. Infatti, ad esempio nel caso di
``peek'' di un link, \`e necessario leggere esattamente $4n$ bytes
da un link, dove $n$ \`e il numero di word da leggere.
Pertanto, durante l'esecuzione di una
istruzione di peek, viene invocata una particolare funzione che
attende tutti i bytes richiesti siano effettivamente letti prima
di effettuare la trasmissione verso la rete.
Questa funzione \`e ancora da implementare.

\section{Fault tolerance}

E` molto importante che il {\tt pcserver} sia in grado di reagire
a situazioni di errore senza bloccarsi. Diverse strategie possono
essere utilizzate, basate sia sulla esplicita identificazione di
errori che sull'uso di timeout. Le azioni da prendere devono
essere tali da causare il minor danno possibile pur garantendo
che il {\tt pcserver} possa ripristinare le sue funzionalit\`a.

In generale, errori non recuperabili che riguardano una singola
sessione comportano la chiusura della sessione stessa, senza
per\`o effettuare operazioni (es. reset) sul link. Errori gravi
nell'accesso alla rete possono richiedere la reinizializzazione
dell'intero programma.

Un buon criterio per rivelare errori consiste nell'uso di
timeout. Questo si effettua semplicemente registrando, per
ciascuna sessione l'ora in cui \`e avvenuta l'ultima transizione
di stato, e verificando ogni volta per quanto tempo quella
sessione \`e rimasta nello stesso stato.
Certi stati infatti possono essere mantenuti per un
tempo potenzialmente infinito, mentre in altri si deve restare
per un tempo molto limitato. In particolare si pu\`o distinguere
tra gli stati seguenti:

\begin{enumerate}
\item   stati in cui si pu\`o restare per un tempo arbitrario,
	eventualmente anche effettuare il restart del programma. Questo
	per esempio accade quando tutti le sessioni sono inattive ({\tt
	lbufstat=B\_IDLE})

\item	stati in cui si pu\`o restare per un tempo arbitrario, ma
	non \`e possibile effettuare il restart. Ad esempio,
	{\tt B\_EMPTY} per entrambi i buffer.

\item	stati con timeout lunghi (minuti),
	per esempio nel caso di
	comandi distinti inviati dal {\em server} ({\tt
	lbufstat=B\_INIT\_WAIT}).

\item	stati con timeout medi (decine di secondi),
	per esempio quando
	si \`e in attesa del completamento di un
	trasferimento sulla rete.

\item	stati con timeout brevi (secondi), per esempio nel caso
	di completamento di un trasferimento sul link.

\end{enumerate}

Ai timeout si pu\`o reagire forzando l'interruzione della
sessione.

\section{Ambiente di debugging}

Per facilitare il debugging di {\tt pcserver} Unix, sono
presenti dei programmi addizionali. Innanzitutto, i moduli per
gestire la rete e il link su MSDOS ({\tt net.c} e {\tt link.c})
sono sostituiti da due moduli che svolgono le stesse funzioni per
Unix, e sono ({\tt unixnet.c} e {\tt unixlink.c}). La
gestione della rete \`e simile (si aprono delle connessioni in
modo passivo a partire dalla porta 2199). I link invece non sono
presenti, e sono quindi simulati tentando di aprire delle
connessioni come cliente sulle porte 2299 e seguenti.

Un paio di programmi sono usati come interfaccia. Il primo ({\tt
fakeserv.c}) simula il funzionamento di un server, e permette di
connettersi a {\tt pcserver} e leggere/scrivere dati. L'utente
deve simulare il comportamento di un server. L'I/O viene
fatto in esadecimale, mentre sulla rete viaggiano dati binari.
Se il server reale (afserver o iserver) esiste, \`e possibile
usarlo al posto di {\tt fakeserv}.

Il secondo programma ({\tt fakelink.c}) si mette in ascolto
sulla porta 2299 e seguenti, e simula un link. Anche in questo
caso l'utente simula il funzionamento di un Transputer, e l'I/O a
livello utente \`e effettuato in esadecimale anche se in rete
viaggiano dati binari.

\section{Modifiche a iserver}

{\tt iserver} \`e gi\`a strutturato in modo da fare uso di
comunicazione a blocchi su un device. Pertanto, non sono
necessarie grandi modifiche. In particolare, va solo aggiunto
un modulo che provvede ad effettuare l'I/O dalla rete invece che
dal link adapter. Tutto il nuovo codice va in {\tt pcs\_link.c}.

In questo modulo sono definite le funzioni base, ovvero:

\begin{itemize}

\item{\tt OpenLink()} Apre una connessione col server. Il
	parametro da passare alla procedura \`e una stringa che
	specifica il nome del link. Noi converremo di che questa
	stringa indichi l'hostname, eventualmente preceduto da un
	digit che indica quale utilizzare tra i vari link
	disponibili sul server.

\item{\tt CloseLink(l)} corrisponde alla {\tt close()} di unix,
	usa la stessa interfaccia.

\item{\tt ReadLink(l)} Legge dal link. In realt\`a, a causa del
	protocollo utilizzato, dobbiamo gestire localmente un
	buffer su cui fare I/O a blocchi.

\item{\tt WriteLink(l)} Anche qui dobbiamo bufferizzare l'I/O.

\item{\tt TestError()} Ritorna true se l'error flag del
	Transputer \`e settato. Siccome sul link transitano dati,
	questa situazione viene rivelata con una violazione di
	protocollo nella comunicazione sulla rete, oppure
	forzando la chiusura della comunicazione da parte del
	{\tt pcserver}. Nel primo caso si pu\`o ad esempio
	inviare un messaggio con campo lunghezza=0
	per indicare che l'error flag \`e
	settato. Questo header pu\`o arrivare in maniera
	asincrona e deve quindi essere rivelato dalla procedura
	di ricezione ed eventualmente memorizzato. Una volta
	settato, l'error flag non si resetta se non in caso di
	esplicito reset del Transputer.
	Il secondo metodo \`e forse pi\`u semplice da
	implementare, anche considerando che un errore, su {\tt
	iserver}, provoca sempre la terminazione del programma.
	Va notato per\`o che in questo caso bisogna prevedere un
	comando esplicito col quale il {\em server} chiede a {\tt
	pcserver} di segnalare in questo modo gli errori sul
	link. Questo comando \`e forse di difficile introduzione
	nei server.

\end{itemize}
\end{document}
