AVANTI-W: Job-Uebergabe
Thomas Berger
ThB.com at t-online.de
Di Mär 31 20:40:37 CEST 1998
ve at buch.biblio.etc.tu-bs.de wrote:
>
> Liebe Frau Koczian,
>
> > ich habe mit einem eigentlich recht primitiven Avanti-Klienten
> > (Perl-Skript) ziemlich gekaempft und bin jetzt zu folgender Vermutung
> > vorgedrungen:
> >
> > Konstruktionen der Art (S ist ein Socket)
> >
> > print S "& c:\\allegro\\ParDir\n";
> > print S "$befehle\n";
> > print S "@ DB=db ID=user/PASS\n";
> > print S "AVANTI:EOJ";
> >
> > gehen schief - haengt man dieselben Strings aber aneinander:
> >
> > print S "& c:\\allegro\\ParDir\n$befehle\n@ DB=db ID=user/PASS\n";
> > print S "AVANTI:EOJ";
>
> > dann klappt derselbe Auftrag. Aber: die erste Variante kann auch
>
> Man sollte grundsaetzlich den gesamten Auftrag in einem Stueck
> uebergeben (allein schon um den TCP/IP-Overhead zu reduzieren). Dies
> geht am Besten, wenn die Befehle zuerst in eine interne Variabel
> gelangen und diese dann mit
> "print S $Variable;"
> verschickt wird.
Hm.
Was die Beispiele unterscheidet, ist die Bufferung des
print-Statements: Standardmaessig erfolgt die Ausgabe auch
auf Socktets in perl unter dem Paradigma interaktiver IO,
d.h. nach jedem print-Statement wird der Inhalt des Buffers
uebertragen.
Beeinflussen laesst sich dies ueber die spezielle Variable $|,
die jeweils fuer den aktuell select-eten Filehandle gilt:
$savefh = select S; $| = 0; select($savefh);
stellt die IO auf gebuffert um. Dann darf man aber nicht
vergessen, nach dem letzten print den Buffer zu flushen:
$savefh = select S; $| = 1; print ""; $| = 0; select($savefh);
Was Frau Koczian beobachtet, ist ein Problem, das letzten
Sommer eigentlich durch die Einfuehrung von "AVANTI:EOJ"
geloest worden ist. Dadurch kann naemlich avanti bestimmen,
wann der Job zuende ist (wer haette das gedacht :-), vorher
hat es geraten: wenn gerade zufaellig keine Daten mehr
auslesbar waren (je schneller der Server und je langsamer
der Client...), wurde der (unvollstaendige) Job als beendet
angesehen, dementsprechend sinnlos (keine Angaben zur Datenbank
etwa) abgearbeitet und der restliche Job, der inzwischen
angekommen war, gab dann erst recht Probleme.
In LANs wird mit sehr grossen Blockgroessen gearbeitet,
in WAN-Verbindungen sind diese u.U. wesentlich kleiner.
Auch gebufferte IO (oder ein einzelnes print-Statement)
schickt nicht unbedingt alles auf einmal ab, sondern bei
grossen Jobs (>8k etwa) naturgemaess in mehreren Portionen.
Insofern halte ich es fuer zwingend, dass avanti auch unter
Frau Koczians Bedingungen funktioniert.
> Die Unterschiede zwische Avanti-W und dem Dienstprogramm erklaeren
> sich durch die ausgefeiltere Version der TCP/IP Schnittstelle in
> Avanti-W (asynchron). Aus internen Gruenden konnte dies nicht in das
> Systemprogramm uebernommen werden (dort und auch in den
> UNIX-Varianten: blockierende Sockets).
> Dies muß man leider hinnehmen.
Obige Geschichte hat zunaechst einmal nichts mit blockierenden
oder asynchronen Sockets zu tun.
Asynchrone Sockets sind nicht das Gegenteil von blockierenden
Sockets. Vielmehr sind asynchrone Sockets der Versuch von $Bill
in nicht-multitaskingfaehigen Betriebssystemen (WfW 3.11)
gewisse Grundfunktionalitaeten fuer die Arbeit mit "normalen"
Sockets zu retten: Wenn man keinen Prozess abspalten kann,
um die IO asynchron zum Hauptprozess zu regeln, muss man
auf Systemniveau "asynchrone" Signalhandler und IO-Buffer
installieren. Dies ist ein Geschaeft mit vielen vielen
Fallstricken wg. reentrancy.
Unter Berkeley Sockets (UNIX) wie auch unter Win32 besteht
die Moeglichkeit, mit nicht-asynchronen, nicht-blockierenden
Sockets zu arbeiten, dafuer gibt es select(), uebrigens auch
in perl (nicht zu verwechseln mit dem select() in obigen
Beispielen uebrigens).
Viele Gruesse
Thomas Berger
Mehr Informationen über die Mailingliste Allegro