Newsgroup: it.comp.lang.perl
Titolo: [semi OT] Problema con refresh di grafici

Cia a tutti.
Ho fatto un cgi che riporta in via grafica tramite GD::Graph
dei dati in base a un certo range temporale.
Nello stesso CGI è presente anche un form
che permette di variare questo range.
Il problema è che quando faccio il submit (via POST)
con un nuovo arco temporale e mi viene restituita la nuova pagina,
il browser (IE 6) non aggiorna i files dei grafici,
mentre tutti gli altri dati vengono correttamente aggiornati.
L'unico modo per avere il grafico corretto
è quello di fare un refresh (F5) della pagina.
ho provato a mettere un expire per la pagina,
e anche a cancellare i files png prima di ricrearli
(hanno sempre lo stesso nome), ma non ho ottenuto risultati.
Normalmente come vengono gestite queste situazioni?
Si creano dei files temporanei con nomi random o simili?
se si, immagino serva qualche procedura
che quotidianamente cancelli questi files, giusto?
O c'è qualcosa che gestisce tutto in automatico?
Spero possiate aiutarmi.
Mille grazie

 O c'è qualcosa che gestisce tutto in automatico?
Non so.
  Raffaello

 O c'è qualcosa che gestisce tutto in automatico?
Ti consiglio di non creare *mai* file su disco (a meno che tu non abbia 
qualche particolare necessità di archiviazione/caching), perché la 
creazione di file su disco è inutile, lenta e crea una serie di 
problemi, come quelli da te descritti ed anche altri.
Semplicemente, basta creare uno script cgi ad hoc (oppure un runmode, se 
usi CGI::Application) che genera l'immagine e la manda direttamente al 
browser, senza alcuna necessità di salvarla prima su disco.
In questo modo risolvi tutti i problemi da te descritti.
Ecco come si fa, *molto* schematicamente.
Nel tuo HTML, dichiara l'immagine in questione in questo modo:
	<img src="
http://tuo_server/cgi-bin/chart.cgi
">
dove chart.cgi è uno script che genera e stampa il contenuto (binario) 
dell'immagine, in un qualche formato interpretabile dal browser (ad 
esempio png), avendo cura di specificare prima l'header corretto (questo 
è fondamentale).
Se usi GD::Graph (ma non CGI), una cosa del tipo:
	my $graph_data = [] # valorizzare come necessario.
	my $graph = GD::Graph::bars->new(320, 240);
	# ...
	print "Content-type: image/png\n\n"; # header corretto!
	print $graph->plot($graph_data)->png;
Se invece usi CGI (meglio), allora la riga di generazione dell'header 
diventa:
	print header('image/png');
Infine, se usi CGI::Application (ancora meglio di CGI nudo e crudo), 
allora puoi definirti i runmode di generazione dei grafici come metodi 
di una sottoclasse della classe principale della tua applicazione, nella 
quale avrai sovrascritto il metodo cgiapp_postrun nel seguente modo:
	sub cgiapp_postrun {
		my $self = shift;
		$self->header_props(-type => 'image/png')
	}
Ciao,
Emanuele.

 senza alcuna necessità di salvarla prima su disco.
Funziona anche con una pagina HTML abbastanza complessa che contiene
diverse immagini?
  Raffaello


Forse tempo fa a vevo provato qualcosa del genere..
Problema è che gli stessi dati che uso per fare _i_ grafici
li devo poi stampare annche in tabelle.
Quindi usando un cgi per ogni grafico,
dovrei fare le stesse estrazioni dal DB più volte.
Spero che il problema sia chiaro:
come lo si può risolvere?
Grazie a entrambi per le risposte

 come lo si puň risolvere?
Se non vuoi ripetere le query, puoi serializzarne i risultati nei dati 
di sessione server-side alla prima esecuzione, e poi recuperare i dati 
serializzati in fase di generazione dei grafici, cosa che potresti fare 
molto facilmente (in maniera trasparente) ad esempio con CGI::Session.
Oppure potresti risolvere la cosa a livello di db, popolando una tabella 
temporanea con la prima esecuzione della query, e poi leggendo i dati da 
tale tabella per la generazione dei grafici.
Ma io ti consiglierei ugualmente di provare prima come ti ho detto, e 
poi valutare se la ripetizione della query č troppo onerosa per te.
Considera che risparmi una scrittura su disco e una successiva lettura 
da disco per ogni grafico (visto che adesso generi il grafico 
on-the-fly, senza passare per il file temporaneo), cosa che costituisce 
un discreto vantaggio, soprattutto in un ambiente persistente (come 
mod_perl/Apache::Registry, FastCGI, SpeedyCGI, PersistentPerl etc.) dove 
non hai neanche l'overhead dovuto all'esecuzione aggiuntiva del 
compilatore perl. Poi dipende anche da quanto sono complesse le tue 
query, ovviamente...
Direi che in questo caso si applica l'antico adagio: "Profile. Don't 
speculate" ;-)
Ciao,
Emanuele.

 diverse immagini?
