Datenbank synchronisieren

Themen zum Programmieren, Skripten, etc.

Moderator: LiMuBei

Benutzeravatar
Behemoth
Initiative Big Boss
Beiträge: 1827
Registriert: Donnerstag 10. Februar 2005, 14:48
Wohnort: Karlsruhe

Beitrag von Behemoth » Freitag 8. Dezember 2006, 18:35

Die Rekursionen waren tatsächlich alle ziemlich Banane.
Look at me, I'm invisible!

Benutzeravatar
Behemoth
Initiative Big Boss
Beiträge: 1827
Registriert: Donnerstag 10. Februar 2005, 14:48
Wohnort: Karlsruhe

Beitrag von Behemoth » Freitag 8. Dezember 2006, 18:48

Magic hat geschrieben:GGT_Handle_PlayerTime() ...
Ok, ich empfange einen timestamp zu einem player, der neuer ist als meine eigene Info, timestamp > data.timestamp.
Ich fordere die Info an mit GGT_Send_PlayerTime(data) und erwarte die neue Info, data.desiredtimetamp (sp?) = timestamp.
Nun empfange ich den gleichen timestamp zum gleichen player von einem anderen sender.
Wegen not data.lastrequesttime fordere ich die Info nochmal an mit GGT_Send_PlayerTime(data), ja?
Nun empfange ich einen noch neueren timestamp zu dem player, timestamp > data.desiredtimestamp.
Dann fordere ich die Info gleich nochmal an, oder? ^^

Vielleicht besser so:

Code: Alles auswählen

        if not data.desiredtimetamp or data.desiredtimetamp < timestamp then
          data.desiredtimetamp = timestamp
        end
        if not data.lastrequesttime or data.lastrequesttime + GGT_AnswerDelay < time() then
          GGT_Send_PlayerTime(data)
          data.lastrequesttime = time()
        end
Stimmt fast. Sollte aber "nur" einen Durchlauf ausmachen, wenn tatsächlich die anderen nichts voneinander wissen (sollte nicht vorkommen). Deine Variante würde aber nicht "nachfragen", wenn ein neuer neuerer Timestamp ankommt. Bei Dir hat die requesttime Prio vor dem Timestamp, und sollte genau anders rum sein. Bzw.: bei Deiner Version ist es nur von der Zeit abhängig, ob neu angefragt wird, und eigentlich gar nicht davon, ob die Daten überhaupt neuer sind als die eigenen.

Ich habe es mal geändert zu:

Code: Alles auswählen

        if not data.desiredtimestamp or data.desiredtimestamp < timestamp then
          GGT_Send_PlayerTime(data)
          data.desiredtimestamp = timestamp
          data.lastrequesttime = time()
        elseif not data.lastrequesttime or data.lastrequesttime + GGT_AnswerDelay < time() then
          GGT_Send_PlayerTime(data)
          data.lastrequesttime = time()
        end
Look at me, I'm invisible!

Benutzeravatar
Behemoth
Initiative Big Boss
Beiträge: 1827
Registriert: Donnerstag 10. Februar 2005, 14:48
Wohnort: Karlsruhe

Beitrag von Behemoth » Freitag 8. Dezember 2006, 18:50

Magic hat geschrieben: Was passiert eigentlich bei der for-Schleife

Code: Alles auswählen

  for i = 1, getn(GGT_RequestQueue) do
    if GGT_RequestQueue[i] and GGT_RequestQueue[i].sendtime <= curtime then
      GGT_Send_PlayerDataByName(GGT_RequestQueue[i].name)
      tremove(GGT_RequestQueue, i)
    end
  end
wenn tremove ausgeführt wird? Wird ein Eintrag übersprungen? Ist aber nicht schlimm, weil GGT_RequestHandler() eh wieder aufgerufen wird, gell? Wird es 1x pro Sekunde aufgerufen? In Bezug auf "tinsert(GG_UpdateFuncs, {delay = 1, func = GGT_RequestHandler})".
Stimmt genau. Man könnte i noch um eins decrementieren nach dem tremove, aber weiss gerade nicht, ob das in Lua mit Zählvariablen geht. Gleich mal testen.
Look at me, I'm invisible!

Benutzeravatar
Behemoth
Initiative Big Boss
Beiträge: 1827
Registriert: Donnerstag 10. Februar 2005, 14:48
Wohnort: Karlsruhe

Beitrag von Behemoth » Freitag 8. Dezember 2006, 19:04

