Scopo del sistema
Supporto per l'accesso remoto ai file sui computer in rete. Il sistema supporta "virtualmente" tutte le operazioni file fondamentali (creazione, eliminazione, lettura, scrittura, ecc.) attraverso lo scambio di transazioni (messaggi) utilizzando il protocollo TCP.
Ambiti di applicazione
Le funzionalità del sistema sono efficaci nei seguenti casi:
- nelle applicazioni native per dispositivi mobili e embedded (smartphone, sistemi di controllo a bordo, ecc.), che richiedono un accesso rapido ai file su server remoti in caso di possibili interruzioni temporanee della connessione (quando si va offline);
- in sistemi di database sovraccarichi, se l'elaborazione delle richieste avviene su server diversi dalla memorizzazione dei dati;
- in reti aziendali distribuite per la raccolta e l'elaborazione delle informazioni, che richiedono elevate velocità di scambio dei dati, riserva e affidabilità;
- in sistemi complessi con architettura a microservizi, dove i ritardi nello scambio di informazioni tra i moduli sono di fondamentale importanza.
Struttura
Il sistema Cage (è disponibile una realizzazione — versione beta su Python 3.7 per OS Windows) include due parti principali:
- Cageserver — programma del file server (pacchetto di funzioni), che viene avviato sui computer della rete, ai cui file è necessario l'accesso remoto;
- classe Cage con una libreria di metodi per software client, che semplifica il codice per l'interazione con i server.
Utilizzo del sistema lato client
I metodi della classe Cage sostituiscono le normali operazioni "routine" del file system: creazione, apertura, chiusura, eliminazione di file, così come lettura/scrittura di dati in formato binario (specificando la posizione e la dimensione dei dati). Concettualmente, questi metodi sono simili alle funzioni file del linguaggio C, dove l'apertura/chiusura dei file avviene "sui canali" di input/output.
In altre parole, il programmatore non lavora con i metodi degli oggetti "file" (classe _io in Python), ma con i metodi della classe Cage.
Quando viene creato un'istanza dell'oggetto Cage, essa stabilisce un collegamento iniziale con il server (o più server), passa l'autenticazione tramite l'ID del cliente e riceve conferma con il numero della porta assegnata per tutte le operazioni sui file. Alla cancellazione dell'oggetto Cage, viene inviata al server un'istruzione per interrompere la connessione e chiudere i file. Anche i server possono iniziare l'interruzione della connessione.
Il sistema aumenta le prestazioni di lettura/scrittura basandosi sulla memorizzazione nella cache di frammenti di file frequentemente utilizzati nei programmi client nella memoria RAM (buffer).
Il software client può utilizzare qualsiasi numero di oggetti Cage con diverse impostazioni (dimensione della memoria buffer, dimensione dei blocchi durante lo scambio con il server, ecc.).
Un oggetto Cage può scambiare dati con più file su diversi server. I parametri di connessione (indirizzo IP o DNS del server, porta principale per l'autenticazione, percorso e nome del file) sono impostati al momento della creazione dell'oggetto.
Poiché ogni oggetto Cage può lavorare contemporaneamente con numerosi file, si utilizza uno spazio di memoria condiviso per la memorizzazione nella cache. La dimensione della cache – il numero di pagine e la loro dimensione – viene definita dinamicamente al momento della creazione dell'oggetto Cage. Ad esempio, una cache di 1 GB corrisponde a 1000 pagine da 1 MB, oppure 10.000 pagine da 100 KB, oppure 1 milione di pagine da 1 KB. La scelta della dimensione e del numero di pagine è una questione specifica per ogni caso applicativo.
È possibile utilizzare simultaneamente più oggetti Cage per definire diverse impostazioni della memoria buffer in base alle caratteristiche di accesso alle informazioni in vari file. Viene applicato un algoritmo di memorizzazione nella cache di base: dopo l'esaurimento della memoria assegnata, nuove pagine sostituiscono le vecchie secondo il principio di rimozione con il numero minimo di accessi. La memorizzazione nella cache è particolarmente efficace in caso di accesso congiunto non uniforme (in senso statistico), sia a file diversi, sia a frammenti di ciascun file.
La classe Cage supporta l'input/output non solo per indirizzi dati (indicando la posizione e la lunghezza dell'array, 'sostituendo' le operazioni del file system), ma anche a un livello più basso, 'fisico' – per numeri di pagina nella memoria buffer.
Per gli oggetti Cage è supportata la funzione originale «ibernazione» («sogno») – possono essere «compressi» (ad esempio, in caso di interruzione della connessione ai server, o quando l'applicazione viene arrestata, ecc.) in un file di dump locale sul client e rapidamente ripristinati da questo file (dopo il ripristino della connessione, al riavvio dell'applicazione). Questo consente una significativa riduzione del traffico quando viene riattivata l'applicazione client dopo un temporaneo allontanamento «offline», poiché frammenti di file frequentemente utilizzati saranno già presenti nella cache.
Cage — è di circa 3600 righe di codice.
Principi di costruzione dei server
I file-server Cageserver possono essere avviati con un numero qualsiasi di porte, una delle quali («principale») è utilizzata solo per l'autenticazione di tutti i client, le altre — per lo scambio di dati. Per il programma del server Cage è richiesto solo Python. Parallelamente, il computer con il file-server può eseguire qualsiasi altro lavoro.
Il server viene avviato inizialmente come un insieme di due processi principali:
- «Connessioni» – processo per eseguire operazioni di instaurazione e interruzione della connessione con i client a iniziativa del server;
- «Operazioni» – processo per eseguire compiti (operazioni) dei client relativi ai file, oltre a chiudere le sessioni di connessione su comandi dei client.
Entrambi i processi non sono sincronizzati e organizzati come cicli infiniti di ricezione e invio di messaggi sulla base di code multiprocessuali, oggetti proxy, lock e socket.
Il processo «Connessioni» assegna a ogni client una porta per la trasmissione di dati. Il numero di porte è definito all'avvio del server. La corrispondenza tra porte e client è memorizzata in una memoria proxy condivisa tra i processi.
Il processo «Operazioni» supporta la condivisione delle risorse file, consentendo a più client diversi di leggere insieme (quasi in parallelo, poiché l'accesso è gestito tramite lock) dati da un file, se questo è stato autorizzato al momento della sua apertura iniziale da parte del «primo» client.
L'elaborazione dei comandi per la creazione/rimozione/apertura/chiusura di file su server è eseguita all'interno del processo «Operazioni» in modo strettamente sequenziale utilizzando il sottosistema file del server OS.
Per accelerare la lettura/scrittura, queste operazioni vengono eseguite in thread generati dal processo "Operazioni". Il numero di thread è generalmente pari al numero di file aperti. I compiti di lettura/scrittura dai clienti vengono inviati a una coda comune e il primo thread disponibile preleva il compito dalla testa della coda. Una logica speciale consente di escludere le operazioni di riscrittura dei dati nella memoria operativa del server.
Il processo "Operazioni" monitora l'attività dei clienti e interrompe il loro servizio sia su loro comando che in caso di superamento del timeout di inattività.
Per garantire l'affidabilità, il Cageserver tiene traccia di tutti i registri delle transazioni. Un unico registro generale contiene copie dei messaggi dai clienti con compiti di creazione/apertura/rinominazione/cancellazione di file. Per ciascun file di lavoro viene creato un registro separato, in cui sono registrate le copie dei messaggi con compiti di lettura e scrittura dei dati in quel file di lavoro, nonché gli array di dati scritti (nuovi) e gli array di dati che sono stati distrutti durante la riscrittura (scrittura di nuovi dati "sopra" ai vecchi).
Questi registri permettono sia il recupero delle nuove modifiche nei backup, sia il "rollback" del contenuto attuale al momento desiderato del passato.
Cageserver comprende circa 3100 righe di codice.

Avvio del programma del file server Cageserver
All'avvio, nella finestra di dialogo è necessario definire:
— la porta principale per l'autenticazione;
— il numero di porte per lo scambio di transazioni con i clienti autorizzati (da 1 in su, il pool dei numeri inizia dal successivo numero della porta principale).
Utilizzo della classe Cage
class cage.Cage( cage_name=»», pagesize=0, numpages=0, maxstrlen=0, server_ip={}, wait=0, awake=False, cache_file=»» )
Da questa classe vengono creati oggetti che interagiscono con i file server e contengono memoria buffer.
Parametri
- cage_name(str) — nome convenzionale dell'oggetto, utilizzato per identificare i clienti dal lato del server
- pagesize(int) — dimensione di una pagina di memoria buffer (in byte)
- numpages(int) — numero di pagine di memoria buffer
- maxstrlen(int) — lunghezza massima della stringa in byte nelle operazioni di scrittura e lettura
- server_ip(dict) — dizionario con gli indirizzi utilizzati server, dove la chiave è il nome condizionale del server (id del server all'interno dell'applicazione), e il valore è una stringa con l'indirizzo: “ip address:port” o “DNS:port” (la corrispondenza tra nomi e indirizzi reali è temporanea, può essere cambiata)
- wait(int) — tempo di attesa per la risposta dal server durante la ricezione delle porte (in sec.)
- sveglia(campo) — flag del metodo di creazione dell'oggetto (False — se viene creato un nuovo oggetto, Vero — se l'oggetto viene creato da un precedente 'sospeso' — utilizzando l'operazione di 'ibernazione', di default Falso)
- cache_file(str) — nome del file per l'ibernazione
Metodi
Cage.file_create( server, path ) – creare un nuovo file
Cage.file_rename( server, path, new_name ) – rinominare il file
Cage.file_remove( server, path) – rimuovere il file
Cage.open( server, path, mod ) – aprire il file
Restituisce fchannel numero del canale. Il parametro mod — è la modalità di apertura del file: 'wm' — monopolista (lettura/scrittura), 'rs' — solo lettura, e condiviso solo per la lettura da altri client, 'ws' — lettura/scrittura, e condiviso solo per la lettura da altri client.
Cage.close (fchannel) – chiudere il file
Cage.write (fchannel, begin, data ) – scrivere una stringa di byte nel file
Cage.read (fchannel, begin, len_data ) – leggere una stringa di byte dal file
Cage.put_pages ( fchannel ) – 'spinge' dal buffer al server tutte le pagine del canale specificato, che sono state modificate. Utilizzato nei punti dell'algoritmo quando è necessario essere certi che tutte le operazioni sul canale siano fisicamente salvate nel file sul server.
Cage.push_all () – 'spinge' dal buffer al server tutte le pagine di tutti i canali per l'istanza della classe Cage, che sono state modificate. Utilizzato quando è necessario essere certi che tutte le operazioni su tutti i canali siano salvate sul server.
Fonte: habr.com