Certo!
Non ci sono problemi di sorta per quanto attiene al /funzionamento/.
(Io personalmente ho in produzione web application anche con una decina 
di grafici per pagina, tutti generati on-the-fly, senza alcun problema).
Ed anche dal punto di vista prestazionale è quasi sempre vantaggioso, 
specialmente in ambienti persistenti.
Dico /quasi sempre/ e non sempre giusto per contemplare situazioni 
particolari come quella di svetj, dove si utilizza la stessa query sia 
per il grafico che per una tabella generata nella stessa pagina (se ho 
capito bene); qui la valutazione va fatta caso per caso e dipende da 
svariati fattori (complessità della query, numero di record ritornati, 
dimensioni del grafico etc.)
Ovviamente parliamo di grafici in tempo reale, e non di grafici che si 
aggiornano raramente, caso quest'ultimo che suggerirebbe l'adozione di 
strategie di caching, come accennavo nel mio primo messaggio.
Ma secondo l'avviso comune (da me pienamente condiviso) i benefici in 
termini di semplicità e chiarezza sono sempre da preferire agli 
ipotetici benefici prestazionali.
Ciao,
Emanuele.

 	<img src="
http://tuo_server/cgi-bin/chart.cgi
">
Questa e' sicuramente una buona idea, ma di contro hai da
eseguire sul server un cgi per ogni immagine che visualizzi,
nel mio caso sono piu' di 40 ...
  Raffaello

 nel mio caso sono piu' di 40 ...
Per l'appunto, non andrei mai a scrivermi 40 file per ogni invocazione 
dello script!
Se ti fai 2 conti, la generazione delle immagini dal punto di vista 
computazionale richiede lo stesso carico nei due diversi casi; viene 
solo spostata temporalmente: tu generi tutte e 40 le immagini prima di 
rispondere al server, mentre nel mio caso la generazione di ogni 
immagine viene eseguita singolarmente, quando la richiede il browser, ma 
le due cose sono computazionalmente equivalenti (posto che si sia in un 
ambiente persistente).
Solo che nel tuo caso devi aggiungere l'overhead dovuto alla creazione 
di un file e alla successiva lettura da file per ogni singola immagine, 
cosa che nel mio caso non esiste; e non è poco, considerando che il 
disco è lento.
Considera pure che, in un ambiente persistente, in pratica non c'è 
overhead per l'esecuzione di un processo cgi (che è già istanziato, 
*compilato* e caricato in memoria).
Insomma, in definitiva tu aggiungi la creazione di un file e la lettura 
da file per ogni singola immagine, cosa che invece io non ho.
Le due soluzioni potrebbero equivalersi come prestazioni giusto in un 
ambiente non persistente, altrimenti tu hai un discreto svantaggio anche 
dal punto di vista prestazionale.
Per concludere, nei miei messaggi mi sono limitato a suggerire quella 
che è la pratica migliore per la gestione di questi casi; non sono io 
che lo dico, beninteso, basta consultare un qualsiasi manuale di 
programmazione cgi:
http://www.oreilly.com/openbook/cgi/ch06_02.html
leggi il paragrafo: "Inserting Multiple Dynamic Images", esattamente 
quello di cui parliamo noi, e guarda come lo risolve.
Poi ognuno è libero di adottare le soluzioni che preferisce e di 
coltivare il proprio senso estetico.
E da parte mia faccio di tutto affinché queste libertà vengano 
preservate ;-)
Ciao,
Emanuele.

 molto facilmente (in maniera trasparente) ad esempio con CGI::Session.
Quest'ultima opzione sembra interessante:
io normalmente butto tutti i dati che mi servono
dentro un hash o dentro alcuni array:
l'ideale sarebbe poter passare queste variabili
agli script che generano i grafici,
in modo da non dover riestrarre tutto dal db,
dato che le query, a seconda dell'arco temporale scelto,
sono un po' pesanti.
Ho visto che CGI::Session puň salvare questi dati
(
http://search.cpan.org/~sherzodr/CGI-Session-3.95/Session/Tutorial.pm#STORING_DATA_IN_THE_SESSION
)
ma devo riprendermi in mano parte degli script.
Per ora anch'io ho adottato il metodo del nome del file random,
con un job che a mezzanotte ripulisce tutto.
Questo, a parte, eventualmente, le performance, a me non crea problemi,
trattandosi di CGI utilizzati solo in orario lavorativo.
Ciň non toglie che vorrei trovare un modo piů elegante di lavorare.
Grazie ancora.
   Stefano