[linux-l] Re: [linux-l] Transaktionen? und Prozessesnapshots für alle und jeden und überall und jederzeit

Jan Krueger jk at microgalaxy.net
Di Aug 26 11:25:01 CEST 2003


On Wednesday 20 August 2003 09:04, Steffen Dettmer wrote:
> * Jan Krueger wrote on Wed, Aug 20, 2003 at 08:30 +0200:
> > On Wednesday 20 August 2003 01:58, Steffen Dettmer wrote:
> > > > > Natürlich auch wieder doof,
> > > > > weil nicht mehr alle Daten mit der Umwelt konsistent sein müssen
> > > > > (hat man bei DBs natürlich auch, aber sieht das oft besser).
> > >
> > > Schon ein kooperatives suspend-to-disk ist nicht so ganz einfach.
> >
> > Also fasse man voneinander abhängige Prozesse zusammen
>
> Ja, plus Umwelt :)

Um sie sich dann auf dem Holo-Deck anschauen zu können :)

> > Der Prozeß ist für sein error-handling selbst verantwortlich.
> >
> > dann ist der mensch für das errorhandling selbst verantwortlich und muß
> > sich entsprechend zurechtfinden. Das ist nun mal so wenn man snapshottet.
>
> Wie soll man das programmieren? Nimm mal an, Du hast sowas wie
>
> while(...) {
> 	accept(fd...)
> 	syslog(LOG_AUTHPRIV, "connection from ...")
> 	if ( send (fd, ...) == -1 ) {
> 		syslog(LOG_ERR, "send failed");
> 		exit (1);
> 	}
> }
>
> oder sowas. Geht nicht per snapshot, weil dann exit 1 gemacht
> wird. Wie also den Fehler behandeln? Ich mein, es kann dann sein,
> das nach einem memcpy die (im Code "eben" geholten) Daten falsch
> sind!

> > Das OS könnte dann höchstens die Hilfe geben, ein signal, hallo
> > prozeß du warst gesnapshottet.
>
> Dann muß man da ein flag setzen. Was macht man dann?
> Sicherheitshalber (weil Zustand ja nicht bekannt) geht man am
> besten raus, bis zurück an den Anfang auf Applikationslevel,
> initialisiert alles neu, damit man sich drauf verlassen kann.
>
> Geht auch ganz gut per exit :-)

Überprüft sämtliche handler auf ihre gültigkeit, beantragt sie gegebenenfalls 
neu, und macht dann halt weiter.

> > Also, wenn man ein Programm schreibt für ein OS, von welchem
> > man weiß, daß es Prozesse einschläfern kann,
>
> einschläfern ist ja auch weniger das Problem, denk ich. Bloß mit
> Folgefehlern (beispielsweise merkwürdigen Socketverhalten, was
> normalerweise schlicht und ergreifend mit exit quitiert wird)
> klarzukommen, ist vielleicht schon schwieriger...

Socket neu einrichten, fertig.

> > dann kann man auch ein entsprechendes Error-Handling dafür
> > installieren, besonders wenn man ein signal bekommt: du hast
> > schlafen müssen, überprüfe dich und deine Umgebung.
>
> Stell Dir das doch mal im Code vor. Im Prinzip muß doch nach jeder
> Zeile (man kann ja immer snapshoten):
>
> if (global.flag.snapshotrestored) {
> 	/* alle Daten checken */
> }
>
> Ach so, da entstehen auch viele Zeilen, da muß man natürlich auch
> checken :)

Na momentchen bitte, Ein heutiges Programm fragt doch auch nicht nach jeder 
Zeile of es ein SIGTERM/SIGUSR1 oder so bekommt, sondern dafür gibt es einen 
signalhandler der halt immer wieder mal überprüft wird oder auch nicht, was 
im fall von SIGKILL auch ziemlich egal wäre.

> > So ginge es doch.
>
> Ja, aber bleibt schwierig. Einen Prozeß einfach zu starten ist
> hingegen recht einfach.
>
> > Ähm, das Signal hat einer in weiser Vorraussicht ja schon eingebaut:
> > SIGCONT   19,18,25            Continue if stopped
> >
> :-)
> > snapshotted und wieder geladen ist halt dann eine
> > Interpretation von stopped.
>
> Ja, klar, könnte man machen. Fragt sich eben nur, ob das viel
> Sinn macht. So ähnlich funktionierte ja so ein Perl compiler:
> einfach memory dumpen (gut, sind paar MB, aber schnell ist's),
> beim Start dann laden.

na super! Wenn man mozilla so starten könnte, oder openoffice :)