Magic hat geschrieben:GGT_Handle_Item arbeitet ja direkt in der aktuellen Liste. Na wenn das mal gut geht. :-)
Was passiert, wenn nur eine Nachricht empfangen wurde und dann die Verbindung abbricht?
table.setn(items, totalitems) setzt die Listengröße auf das Soll, ohne dass alle Einträge vorhanden sind. Sind das dann leere Einträge?
Müssten es gewesen sein. Nachvollziehen kann ich es jetzt nicht mehr, weil setn mit 2.0.1 rausgeflogen ist, aber ich habe es mit einer Funktion ersetzt, die nil reinschreibt in die unbelegten, jo.
Magic hat geschrieben:Deine items haben eigene timestamps. Diese sind gleich dem timestamp der Liste, wenn alles gut ging. Zu Inkonsistenzen kommt es während der Übertragung/Aktualisierung. Was geschieht, wenn die Inkonsistenz nicht aufgelöst wird? In GGT_Send_PlayerData() setzt du die item-timestamps auf die der Liste, falls es Abweichungen gab, ohne darauf einzugehen. Absicht? Falls ich eine unvollständige Liste empfangen hatte und mir derzeit niemand eine aktuellere geben kann - jetzt kommt eine Anfrage auf meine Liste - ist das der Zeitpunkt, an dem meine Liste zu einer gültigen Liste gemacht wird? Was passiert eigentlich bei der Übertragung einer unvollständigen Liste? Es wird getn(data.offers) betrachtet, aber die einzelnen items werden nicht mehr geprüft.
Durch das Setzen und die Überprüfung in GGT_CheckForSyncEnd wird der Timestamp der Liste auf den "minimalen" Timestamp aller darin steckenden Items gesetzt. Beim Übertragen werden die Timestamps der Items alle auf den der Liste "reduziert". Potentielle Fehlerquelle, da hast Recht.
Magic hat geschrieben:Wie gesagt hätte ich die Übertragung der Listen etwas anders gestaltet. Sicherer erscheint es mir, die übertragene Listen erst zu puffern und nur bei Vollständigkeit die alten zu ersetzen. Oder: Man kann es auch so sehen, dass wenn es eine neue Liste gibt, dann kann ich die alte eh verwerfen (wohl nur bei Needs sinnvoll). Also statt einzelne Einträge überschreiben, erst mal alte Liste komplett weg, dann auffüllen. Sollte ich unvollständige Liste haben und jemand will diese haben, so hat er zum Schluss auch nur eine als unvollständig markierte Liste.
Von der Art war mein erster Ansatz, und der führte immer dazu, dass Leute aus der Anzeige verschwanden (Liste wurde gelöscht, aber dann kam nichts mehr, Liste = leer, Spieler verschwindet aus Anzeige). Doppelpufferung wäre wohl eine Möglichkeit, aber davor hatte ich immer Bammel, weil es ist ja immerhin "nur" eine Skriptsprache, und ich finde es jetzt schon ganz schön krass, wieviel Zeug da dann im Speicher rumfährt, wenn man "nur ein paar Items abspeichern will". Najo, vielleicht ist das auch gar kein wirklich Problem, und ich bilde mir das nur ein, mal kucken.
Magic hat geschrieben:Noch eine Idee, falls du in der bestehenden Liste aktualisieren willst: Sortiere die items stets sprachunabhängig nach ihrer ID. Alphabetische Anzeigelisten können nebenher erstellt/abgespeichert werden. Übertragen wird auch nach der ID sortiert. Wenn eine zweite ID empfangen wird, können alle bestehenden IDs zwischen erster und zweiter empfangener ID gelöscht werden. Dieses Vorgehen ist aber eigentlich nur zu empfehlen, wenn Listen oft nicht vollständig aktualisiert werden können.
Gleiches Problem wie oben: benötigt halt ganze Menge Speicher/Rechenzeit. Aber klingt so, als wäre eine genauere Betrachtung des Ansatzes eine ganz gute Idee.
Magic hat geschrieben:Zu guter Letzt: Fremden, unkommentierten Code durchzuschauen ist doppelt nervig, weißt ja. :-)
Pah! Versuch mal Code durchzuschauen, bei dem die Hälfte des Codes in der cpp Datei, ein Viertel in der h Datei, der Rest in irgendwelchen ominösen inl Dateien steckt, und alles mit kyrillischen Kommentaren versehen ist! Dann weisst du, was doppelt nervig ist! Russland 4tw!

Danke schon mal, für die vielen Ideen. :D
Look at me, I'm invisible!

Antworten