\articolo{Media Library}{Federico Zuccollo}

\noindent Media Library fornisce il supporto per la scrittura e l'uso di file system
modulari, in cui ogni componente implementa un insieme di funzionalità e
può essere liberamente aggiunto, sostituito o rimosso.

Lo scrittore di componenti può scegliere tra un'implementazione completa,
oppure basata sulla combinazione di componenti in uso o di loro funzioni.

Lo scrittore di applicazioni pianifica l'accesso al file system in termini
di componenti, potendo scegliere fra diverse implementazioni ed
eventualmente scriverne o definirne di nuove.

Le funzionalità dei componenti non sono necessariamente limitate a quelle
trovate nei file system tradizionali, ma possono includere servizi
usualmente forniti da librerie, patch, wedge, ecc.

Infine, la creazione e gestione di un file system è semplice quanto quella
di un file, per cui è immaginabile l'uso di file system temporanei o
dedicati a una specifica applicazione.


\paragrafo{Introduzione}
\noindent AmigaDOS offre un'interfaccia uniforme verso differenti file system tramite
degli handler esterni, con cui comunica attraverso un protocollo a pacchetti.

Questo modello, se da una parte è aperto all'implementazione di nuovi file
system, dall'altra richiede che tutte le funzionalità siano comprese nel
protocollo a pacchetti, oppure vengano fornite dalla libreria DOS: ad
esempio, il pattern matching e l'I/O buffering.

Media Library propone un modello a framework, in cui un file system è
composto da classi indipendenti e combinate a seconda dei servizi necessari.
Per ogni funzionalità si definisce un'interfaccia corrispondente ai servizi
della classe.

Questo articolo fornisce una panoramica di Media Library, senza essere
particolarmente dettagliato: la distribuzione comprende il software
dimostrativo e gli autodoc con un'introduzione tecnica.