> > [...]
> >
> > Langsam ist nicht egal.
>
> Warum nicht? Wenn der Prozeß "hängt", und man ein paar Stunden
> später einen gdb einhängt, ist doch egal, ob der 5 oder 30
> Sekunden braucht? Außerdem ist der gdb nicht langsam, denke ich.
> Wenn Du was ohne debugsymbole hast, ist er verdammt fix. Gut,
> möchte man nicht, also muß er eben paar MB symbole laden etc.
>
> [hängende Signalhandler]
>
> > > Na ja, siehe eben oben!
> >
> > Na, ohne sleep!?
>
> häh? Dann nimmste eben select. sleep paßt aber: man möchte ja
> Prozeß bleiben, aber keine Rechenzeit verbrauchen. Dieser
> Prozeßstatus heißt sleep :) Paßt doch, oder?
>
> > > Yep, geht mir genauso. Das ist das schöne an Unix: man denkt
> > > lange drüber nach und kommt auf gleiche Ideen. Bei Windows
> > > ist das eher anders. Dann fragt man sich eher, warum man
> > > ausgerechnet *das* nicht auch noch abscheiben konnte und
> > > installiert sich ein cygwin ;)
> >
> > Und während der windows-Admin-Kollege sein VisualStudio started
> > hat man das bash-script mit vi schon fertig geschrieben
>
> ... und den gdb am Start :-) SNCR ...

... nach dem snapshot :)

> > > > Wegen der besonderen Eigenheiten von flash-speicher welche bei
> > > > direct IO nicht berücksichtigt werden.
> > >
> > > Woher weißt, was meine Applikation da macht?
> >
> > Dös wois i net. Ich wüßte es, wenn sie kein DirectIO macht -> read() und
> > write().
>
> Ja, in beiden Fällen, oder?!
>
> // system buffered I/O
> int sysfd = open("/tmp/file", 0);
> write(sysfd, "some data", 10);
> close(sysfd);
>
> // raw I/O
> int rawfd = open("/dev/raw/0", 0);
> write(rawfd, "some data", 10); // dauert...
> close(rawfd);
>
> Ist doch genauso, nur das open ist anders, oder?

Also rawIO ist doch sinnlos. Sag ich doch :)


> > Dies würde mir ein Gefühl der Sicherheit geben, ich könnte auf
> > die Anwendung und deren IO Unix-Einfluß nehmen :)
>
> Geht immer, man kill :-)
>
> Nee, klar, wenn die ANwendung Spezialverhalten hat, muß sie ggf.
> ne Configoption zum Abshclaten haben. Sprich: optionales rawIO,
> hat Oracle ja auch :)
>
> > Wenn ich mir die embedded Linux-Entwicklungen so anschaue (zb.
> > eben JFFS oder JFFS2) dann nutz man auch weitestmöglich
> > abstraktionen weil man sich ja damit nicht auseinandersetzen
> > will, sondern man will eine anwendung schreiben.
>
> Ja, sicherlich, ich würde auch lieber C++ schreiben, aber da ist
> nun mal weniger Speicher, da kann man oft nicht "schön" arbeiten.
>
> SomeElement *
> Utility::searchRecursive(SomeList list, SomeElement element)
> {
> 	if (list.isEmpty()) {
> 		return NULL;
> 	}
> 	if (list[0] == element) {
> 		return list[0];
> 	}
> 	return searchRecursive(list.slice(1, list.size()), element);
> }
>
> ist bei embedded (gut, bei PCs oft auch :-)) absolut tötlich:
> jeder call benötigt liste-1*element (plus Verwaltungsdaten) auf
> dem Stack. Geht einfach nicht.
>
> Wenn Du nur noch 300 byte frei hast, paßt da ein jffs sicherlich
> schlecht rein ;) Und  8KB mehr speicher (bzw. dann 1MB ;))
> kosten bei *jedem* Gerät, also haben die den zusätzlichen Chip
> erstmal nicht.
>
> > > Er formuliert sie auf 99.9% von 24/7 um. Bleibt über eine Minute
> > > am Tag. Verfügbarkeiten von 99.9% sind meist ausreichend,
> > > zumindestens für das, was ich mache, in jedem Fall.
> >
> > Ja, klar. Auch bei dem was ich mache.
>
> Yo.
>
> > > ? Nee... Wenn jemand eine Datei liest, schreibt und nach 3
> > > Stunden nochmal einen Block davon neu schreibt (also einen
> > > exklusiven Lock hat), kann logischerweise 3 Stunden niemand
> > > anders die Datei lesen, weil er ja nicht wissen kann, ob der
> > > erste geschriebene Block commitet wird oder nicht. Man könnte
> > > natürlich noch "views" dazunehmen, daß der andere dann die Daten
> > > sieht, die es mal waren. Wird natürlich auch wieder teuer, weil
> > > man dann alle View-Daten speichern muß (was natürlich jede
> > > Datenbank  - außer vielleicht mySQL und "kleine" - kann, wo wir
> > > wieder beim Thema wären ;)). Wenn beide schreiben wollen, muß auf
> > > jeden Fall sequentialisiert werden, einer kann ja nur.
> >
> > Eben. Diese beiden verhalten sich wie ein einziger. und der
> > kann immer, weil er ja der einzige ist, halt intern doppelt.
>
> ? Jedenfalls muß der andere eben 3 Stunden einfach nur warten...

