[phpBB Debug] PHP Warning: in file [ROOT]/ext/tas2580/privacyprotection/cron/task/anonymize_ip.php on line 83: A non-numeric value encountered
Inoffizielles deutsches Xbase-Forum • Phantomsatz
Seite 1 von 1

Phantomsatz

Verfasst: Di, 28. Apr 2009 17:13
von Manfred
Hi,

mir ist gerade etwas sehr interessantes passiert. Ich sperre in einem Menue 2 DB. Das ist auch richtig so. Allerdings habe ich einen Denkfehler gemacht, von dem ich aber nicht 100% überzeugt bin, dass es einer war. In der 1.DB wird ein Satz gesucht. Wenn der gefunden wurde, wird in der 2.DB (Relation) die Ergänzung gesucht. Wenn in der 2.DB etwas gefunden wurde, ist alles klar, wenn aber nichts gefunden wurde, dann kommt jetzt der Fehler: Ich sperre pauschal beide DB. Einmal den gefundenen Satz und einmal wohl den Phantomsatz, weil in der 2.DB nichts gefunden wurde.
Wenn jetzt eine andere Station in der 2.DB etwas anhängen will, gibt es einen NetError().

Ich überlege die ganze Zeit, ob es richtig ist, dass es einen NetError() beim Appenden gibt. Ich dachte es wird generell ein leerer Satz angehängt und der wird automatisch gesperrt. Wenn nun die DB am Ende steht, weil nichts gefunden wurde, wie kann denn dann der Sperrvorgang der einen WS für den Appendvorgang der anderen WS einen Fehler erzeugen?

Re: Phantomsatz

Verfasst: Di, 28. Apr 2009 17:24
von Jan
Manfred,

bevor ich jetzt wieder irgendwas in Deine Worte interpretiere, was Du garnicht gemeint hast: Eine Verständnisfrage. Wenn ich das so lese hört sich das an, als wenn Du die beiden DBs getrennt "verarbeitest". Andererseits benutzt Du das Wort Relation. Kannst Du das bitte etwas präzisieren? Ist das nun eine DBSetRelation() bzw. SET RELATION oder eine manuelle Mitführung?

Jan

Re: Phantomsatz

Verfasst: Di, 28. Apr 2009 17:35
von Manfred
Jan,

sehr gut. Was ich meine ist, dass ich eine Relation nachgebaut habe. Ich erwähne das nur, damit man sofort verstehe, was ich meine und tue. Also eigentlich nur ein Dbseek() mit eigener Hand zwischen den DB. Keine automatische Führung wie bei der Relation. Aber darauf kommt es nicht an. Es ist nur das Sperren eines Satzes, der gar nicht vorhanden ist, aber das Appenden an der Datenbank verhindert.

Re: Phantomsatz

Verfasst: Di, 28. Apr 2009 17:38
von Martin Altmann
Manfred,
und warum sperrst Du einen nicht vorhandenen Satz?
Sperre doch nicht beim Suchen (bzw. Finden), sondern erst beim Schreiben!
Und vor dem Schreiben vergleichst Du die Werte, die dort gespeichert sind, mit denen, die Du vor dem Bearbeiten gelesen hattest - ist da ein Unterschied, hat bereits jemand (zeitgleich) mit Dir geändert.
Oder Du sperrst halt den gefundenen Datensatz, bis eine Änderung zurückgeschrieben wird oder der Datensatzzeiger weiter bewegt wird - aber halt den gefundenen!

Viele Grüße,
Martin

Re: Phantomsatz

Verfasst: Di, 28. Apr 2009 17:45
von Jan
Manfred,

Danke für die Ergänzung. Im Pronzip kann in dem Fall nur unterschreiben, was Martin gesagt hat. Ich verstehe nicht ganz, wie Du einen nicht gefunden Satz sperren kannst bei einer manuellen Relation? Du schreibst ja selber, daß Du passend zum Ergebnis in der 1. DB in der 2. suchst. Aber wieso sperrst Du da, wenn nichts gefunden wird?

Jan

Re: Phantomsatz