\paragrafo{Come nacque l'idea}
\noindent Nel 1989 stavo scrivendo un file system molto più efficiente nel seeking,
grazie a un layout ad albero, e mi resi conto che sarebbe stato utile
scomporlo in parti indipendenti, sia per utilizzarle separatemente che per
sostituirle in modo da creare nuovi sistemi col minimo sforzo.

Col tempo vidi che non bastava una semplice definizione di protocollo di
composizione di parti, ma era anche richiesto un supporto per la
cooperazione, che infine divenne Media Library.


\paragrafo{Confronto con AmigaDOS}
\noindent Il file system di AmigaDOS è basato su un'interfaccia a pacchetti per
richiedere l'esecuzione di funzioni a handler esterni alla libreria.

Se da una parte questo permette l'aggiunta immediata di nuovi file system
tramite un semplice handler, d'altra parte comporta anche le seguenti limitazioni:

\begin{itemize}
\item{le funzioni esplicitamente invocabili sono solo quelle presenti nella
\f{dos.library}; i pacchetti sconosciuti alla libreria devono essere
inviati attraverso funzioni generiche senza controllo di tipo; questo
introduce un'asimmetria tra pacchetti standard e pacchetti speciali;}

\item{in un file system sono individuabili insiemi distinti di funzioni (per
esempio directory e file) che però devono essere raccolte in un solo
handler: questo impedisce di modificare un singolo insieme e riutilizzare
gli altri come moduli separati, portando quindi alla duplicazione di codice;}

\item{uno handler nasconde le funzioni disponibili: l'unico modo di
verificarne la presenza è attraverso l'invio di un pacchetto.
Un'applicazione non può perciò sapere in anticipo quali funzioni sono
presenti in un particolare file system.}
\end{itemize}


Media Library propone queste soluzioni:

\begin{itemize}
\item{le funzioni non risiedono nella libreria, ma sono racchiuse in
componenti separati, senza asimmetrie fra parti di sistema ed estensioni
dell'utente;}

\item{ogni componente implementa un insieme di servizi ed è ben distinto
dagli altri e che quindi non sono influenzati dalle sue modifiche;}

\item{ogni componente ha un tipo, la sua presenza in un file system
garantisce la disponibilità di almeno una parte delle sue funzioni, mentre
la sua assenza indica che il file system non fornisce assolutamente quei
servizi.}
\end{itemize}

\noindent L'idea di fondo è di rendere disponibili interfacce separate per ogni
oggetto presente in un file system, estraendo dalle applicazioni il codice
di gestione delle strutture persistenti.

Nel modello a handler questo non è proponibile; sia perché non tutte le
applicazioni persistenti sono riducibili a operazioni su file in modo da
usare le funzioni della \f{dos.library}; sia perché l'overhead del protocollo a
pacchetti rende talvolta improponibile l'uso di uno handler, per cui si
preferisce del codice interno a una normale libreria.
Ad esempio, le funzioni di I/O buffering aggiunte nel DOS 2.0 non avrebbero
potuto essere implementate con uno handler, poiché il loro scopo è proprio
quello di minimizzare lo scambio di pacchetti.

Al contrario, una classe comprendente le medesime funzioni può essere
aggiunta a qualsiasi file system, esternamente a Media Library.


\paragrafo{Descrizione del framework}
\noindent
\sottoparagrafo{Composizione del file system}
\noindent Svariate classi possono far parte di un file system, che viene detto {\em
spazio} delle classi, perché è l'ambito in cui coesistono, il loro universo.

La memoria persistente necessaria a ogni classe viene tracciata e allocata
da una classe speciale, che opera come l'allocatore di sistema per i task:
questa classe deve essere installata per prima, così da essere disponibile a
tutte le altre. Ciò consente la scrittura di classi indipendenti.

D'altra parte, se si scrivono delle classi cooperanti, basate su strutture
comuni, non è richiesta la classe di allocazione: questo è il caso dei file
system esistenti.

Un'altra classe predefinita fornisce lo store: si tratta di un file senza
nome, con un identificatore numerico; è analogo all'{\it inode} del file system
Unix.

Le operazioni ammesse sullo store sono quelle tradizionali (\c{open()},
\c{close()}, \c{read()}, \c{write()}, \c{seek()}) più altre meno
usuali, richieste dall'utilizzo fondamentale degli store: essi ospitano
fisicamente lo spazio e le sue classi.


\begin{figure}[ht]
\begin{center}\small\ttfamily\settowidth{\charwidth}{X}\begin{minipage}{29\charwidth}\begin{verbatim}
+--------------------------+
| +--------+    +--------+ |
| | classe | .. | classe | |
| +--------+    +--------+ |
|          spazio          |
+--------------------------+
            \  /
          +-------+
          | store |
          +-------+
\end{verbatim}\end{minipage}\end{center}
\caption{\small Lo spazio, le classi e lo store}
\end{figure}

Questo consente due particolarità:
\begin{itemize}
\item{ogni classe usa l'interfaccia \hbox{``Stores''} per accedere ai propri dati,
risultando in un'implementazione e un porting semplificati;}
\item{ovunque vi sia una classe \hbox{``Stores''} possono essere montati degli spazi, anche
all'interno di altri spazi. La creazione di file system è altrettanto facile
quanto la creazione degli store.}
\end{itemize}

\begin{figure}[ht]
\begin{center}\small\ttfamily\settowidth{\charwidth}{X}\begin{minipage}{26\charwidth}\begin{verbatim}
    +------------+
+-> | sub-spazio |
|   +------------+
|     \  /
|   +-------+
|   | store |
|   +-------+  ...   ...
|       \       |    /
|        +----------+
|        |  classe  |  ..
|        | "Stores" |
|      | +----------+
+------|    spazio
 link  +---------------
 tra        \  /
 spazi    +-------+
          | store |
          +-------+
\end{verbatim}\end{minipage}\end{center}
\caption{\small Spazio e sub-spazio}
\end{figure}


\noindent Il mounting di spazi all'interno di altri crea un albero degli spazi, utile
ad esempio per file system su diversi livelli. Ogni spazio ha un nome locale
(relativo al genitore) e un nome globale, composto dai nomi degli spazi
lungo il percorso fino al primo livello.

Esistono spazi non legati a uno store, le cui classi accedono in altri modi
ai propri dati: tali spazi sono detti \emph{root} e costituiscono il
collegamento con i device del sistema operativo.

\begin{figure}[ht]
\begin{center}\small\ttfamily\settowidth{\charwidth}{X}\begin{minipage}{26\charwidth}\begin{verbatim}
      +-------------+
+---> | spazio root |
|     +-------------+
|          \  /
|   +-------------------+
|   | Exec device o RAM |
|   +-------------------+
:
:
|      |
+------| eventuale
 link  | spazio host
 tra   +--------------
 spazi    \  /
           ...
\end{verbatim}\end{minipage}\end{center}
\caption{\small Uno spazio root}
\end{figure}

Solitamente una root appare al primo livello, ma può anche essere montata in
uno spazio qualunque, che ospiti o meno la classe \hbox{``Stores''}\,---\,che del resto
non viene usata. Esempio di root ubicabile ovunque è lo spazio
``ramdisk'',
montabile in ogni spazio come file system temporaneo.


\sottoparagrafo{Composizione della classe}
\noindent Una classe viene implementata in due componenti caricati separatamente.

\begin{itemize}
\item{Il primo componente è detto {\it IKernel}\footnote{Interface Kernel.} e rappresenta la parte pubblica della
classe: le sue funzioni vengono invocate concorrentemente da diversi task,
e svolgono i compiti di controllo e {\it policy} (politica) degli accessi.}
\item{Il secondo componente è detto {\it Mos}\footnote{Modular Operating
System.} e rappresenta la parte privata: le sue
funzioni sono invocate esclusivamente dall'IKernel associato, e implementano
il {\it mechanism} dell'oggetto. A sua volta, il Mos accede allo store in cui
è ospitato il suo spazio: si noti che non ha privilegi speciali, ma usa lo
store come farebbe una qualunque applicazione.}
\end{itemize}


\begin{figure}[ht]
\begin{center}\small\ttfamily\settowidth{\charwidth}{X}\begin{minipage}{27\charwidth}\begin{verbatim}
  interfaccia
  della classe
+-----\ /-----+
| +---------+ | componente
| | IKernel | | pubblico
| +---------+ |
|- - -| |- - -|
| +---------+ | componente
| |   Mos   | | privato
| +---------+ |
+-----| |-----+
      \ /
   +-------+
   | store |
   +-------+
\end{verbatim}\end{minipage}\end{center}
\caption{\small La classe e i suoi componenti}
\end{figure}


\noindent I nomi IKernel e Mos sono lasciti storici da una prima (obsoleta) versione
di Media Library.

Esistono anche implementazioni senza store, come per esempio il ramdisk,
nelle quali un flag indica questa eccezione. Media Library usa il flag per
mantenere separate le classi con e senza store, in modo da avere spazi
omogenei.

La divisione di politica e meccanismo fra IKernel e Mos è solo una
convenzione, dato che Media Library non ha né il modo né lo scopo di
verificare che i compiti siano effettivamente separati.

I vantaggi consistono nella semplificazione delle funzioni Mos
e nella varietà di IKernel. Le funzioni Mos vengono
scritte come delle subroutine non concorrenti, dato che l'IKernel
serializza gli accessi.

Vi sono delle eccezioni alla separazione fra IKernel e Mos:

\begin{itemize}
\item il componente pubblico può non passare attraverso il Mos, ma far uso
diretto delle risorse di sistema: ne sono esempio gli stores IKernel per i
device, che mappano uno store su una unit;

\begin{figure}[ht]
\begin{center}\small\ttfamily\settowidth{\charwidth}{X}\begin{minipage}{27\charwidth}\begin{verbatim}
+-------------+
| +---------+ |
| | Device  | | componente
| | IKernel | | diretto
| +---------+ |
|- - -| |- - -|
| +---| |---+ | componente
| |   | |   | | nullo
| +---| |---+ |
+-----| |-----+
      \ /
+-------------------+
| Exec device o RAM |
+-------------------+
\end{verbatim}\end{minipage}\end{center}
\caption{\small Uso diretto delle risorse}
\end{figure}

\item{il componente pubblico può basarsi su altre classi già presenti nello
spazio, sia per modificarne il comportamento, sia per costruire una nuova
interfaccia.

\begin{figure}[ht]
\begin{center}\small\ttfamily\settowidth{\charwidth}{X}\begin{minipage}{27\charwidth}\begin{verbatim}
+-------------+
| +---------+ |
| | Runtime | | componente
| | IKernel | | runtime
| +---------+ |
|- - -| |- - -|
| +---| |---+ | componente
| |   | |   | | nullo
| +---| |---+ |
+-----| |-----+
      \ /
   +--------+
   | classe |
   +--------+
\end{verbatim}\end{minipage}\end{center}
\caption{\small Utilizzo di altre classi}
\end{figure}


}
\end{itemize}

\noindent In entrambi i casi, il componente privato non è presente, e Media Library lo
sostituisce con un modulo vuoto.


\paragrafo{La libreria}
\noindent Classe e spazio sono i due concetti su cui si basa il framework, e la
suddivisione della libreria in due manager rispecchia ciò. Inoltre questo
risponde ai requisiti di coesione (le funzioni correlate si trovano insieme)
e loose coupling  (nessun manager conosce né richiede i dettagli
interni dell'altro).


\sottoparagrafo{Class Manager}
\noindent Il Class Manager si incarica di cercare, caricare e costruire i componenti e
le classi.

Il componente viene costruito partendo da un tag, residente nella libreria
oppure caricato da disco, e identificato da visibilità, classe e
implementazione: ad esempio \c{private/¦Names/¦ramdisk}, oppure
\c{public/¦Stores/¦trackdisk}.

Durante la costruzione, il componente può richiederne altri, allo scopo
di condividerne le funzioni. Le aperture cicliche A$\to$B$\to$C$\to$A vengono
rilevate, evitando loop infiniti\footnote{Il function sharing
è ancora sperimentale.}.

La classe descrive i suoi 2 componenti, nel formato appena visto.
Naturalmente il medesimo componente può far parte di più classi.


\sottoparagrafo{Mount Manager}
\noindent Il Mount Manager, una volta ottenute le classi dal Class Manager, si
incarica prima di cercare e costruire gli spazi e poi di installarvi e montarvi le classi.
I diversi tipi
di classe, la connessione con lo store, la collaborazione fra classi sono
tutti mantenuti e resi possibili da questo manager.

L'installazione di uno spazio nello store comporta la scrittura di una mount
table in una certa posizione, che conterrà le informazioni sulle classi
presenti; la tavola viene modificata ogni volta che viene aggiunta o rimossa
una classe e viene consultata per il mount su richiesta.

\begin{figure}[ht]
\begin{center}\small\ttfamily\settowidth{\charwidth}{X}\begin{minipage}{16\charwidth}\begin{verbatim}
+-------------+
| mount tag   |
| - - - - - - |
| class list  |
| ...         |
| - - - - - - |
| class data  |
+-------------+
\end{verbatim}\end{minipage}\end{center}
\caption{\small Formato di uno store installato}
\end{figure}


Nei casi in cui lo store sia in un formato diverso, o non sia usato, le
classi devono essere montate fornendo direttamente la loro descrizione.

L'ultima classe montata nasconde le altre dello stesso tipo, consentendo di
alterarne o supplementarne le funzioni.

\begin{figure}[ht]
\begin{center}\small\ttfamily\settowidth{\charwidth}{X}\begin{minipage}{27\charwidth}\begin{verbatim}
    ...
     |
+----------+
|  classe  | FindName()
| "Stores" | trova "alfa"
|  "alfa"  | per prima
+----------+
     |
    ...     (altre classi)
     |
+----------+
|  classe  | "alfa"
| "Stores" | a sua volta
|  "beta"  | chiama "beta"
+----------+
     |
    ...

\end{verbatim}\end{minipage}\end{center}
\caption{\small Alterazione di funzioni}
\end{figure}


Uno spazio montato su uno store può essere online, se connesso, oppure
offline, quando sconnesso: questo si verifica con gli store rimovibili
(dischi), ma può anche essere esplicitamente richiesto al manager. Gli spazi
root rimangono sempre offline.

La ricerca di uno spazio interno ad altri spazi viene fatta via via montando
tutti i nodi dell'albero lungo il percorso, oppure passando al manager una
stringa con la descrizione del percorso: questa stringa è il nome globale
dello spazio, contrapposto al nome locale relativo al genitore.


\sottoparagrafo{Accessors}
\noindent Questa parte della libreria comprende funzioni di accesso a membri di
strutture semi-private.


\paragrafo{La classe}
\noindent Nell'accezione del C++, la derivazione, o ereditarietà, stabilisce una
relazione fra una classe esistente\,---\,la base o super-classe\,---\,e una nuova
classe\,---\,la derivata o sotto-classe\,---\,tale che quest'ultima possa
sostituirsi alla prima, ma non viceversa, avendone tutte le proprietà,
oltre alle sue proprie.

Una classe astratta specifica solamente un'interfaccia, senza implementarne
le funzioni, che saranno fornite da classi concrete: in questo modo si
pubblica una sola interfaccia a diverse versioni del codice e si mantiene la
relazione fra le classi.

Media Library definisce una classe astratta di base, in cui si trovano sia
funzioni riservate ai manager per la costruzione della classe, sia altre
funzioni e strutture comuni a tutte le classi.
Per ogni funzionalità viene poi definita una classe astratta derivata, che
estende le funzioni e le strutture comuni e aggiunge quelle proprie
dell'oggetto.
Infine, si hanno diverse implementazioni della classe derivata, distinte fra
loro per nome.

\begin{figure}[ht]
\begin{center}\small\ttfamily\settowidth{\charwidth}{X}\begin{minipage}{25\charwidth}\begin{verbatim}
  +----------+
  | base     | la base
  | astratta | comune
  | "Mount"  |
  +----------+
    /  \   \
   /   ... ...
  /
 +----------+
 | derivata | una delle
 | astratta | estensioni
 | "Stores" |
 +----------+
   |   |   |
   |  ... ...
   |
   | un'implementazione
  +-----------+
  | "ramdisk" |
  +-----------+
\end{verbatim}\end{minipage}\end{center}
\caption{\small Un esempio di derivazione}
\end{figure}


Si noti che solitamente una classe astratta non viene derivata, poiché è
intesa solo come interfaccia a differenti classi concrete; in questo caso
però la base ha il solo scopo di isolare funzioni comuni e utili per tutte
le altre classi.

\sottoparagrafo{La definizione di base}

\noindent Le funzioni riservate si occupano di installare, montare e
connettere la classe. L'installazione pone nello spazio i dati necessari
alla classe, e ne restituisce la posizione, che sarà poi richiesta nel mount.

Nel mount viene allocata una struttura, il core, usata per operare in quello
spazio: un oggetto di quella classe è rappresentato da un gate, una
struttura mantenuta dal core.

\begin{figure}[ht]
\begin{center}\small\ttfamily\settowidth{\charwidth}{X}\begin{minipage}{19\charwidth}\begin{verbatim}
+----------+
| gate     |
| instance |
+----------+
 |   \    ...  ...
 |    \   /    /
 |   +----------+
 |   | core     |
 |   | instance |
 |   +----------+
 |    |
  \  /
 +-------+
 | store |
 +-------+
\end{verbatim}\end{minipage}\end{center}
\caption{\small Le strutture della classe nello spazio}
\end{figure}

La funzione di connessione della classe con lo store serve a legare il core
a differenti store, ed è principalmente usata nei cambi di disco, ovviamente
non è operativa nelle classi senza store.

Le funzioni non riservate si occupano dello stato degli oggetti, della
notifica di eventi e del core locking.

Lo stato di un core comprende, tra l'altro:

\begin{itemize}
\item{la memoria usata;}
\item{il numero di oggetti creati;}
\item{la dimensione dell'area utente;}
\item{il suo nome;}
\item{la data di creazione.}
\end{itemize}

\noindent Lo stato di un gate comprende, tra l'altro:

\begin{itemize}
\item{il suo identificatore numerico;}
\item{il link con un altro gate;}
\item il contenuto dell'area utente\footnote{Essendo un buffer, la sua dimensione viene
indicata all'installazione.}.
\end{itemize}

\noindent L'area utente è mantenuta da ogni gate e contiene dati privati
dell'utente; il componente non è però obbligato a fornirla.

La notifica di eventi è analoga a quella di AmigaDOS, con l'aggiunta degli
eventi di rimozione e inserimento di dischi.

Il core locking,  o esclusione, chiude temporaneamente il core, riservando
al locker le operazioni che ne alterano lo stato\footnote{Creazione, modifica e
distruzione di oggetti.} e rigettando i tentativi altrui. È pensato per
semplici operazioni atomiche su più oggetti.

\sottoparagrafo{La derivazione}
\noindent Le funzioni comuni vengono ridichiarate usando il tipo derivato, mentre le
strutture estese hanno come primo membro la struttura di base, così da poter
essere usate con entrambi i prototipi di funzione.

La presenza di due prototipi\footnote{Base e derivata.} per ogni funzione comune
permette ad esempio di ottenere lo stato di un oggetto sia utilizzando la
struttura base, con i dati generali, che quella estesa, con in più i dati
specifici della classe. Si noti che la funzione chiamata è la stessa in
entrambi i casi: un membro della struttura base ne indica la dimensione reale,
di modo che la funzione sappia quanti dati trasferire.


\sottoparagrafo{Il componente}
\noindent Costituente ultimo della classe, il componente è il modulo caricabile che
comprende le funzioni IKernel o Mos e l'informazione su classe,
implementazione, versione e function sharing.

Il suo formato è simile, ma non identico, a quello delle librerie
condivise, in modo da poter sfruttare la direttiva \c{\#pragma libcall},
evitando però erronei caricamenti con \c{OpenLibrary()}.

Il componente IKernel può offrire a richiesta l'I/O concorrente\footnote{Diverse
richieste in esecuzione.} e l'I/O asincrono\footnote{Una richiesta eseguita
autonomamente.}.

Il componente Mos offre solo l'I/O serializzato, on includendo meccanismi di
locking, e l'I/O sincrono (niente code di richieste da eseguire). L'I/O
sincrono deve trasferire la minima quantità efficiente di dati, cosicché
l'IKernel possa alternare fra diverse richieste, in una sorta di
multi-esecuzione.


\paragrafo{Le classi predefinite}
\noindent Sebbene per Media Library non esistano classi speciali, è indubbio che il
framework deve basarsi sulle caratteristiche di una o più classi.


\sottoparagrafo{Mount}
\noindent È la classe di base, e inquadra le funzioni e strutture comuni: viene
usata solo nell'accesso a classi di cui non si conosce il tipo.


\sottoparagrafo{Stores}
\noindent È la classe fondamentale, e fornisce l'astrazione per l'accesso alle
partizioni e in generale ai file senza nome. Oltre alle classiche
operazioni, è stata dotata di:

\begin{itemize}
\item{un accesso flessibile ai dati, le cui modalità (lettura, scrittura sincrona
e asincrona)
possono essere variate tra l'apertura e la chiusura dello store; una classe
può così mantenere aperto lo store senza bloccarne l'accesso;}
\item{un controllo esplicito dei blocchi occupati, che permette di preallocare
e liberare dinamicamente zone dello store;}
\item{una scrittura sparsa, con cui ci si può spostare in un punto qualunque
dello store, entro i limiti consentiti dall'implementazione
($\text{0}\ldots\text{2}^{\text{31}}-\text{1}$),
e scrivere un blocco di dati allocando al volo quella zona, similmente
alla memoria virtuale.}
\end{itemize}

\noindent Queste operazioni sono particolarmente utili per un file system,
ma sono a disposizione anche di normali applicazioni.


\sottoparagrafo{Blocks}
\noindent Questa classe non è fondamentale, ma consente alle altre classi di
coesistere in uno store e di cambiare la strategia di allocazione a seconda
del file system.

Allo stato corrente, sono state definite 3 operazioni: split, merge e
bitmap, per ottenere una mappa dei settori. È ancora da verificare se siano
sufficienti e ben definite, perché non sono ancora state scritte classi che
ne facciano uso.


\sottoparagrafo{Names}
\noindent Questa classe fornisce le operazioni per inserire e cercare un nome; non usa
il concetto di directory, ma piuttosto definisce un nome come concatenazione
di nomi già inseriti. È dunque una classe generale con la quale si può simulare
un normale file system gerarchico.

Come ogni oggetto, un nome può essere collegato a un altro oggetto: un file
tradizionale viene emulato usando un nome e uno store; ovviamente diversi
nomi possono essere collegati allo stesso store.

La mancanza del concetto di directory richiede che se un nome contiene un
path non esistente, questo venga creato al volo, anche se poi solo il nome
completo sarà visibile. Solo i nomi inseriti, siano nuovi o parte di un path
esistente, sono effettivamente visibili.


\paragrafo{La definizione di nuove classi}
\noindent Una nuova classe richiede la definizione delle interfacce di un IKernel e
di un Mos, e la loro pubblicazione tramite i prototipi e gli include file di
descrizione delle strutture.
In pratica, è sufficiente imitare gli include file già forniti per le altre classi.


\paragrafo{Esempi e possibilità}
\noindent Di seguito sono elencate alcune idee da (provare a) realizzare col
framework di supporto di Media Library.

Si può obiettare che un framework non è necessario, e lo dimostrano tante
altre soluzioni (librerie, patch, wedge, ecc.). Allo stesso modo, si può affermare
che la programmazione a oggetti è possibile anche in C, senza ricorrere al
C++.

La differenza tra C++ e C è che il primo offre supporto diretto per la programmazione
a oggetti, per cui si esprimono certe relazioni già nel linguaggio,
mentre in C è necessario ricorrere a workaround; nondimeno è possibile, ma non
è detto che sia piacevole, sintetico, elegante.

Lo stesso si può dire di Media Library: lo spazio permette
di organizzare e usare le classi di un file system, e queste a loro volta
sono raccolte per tipo e implementazione, senza andare a infoltire la lista
delle librerie di sistema.


\sottoparagrafo{File system riservato}
\noindent La creazione di un nuovo file system richiede soltanto l'installazione in uno
store della mount table e la lista delle classi; un intero progetto può allora
essere mantenuto nello store, separato da altri progetti, e copiato o
spostato tramite lo store.

Similmente, si può montare un ramdisk temporaneo e rimuoverlo per
cancellarne in blocco tutti gli oggetti.


\sottoparagrafo{Filtri}
\noindent La classe \hbox{``Stores''} viene supplementata con alias in grado di
intercettare le funzioni \c{read()} e \c{write()} ed elaborarne i dati,
ad esempio per codificarli o comprimerli trasparentemente,
sotto il controllo della classe alias.


\sottoparagrafo{Icon cache}
\noindent La velocità di accesso ai file \f{.info} non è sempre entusiasmante, e la loro
spesso piccola dimensione usa molto più spazio di quanto non sembri (minimo
1\,K), ma non varrebbe certo la pena di scrivere uno handler solo per le icone.

D'altra parte, un alias per la classe \hbox{``Names''}, che filtri i file \f{.info} e li
memorizzi in un modo ottimo sia per cercarli che per leggerli, non è al di
fuori delle capacità di Media Library. Certamente, la difficoltà starebbe
nel fare usare a \f{icon.library} la nuova classe.


\sottoparagrafo{Pattern matching}
\noindent In uno spazio contenente, tra l'altro, la classe \hbox{``Names''} si aggiunge una
classe ``PatternMatch'', la quale comprende le funzioni classiche di wildcarding che non
sono incluse in \hbox{``Names''}:
\c{match\_first()}, \c{match\_next()}, \c{match\_end()}.


\sottoparagrafo{I/O buffering}
\noindent In uno spazio contenente, tra l'altro, la classe \hbox{``Stores''} si aggiunge una
classe ``IOBuffer'', comprendente le funzioni classiche di I/O a carattere -
\c{fgetc()}, \c{fputc()}\,---\,in modo da ottimizzare l'I/O su store, che solitamente
non usa buffer.


\sottoparagrafo{Database engine}
\noindent Supponendo che in uno spazio siano già presenti \hbox{``Names''} e \hbox{``Stores''}, si
scrive una classe ``Records'' che, tramite nomi e store, implementi un
database con dei record indicizzati: l'utilità starebbe nel rendere parte
del file system l'interfaccia al database, che potrebbe allora essere
consultato da diverse applicazioni, oltre che dal creatore.

In più, ogni spazio può adottare un'implementazione diversa di ``Records'', a
seconda dello scopo del file system.


\sottoparagrafo{Diagnostica}
\noindent La funzionalità di check e repair di un file system viene isolata
in una classe, di cui si scrivono versioni per ogni classe associata:
per esempio, a \hbox{``Names''} corrisponde ``Names-diag'', e un programma
come DiskSalv non ha più bisogno di essere aggiornato per ogni nuovo
file system.


\sottoparagrafo{Monitoring e debugging}
\noindent Statistiche sull'uso di una classe vengono raccolte da una
classe alias che intercetta (legalmente) le chiamate di funzione
e prepara un report, oppure controlla i parametri e intraprende
azioni correttive.


\sottoparagrafo{Device control}
\noindent Inizialmente, non fu chiaro se includere nella classe \hbox{``Stores''} anche le
funzioni specifiche solo a un device come format e raw read/write, dato che
non rientrano nel concetto di store.

Si decise poi di definire classi a parte, in modo che le applicazioni
a conoscenza della classe speciale potessero aggiungerla e usarla
senza influenzare la classe \hbox{``Stores''}.

Per esempio, il comando \c{format} viene incluso nelle classi
``DiskFormat'' o ``DiskCtl''.

Notare che l'interrupt di cambio disco rientra invece negli eventi
segnalati dalla funzione di notifica, presente in tutte le classi.


\paragrafo{Stato attuale e sviluppi futuri}
\noindent Sia la libreria che le classi fornite sono utilizzabili per avere un'idea di
come strutturare un'applicazione, tuttavia non sono ancora in uno stato
definitivo.

La libreria è ancora priva di un sistema di report ed error logging: in
altre parole, una funzione restituisce $-$1 o \c{NULL} in caso di errore,
ma non c'è modo di conoscerne la causa.

L'entry point ARexx in Media Library è previsto ma non ancora implementato.
Anche la classe ha un entry point, non essendo però una libreria, si deve
studiare un meccanismo di forwarding che, passando da Media Library, arrivi
alla classe.

La classe ``Blocks'' non è ancora stata implementata e verificata,
né esistono, ovviamente, classi che ne facciano uso.

L'accesso al file system AmigaDOS è incompleto, disponendo solo
della classe \hbox{``Names''}, mentre manca del tutto la classe \hbox{``Stores''}.

Viceversa, uno handler di compatibilità da AmigaDOS a Media Library
permetterebbe di provare il sistema con le applicazioni esistenti.
Infine, sarebbe utile un nuovo file system completamente a classi,
da installare in una sua partizione su disco.


\sottoparagrafo{Coesistenza con AmigaDOS}
\noindent È importante sottolineare che Media Library è una proposta alternativa
all'interfaccia del file system di AmigaDOS, e non pretende di sostituire
le altre parti\,---\,processi, console, esecuzione di comandi.

Non di meno, queste parti di AmigaDOS fanno riferimento al file system,
e a meno di adattarle, sarà necessario mantenere l'interfaccia esistente
e integrarla con le classi di Media Library.

Le classi di Media Library dovranno comunque fornire tutti i servizi
ottenibili dal file system tradizionale, altrimenti un'applicazione
dovrà appoggiarsi a entrambi i sistemi aumentando la sua complessità,
il che non è esattamente l'obiettivo cercato.

Un altro punto di contesa è se le classi potranno riferirsi all'ambiente
esistente, cioè utilizzare dati delle strutture AmigaDOS, o limitarsi
ai task, così da essere più portabili.

Infine, per quanto riguarda i formati esistenti, Media Library permette
di montare uno spazio da una partizione o disco AmigaDOS, ma richiede
all'applicazione di specificare le diverse classi. In futuro, la conoscenza
riguardo ai formati DOS potrebbe essere aggiunta internamente.


\sottoparagrafo{Conversione}
\noindent È prematuro scrivere di adattamento delle applicazioni esistenti,
dato che mancano delle classi; si può però dire che la conversione
non richiederà solamente di cambiare le chiamate di funzione, ma
anche un ripensamento del modello di dati su cui è fondata l'applicazione,
in modo da spostare nelle classi il codice interno.


\paragrafo{La distribuzione}
\noindent È divisa in tre archivi, secondo la destinazione; gli archivi sono disgiunti
e incrementali; gli include file sono per il SAS/C 6.55, e ne usano
alcune estensioni.

Gli eseguibili sono stati compilati senza ottimizzazione; ho osservato
una riduzione del 10-20\% in alcune prove.


\sottoparagrafo{Utente}
\noindent Questa distribuzione contiene la libreria \f{media.library} e i moduli
\c{.mclass}, \c{.ikern} e \c{.mos} disposti correttamente
nelle loro directory.

Inoltre, sono forniti alcuni tool di test per le classi \hbox{``Names''} e \hbox{``Stores''},
e il tool generico Mount per l'analisi degli spazi.


\sottoparagrafo{Sviluppatore di applicazioni}
\noindent Questa distribuzione aggiunge gli include file per la libreria e le classi,
e gli autodoc con il \f{makefile} per generare i documenti AmigaGuide.


\sottoparagrafo{Sviluppatore di classi}
\noindent Infine, questa distribuzione contiene gli include file per la scrittura
delle classi e alcuni sorgenti di esempio.

\autore{Federico Zuccollo\\
Via Peduzzi 2/a\\
I-22019 Tremezzo CO\\
Tel.:~(0344)41566
}
{Internet: zuccollf@ing.unico.it}

\citazione{\selectlanguage{english}%
\emph{The lesser-known programming languages \#13: SLOBOL}\\
{SLOBOL} is best known for the speed, or lack of it, of its compiler.
Although many compilers allow you to take a coffee break while they
compile, {SLOBOL} compilers allow you to travel to Bolivia to pick the
coffee.  Forty-three programmers are known to have died of boredom
sitting at their terminals while waiting for a {SLOBOL} program to
compile.  Weary {SLOBOL} programmers often turn to a related (but
infinitely faster) language, {COCAINE}.}{}