Worauf denn? er hat doch ne jederzeit identische kopie auf der er arbeiten 
kann.

>
> > Ok, es gibt augenscheinlich sehr komplizierte Transaktionen
> > spätestens dann, wenn mehr und mehr externe Systeme eingebunden
> > werden.
>
> Na ja, immer, wenn man auf komplexen Datenstrukturen einfach
> arbeiten möchte. Da reichen schon vier Tabellen.
>
> > Doch wenn das so kompliziert und damit schwer beherrschbar
> > wird, ist vielleicht das gewählte Modell "Transaktion" das
> > falsche und man hätte etwas besser geeignetes wählen sollen.
>
> Nein, ich denke eher, wenn die Thematik so komplex ist, gibt es
> eben keine noch einfachere Lösung.

Vielleicht ist diese Komplexität gar nicht Notwendig würde man ein anderes 
Modell nehmen?

> > > Physiker würden sagen: "der Zustandsvektor ist superpositiv
> > > und kollabiert bei commit".
> >
> > Des Bundeskanzlingers Katze :)
>
> Genau! BTW, wie geht's ihr eigentlich?? Hab noch nicht
> nachgeguckt, vielleicht stirbt sie ja dabei ;)

Der letzte der nachgeschaut hat konnte nicht mit bestimmtheit sagen ob sie 
noch lebt oder nicht...

> > > Wenn's superpositiv ist, bis zu nicht-abzählbar-unendlich viele,
> > > würde ich mal raten, aber kenn ja Dein Atom nicht persönlich ;)
> >
> > mein Gigabyte-Atom hat 2^(Anzahl bits) zustände ;)
>
> Dann ist es eben nicht super-positiv :)
>
> > + diejenigen zustände, die zutreffen wenn man gerade nicht hinschaut.
> >
> > also insgesamt 3^(Anzahl bits)
> > wobei ich eben unterstelle, daß es nur diese 3 Zustände (0, 1, beides
> > gleichzeitig) gibt.
>
> Yo, eben. Kann aber auch sein, daß es zu 25% 0 und zu 75% 1 ist.
> Die Wahrscheinlichkeiten sind dann oft wieder beliebig, und damit
> unendlich viele Zustände in der Superposition, und
> unendlich^(Anzahl bits) ist recht groß :)

Ja, innerhalb des dritten Zustands, weil 25% 0 und 75% 1 auch beides 
gleichzeitig ist. Was ist mit den Zuständen <0 und >1?
Sind also auch quantencompßuter unvollkommen?

> > Das zeigt wie unvollkommen Computer heutzutage sind, weil sie
> > nur 2 Zustände berücksichtigen.
>
> Also doch Quantencomputer :)
>
> > Ok, wir machen keine halben Sachen und verarbeiten Gigabyteatome am
> > Stück: putDataWithEnourmusSpeed( /path/to/bla, data)
>
> Meistens hast Du ja nur 100 byte zu schreiben. Außerdem wolltest
> Du doch gerade keine Blöcke mehr? So muß ja jeweils ein GB
> gelockt werden! Ist ja noch teurer :)
>
> > > Versteh ich nicht. Wieso merkt die Hardware überhaupt was von
> > > directIO?! Hier wird ja eben ein read oder write Kommando
> >
> > Schon, nur halt nicht das read() und nicht das write() welches man sich
> > mit man read
> > oder
> >  man write
> > anschauen kann, weil diese eben nicht direct sind
>
> Weißt Du doch nicht. Kann sein, daß Du in ne Datei, ne FIFO,
> einen Socket schreibst, aber auch auf ein Terminal (/dev/tty
> geöffnet) oder ein Gerät (/dev/sg0) - oder eben directIO
> (/dev/raw/0). Sind alles nur Files :-)

Dann gibt es keinerlei Vorteil gegenüber einem File wenn man read und write 
benutzt. Sag ich doch. directio ist sinnlos.

> > Und genau diese implementieren wir in Hardware.
>
> Dann merkt die Hardware trozdem nicht, wer das aufruft :)

retc = write(fd, offset, data, "mein name is oracle, write faster!");
print( retc );

"oracle unknown, write delayed."

Gruß
Jan

> oki,
>
> Steffen





Mehr Informationen über die Mailingliste linux-l