Verfasst: Di, 28. Apr 2009 17:51
von Manfred
Hi Martin,
Martin Altmann hat geschrieben:Manfred,
und warum sperrst Du einen nicht vorhandenen Satz?
Weil ich zu dem Zeitpunkt dachte, ich hätte es richtig gemacht. Dem war aber wohl nicht so.
Sperre doch nicht beim Suchen (bzw. Finden), sondern erst beim Schreiben!
Ich sperre, sobald der angezeigte Satz am Bildschirm geändert wird. Da weiß ich ganz genau, dass KEINER mir dazwischen funken kann, was bei dieser Anwendung durchaus passieren kann.
Und vor dem Schreiben vergleichst Du die Werte, die dort gespeichert sind, mit denen, die Du vor dem Bearbeiten gelesen hattest - ist da ein Unterschied, hat bereits jemand (zeitgleich) mit Dir geändert.
dazu bin ich im Moment zu faul. :(
Oder Du sperrst halt den gefundenen Datensatz, bis eine Änderung zurückgeschrieben wird oder der Datensatzzeiger weiter bewegt wird - aber halt den gefundenen!

Viele Grüße,
Martin
Das System klappt ja jetzt prima. Worauf ich hinaus wollte, war die Frage ob das überhaupt so logisch ist, das ein gesperrter nichtgefundener Satz ein Append verhindert. Wenn dem so ist, dann verstehe ich die Technik nicht wirklich. Bzw. warum kommt keine Fehlermeldung vom Laufzeitsystem, dass gar nichts zu sperren da ist?

Re: Phantomsatz

Verfasst: Di, 28. Apr 2009 17:52
von Tom
Tut mir leid, aber ich bekomme ums Verrecken keinen Laufzeitfehler, wenn ich den Phantomsatz einer Tabelle sperre und dann ein DbAppend() versuche. Übrigens auch nicht, wenn ich irgendeinen anderen Satz sperre.

Re: Phantomsatz

Verfasst: Di, 28. Apr 2009 17:54
von Manfred
aha,

das ist ja interessant. Dann werde ich das Dingen nochmals in den Ursprungszustand versetzen und mit dem Debugger nachsehen, was denn dann bei mir passiert, dass es eben einen Fehler gibt.

Re: Phantomsatz

Verfasst: Di, 28. Apr 2009 18:36
von Manfred
Hi Tom,

also es sieht so aus. In der DB sind 31208 Datensätze. Der Phantomsatz ist der 31209 und ich kann exact im Debugger sehen, dass der gesperrt wird. Wenn ich dann im Debugger den Appendversuch ansehe, dann steht die DB genau auf dem 31209 und springt dann in die Errorsys um hier:

Code: Alles auswählen

CASE oError:genCode == XPP_ERR_APPENDLOCK .AND. ;
                       oError:canDefault
                       RETURN(.F.)
zu landen.

Sobald ich dann an der anderen WS das Ändernmenue verlasse und alle Sperren aufhebe, kann angehängt werden.
Watt nu?

Re: Phantomsatz

Verfasst: Di, 28. Apr 2009 20:21
von Martin Altmann
Zeige doch mal die Zeile, in der Du sperrst...

Re: Phantomsatz

Verfasst: Di, 28. Apr 2009 20:50
von AUGE_OHR
hi,
Manfred hat geschrieben:also es sieht so aus. In der DB sind 31208 Datensätze. Der Phantomsatz ist der 31209 und ich kann exact im Debugger sehen, dass der gesperrt wird.
Ich denke hier liegt ein Irrtum vor. Der "GhostRecord" ist LastRec()+1, was aber NICHT bedeutet das es physikalisch auch
die Recno() = LastRec()+1 ist. Vielmehr ist ein "GhostRecord" immer LastRec()+1.

Beispiel : Record = 99
A -> Goto LastRec()+1 -> Edit -> "GhostRec" = 100
B -> Append blank -> Record 100
A -> "GhostRec" -> 101
A -> Append blank -> Record 101

egal was "andere" mit der DBF machen ist der "GhostRec" immer LastRec()+1 was bedeutet er liegt
"ausserhalb" des Datenbank Bereich.

Re: Phantomsatz

Verfasst: Di, 28. Apr 2009 20:52
von Manfred
Meinst Du das hier Martin?

Code: Alles auswählen

********************************************************************************
/// <summary>
///  <para>
///     <bold>sperrt den aktuellen Satz der ZielDb</bold>
///  </para>
///  <para>
///     <bold>oZiel:</bold>wenn eine andere DB benutzt werden soll (default = self)
///  </para>
/// </summary>
METHOD datenbank:satzSperren(oZiel)
       LOCAL cDatum     := DToC((oZiel:nArea)->spdatum)
       LOCAL cPrg       := TRIM((oZiel:nArea)->spprg)
       LOCAL cUser      := TRIM((oZiel:nArea)->spuser)
       LOCAL cStation   := TRIM((oZiel:nArea)->spstation)
       LOCAL cZeit      := (oZiel:nArea)->spzeit
       LOCAL cText      := "ACHTUNG!!!" + CHR(13) +;
                           "Der Datensatz kann nicht gesperrt werden." + CRLF +;
                           "Er wurde an der Station: " + cStation + CRLF +;
                           "vom Benutzer: " + cUser + CRLF +;
                           "am: " + cDatum + CRLF +;
                           "um: " + cZeit  + CRLF +;
                           "vom Programm: " + cPrg + CRLF +;
                           "gesperrt." + CRLF + CRLF + ;
                           "SOLL DER VERSUCH WIEDERHOLT WERDEN?" + CRLF + CRLF +;
                           "Datenbank: "
       LOCAL cText2      := ""
       LOCAL lErfolg     := .T.
       LOCAL nVersuche   := 0
       LOCAL nSatzNummer

       MEMVAR oMessage
       MEMVAR oSysPara

       DEFAULT oZiel TO self

       nSatzNummer := (oZiel:nArea)->(Recno())
       DO WHILE .T.                                                             // Schleife dient nur dem zweck, falls der User es nochmals versuchen möchte, oder muß
          nVersuche++                                                           // es werden mehrere Versuche gegönnt
          IF (oZiel:nArea)->(DbRLock())                                         // Satz konnte gesperrt werden
             (oZiel:nArea)->spDatum   := Date()
             (oZiel:nArea)->spPrg     := oSysPara:cProgrammName
             (oZiel:nArea)->spstation := oSysPara:cNetName
             (oZiel:nArea)->spuser    := oSysPara:cUserName
             (oZiel:nArea)->spzeit    := Time()
//             (oZiel:nArea)->(DbSkip(0))                                         // hier muß auf jeden FAll ein Dbskip(0) hin. (25.08.2008)
             (oZiel:nArea)->(DbGoto(nSatzNummer))                               // das gibt sonst Murks nach einem                       .
             EXIT
          ENDIF
          IF nVersuche > 2                       // es wurde mehrmals versucht. Wie of muß die Erfahrung mit sich bringen
             cText2 = Upper((oZiel:nArea)->(Alias())) + CHR(13)+;
                      "Sperrversuche: " + Alltrim(Str(nVersuche))
             IF oMessage:anzeigen(cText + cText2,.T.,"J")
                LOOP
             ELSE
                lErfolg := .F.
                EXIT
             ENDIF
          ENDIF
       ENDDO
RETURN lErfolg

Re: Phantomsatz

Verfasst: Di, 28. Apr 2009 20:55
von Martin Altmann
Yup!
Du rufst DbRlock() ohne Parameter auf - also wird der aktuelle Datensatz gesperrt! Hast Du denn davor einen Append blank gemacht?
Was passiert, wenn Du die Datensatznummer, die Du sperren willst, explizit angibst?

Viele Grüße,
Martin

Re: Phantomsatz

Verfasst: Di, 28. Apr 2009 20:59
von Manfred
Ja,

richtig, so soll es ja sein. Das ist nur der Sperrmechanismus. Ein Append sieht so aus:

Code: Alles auswählen

********************************************************************************
METHOD datenbank:satzNeu(oZiel,lSchreiben)
       LOCAL lErfolg    := .T.

       MEMVAR oMessage
       MEMVAR oSysPara

       DO WHILE .T.
          (oZiel:nArea)->(DbAppend())
          IF NetErr()                                                           // es wurde ein Fehler zurückgegeben
// geht das evtl. noch eleganter?
             IF oMessage:anzeigen("ACHTUNG!!! Es konnte kein neuer Datensatz an die Datei: " + ::cDbank + ;
                                  "angehängt werden. Nochmal versuchen?",.T.,"J")
                LOOP
             ENDIF
             lErfolg := .F.
          ENDIF
          (oZiel:nArea)->spdatum   := DATE()
          (oZiel:nArea)->spprg     := oSysPara:cProgrammName
          (oZiel:nArea)->spuser    := oSysPara:cUserName
          (oZiel:nArea)->spstation := oSysPara:cNetName
          (oZiel:nArea)->spzeit    := Time()
          IF lSchreiben
             (oZiel:nArea)->(DbCommit())
          ENDIF
          EXIT
       ENDDO .T.
RETURN lErfolg

Re: Phantomsatz

Verfasst: Fr, 17. Jul 2009 7:32
von AUGE_OHR
Tom hat geschrieben:Tut mir leid, aber ich bekomme ums Verrecken keinen Laufzeitfehler, wenn ich den Phantomsatz einer Tabelle sperre und dann ein DbAppend() versuche. Übrigens auch nicht, wenn ich irgendeinen anderen Satz sperre.
aber ich jetzt mit der v335 und FOXCDX ...

Code: Alles auswählen

GOTO LASTREC()+1
nRec := RECNO()
IF RLOCK
    REPLACE
    UNLOCK -> crash  
auch wenn ich es mit DbrLock(nRec) versuche bekomme ich bei DbrUnlock(nRec) einen Fehler ... :-k

hm ... sehr merkwürdig ... das kann ja nicht sein ...
ALIAS ist richtig und Errorlog sagt mir auch das sonst alles klar ist ... und trotzdem ...

achso, weil das UNLOCK ja nicht ging, dachte mir lass es doch einfach erstmal ... bis zum DbAppend() -> crash :shock: