Newsgroup: it.comp.www.php
Titolo: bzopen('http:// .....

Salve.
Ho problemi con la bzopen() e file remoti.
Per i file gz io faccio così:
$fd=gzopen('http://...../file.gz','r');
echo fgets($fd);
e stampo tranquillamente il file già decompresso senza dovermelo
scrivere su disco o mettere in un buffer (da evitare per file grandi)
per i file bz2 sembrerebbe che questa sintassi non venga accettata, o
meglio, facendo un tracciamento il file localmente nel filesystem e
chiamato file.bz2 nella directory "http://..../"
Come si risolve la situazione?
Ciao
01


ho controllato meglio. effettivamente mi sbagliavo, la richiesta http
avviene con successo (ho visto i log del server), ma comunque non
scarica il file.
Io ho notato, dal trace, che al momento del bzopen avviene questo
(strace test1.php su linux):
* connect(4, {sa_family=AF_INET, sin_port=htons(21),
sin_addr=inet_addr("64.50.236.52")}, 16) = -1 EINPROGRESS (Operation
now in progress)
* open("/tmp/phpOM4hHX", O_RDWR|O_CREAT|O_EXCL, 0600) = 5
il 4 è il file descriptor per la connessione mentre il 5 è il file
descriptor del file temporaneo che crea la bzopen().
Nota: questo file mi rimane sempre vuoto
Per la fgets:
* read(5, ""..., 4096)                    = 0
ovvero legge dal file descriptor 5 e l'output è la stringa vuota (le
"")
infine:
close(5)                                = 0
munmap(0x7f5241d58000, 4096)            = 0
close(4)                                = 0
close(5)                                = -1 EBADF (Bad file
descriptor)
unlink("/tmp/phpOM4hHX")                = 0
ovvero:
chiudi il file temporaneo;
rilascia la memoria allocata per quel file
chiudi la connessione http
chiudi il file temporaneo (non so perchè prova a richiuderlo)
elimina il file temporaneo
un var_dump di feof restituisce false, il che indica che il file non è
terminato, però non sono riuscito a vedere niente nel trace
Idee?
Ciao
Matteo

Come si risolve la situazione?
bzdecompress(file_get_contents("http://...")).
Oppure apri un file temporaneo, ci scrivi dentro da fopen normale,
rewind() in modo da flushare i buffer e lo decomprimi.
Tanto, avrai visto, anche bzopen non e' che faccia diversamente...
Leonardo
-- 
The cock doth craw, the day doth daw,
the channerin' worm doth chide:
gin we be mist oot o' oor place,
a sair pain we maun bide.


Quello che non capisco che fa/non fa bzopen/gzopen (ma anche
semplicemente fopen) è se prima scarica TUTTO il file (chiudendo
potenzialmente la connessione http) e con una fgets() mi restituisce
solo una riga, oppure se scarica solo i byte che gli servono,
richiesta per richiesta e se dopo 10 righe do un fclose() non mi
scarica altro (la cosa sarebbe alquanto utile per file grandi).
Matteo

scarica altro (la cosa sarebbe alquanto utile per file grandi).
Sospetto che faccia semplicemente buffering: un writer process che prende
i dati da HTTP e li scarica sul file, e un reader process che decomprime,
e se necessario segnala al writer di prendere qualcos'altro... il file in
/tmp e' usato come ring buffer.
Ma senza visibilita' sullo stato dei puntatori di (de)compressione, mi sa
che questo tu non lo possa fare. Non sai quanti byte compressi sono stati
usati per darti un certo output, quindi non puoi produrne di nuovi.
Forse puoi fare qualcosa con le pipe, pero' (apri il file remoto in fopen
e metti l'output in una pipe, e rileggi con gzread... non so se in PHP si
possa fare, e quanto facilmente).



si, ci stavo pensando pure io... ora me la studio un po'.
Matteo


Questa funziona e mi garantisce un certo parallelismo di elaborazione
e download.
<?php
$bz="http://........./file.bz2";
posix_mkfifo("/tmp/fifo",0666);
if (pcntl_fork() == 0) {
  $fifo=fopen("/tmp/fifo","w");
  $fd=fopen($bz,'r');
  while(!feof($fd))fwrite($fifo,fread($fd,4096));
  fclose($fd);
  fclose($fifo);
  exit;
}
$fifo=bzopen("/tmp/fifo",'r');
while(!feof($fifo)){
  echo fgets($fifo,4096);
}
fclose($fifo);
unlink("/tmp/fifo");
?>
Devo usare più spesso i fork.
Matteo