Große Datenmengen serialisieren und durchschleifen - wie machen?

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Große Datenmengen serialisieren und durchschleifen - wie machen?

    Für Sepia (In Arbeit.... ) schreibe ich gerade eine Erweiterung, eine Art serialize() und Exportfunktion für einzelne (oder mehrere) Datensätze innerhalb des CMS.

    Das heißt, man kann einzelne Datensätze (z.B. Inhaltsseiten) mit allen relevanten Informationen (Erstellungsdatum, Ort in der Baumstruktur, Name, Rechtedatensatz, Ersteller, Darstellungsoptionen) exportieren und bekommt einen Download angeboten, den man dann in einer anderen Sepia-Installation wieder einspielen kann, nicht unähnlich einem SQL-Dump, aber komplexer, weil bis zu 4 Tabellen involviert sind: Der Datensatz selbst, die administrative Seite, die Rechtetabelle und eventuell die zur referentiellen Integrität.

    Soweit so machbar.

    Jetzt ist es aber so, daß an einem solchen Datensatz Dateien hängen können, z.B. hochgeladene Bilder. Diese müssen mit in den Download gepackt werden, sonst hat die Funktion kaum praktischen Wert.
    Es muß eine Datei dabei rauskommen, die ich dann PHP-Seitig wieder auseinandernehmen kann. Kompression ist erstmal zweitrangig.

    Die Frage ist nun: Wie gestalte ich das Zusammenpacken mehrerer Dateien mit unbekannter Dateigröße so, daß auch große Mengen von Dateidaten das Memory-Limit nicht sprengen?

    Also, kennt ihr eine Methode, mit der ich mehrere Dateien hintereinander öffnen, alle in einem Dateioutput als Download durchschleifen und beim späteren Upload dann wieder auseinanderdröseln kann, unter Nutzung der Dateizeiger, sodaß mein Speicher nie überläuft?

    Verpackungsfunktionen wie serialize() kann ich hier ja nicht nutzen, weil diese am Memory-Limit scheitern würden, spätestens wenn eine einzelne Datei größer ist als das Memory-Limit - mit dem Fall muß gerechnet werden, Sepia ist ein sehr robustes System und alles was dazukommt, muß genauso robust sein.

    Ist das Problem einigermaßen klar formuliert?
    Hat jemand Ideen / Ansätze?
    Am ehesten wirds wahrscheinlich etwas sein, was die Dateien hintereinander ausgibt und durch einen vorher festgelegten String trennt. Dafür gibts bestimmt schon was fertiges, was die ganzen Klippen (Kodierungen / CR/LF / und so weiter) schon umschifft hat?

    Gibt es ein einfaches Stichwort zum Googeln, auf das ich nicht komme?
    Zuletzt geändert von pekka; 09.06.2008, 20:56.

  • #2
    Also ich stelle mir gerade soetwas wie eine MIME-Mail vor. Das käme auch deiner Idee mit der Trennung durch einen vorher festgelegten String nahe.

    Allerdings dürftest du da genauso am Speicher scheitern, wie bei anderen großen Dateien, oder?

    Kommentar


    • #3
      Du solltest auf jeden Fall ein festes Dateiformat definieren. Du hast ja im Grunde 3 Arten von Informationen:
      • Die Datensätze
      • Die mit den Datensätzen verknüpften Dateien
      • Metainformationen (Anzahl Datensätze, ...)
      Jetzt kannst du dir jedes beliebige bestehende Dateiformat als Vorbild schnappen und dein Format ähnlich gestalten.
      (Recht anschaulich finde ich da die Doku zu dem Mo-Dateiformat.)
      Oft hast du einige Headerinformationen, die zum Teil die Anzahl Bytes der nachfolgenden Sektionen beinhalten. Dort würde ich auch die Metadaten unterbringen.
      Nach dem Auslesen dieses Headerblocks kennst du schon mal die Anzahl Datensätze, Dateien, Dateilängen, etc. D.h. du kannst die Datei sequentiell weiter parsen und nach entsprechender Anzahl von gelesenen Bytes diese Daten behandeln, zum Beispiel die Datensätze in die Tabellen packen oder Dateien auf die Festplatte legen.

      Alles serialisiert abzulegen, ist natürlich viel zu Groß. Aber zum Beispiel die Headerinformationen könntest du so recht bequem ablegen. Afaik gibt es da aber ein paar bekannte Overflow-Bugs beim unserialize, so dass das mit Vorsicht zu genießen ist.

      Kommentar


      • #4
        Japp, auf ein eigenes Dateiformat wirds wohl rauslaufen!
        Die serialisierten Infos + Strukturinformationen kommen mit serialize() in eine Datei. Die "Attachment"-Dateien sind ja schon da. Größen aller Dateien ermitteln, header mit den zu erwartenden Bytepositionen schreiben, und dann mit fread() und echo() durchschleifen bis es fertig ist.

        Das probier ich mal! Vor sowas hab ich immer einen Heidenrespekt, weil ich es noch nie probiert habe. Aber ich mache mal und stelle dann hier zur Kritik online

        @TobiaZ: Eine MIME-Mail wäre genau das, was ich bräuchte, und würde dazu noch ermöglichen, daß man einzelne Items mailen kann aber es scheitert eben an der Speichergrenze...
        Zuletzt geändert von pekka; 09.06.2008, 21:14.

        Kommentar


        • #5
          Aber wenn du die Daten zippst, solltest du recht vernünftig damit arbeiten können:

          Du kannst alle Dateien im Ursprungsformat belassen, die brauchen dann auch später gar nicht mehr angepackt werden und sollten als einzelnes nicht weiter am Speicher-Limit kauen.
          Die Datensätze oder Metadaten lassen sich in Form von Text ja sicher recht gut komprimieren. Und wenn sie dann tatsächlich (in sich) zu groß werden, dann kannst du sie ja locker splitten.

          Dann wird es gezippt und mit der Dateiendung .sep gespeichert.
          Zuletzt geändert von TobiaZ; 09.06.2008, 21:26.

          Kommentar


          • #6
            Wann darf man denn mit einer Veröffentlichung von deinem CMS rechnen? Bin schon gespannt...

            OffTopic:
            "...bestehende, statische Websites bin hin zu komplexen,..."

            Nur als kurzer Hinweis, da ist ein kleiner Schreibfehler auf deiner deutschen Seite.
            Simploo CMS - das einfache Webseiten-Bearbeitungsprogramm

            Kommentar


            • #7
              Typo3 hat übrigens auch so eine Export-Funktion, die Datensätze und Dateistrukturen/Bilder in eine Datei packt.

              Vielleicht kannst du was rausholen.
              Simploo CMS - das einfache Webseiten-Bearbeitungsprogramm

              Kommentar


              • #8
                OffTopic:
                "...bestehende, statische Websites bin hin zu komplexen,..."

                Nur als kurzer Hinweis, da ist ein kleiner Schreibfehler auf deiner deutschen Seite.
                Mmm? Ich seh keinen?

                Original geschrieben von eintrachtemil
                Wann darf man denn mit einer Veröffentlichung von deinem CMS rechnen? Bin schon gespannt...
                Es sollte eigentlich Mai werden Ich hoffe sehr, daß ich im Juni zu Potte komme. Es ist so, daß es noch ein paar grundlegende Dinge gibt, die ich auf den neuesten Stand bringen möchte, bevor es öffentlich wird. Sonst fangen Leute an, mit dem alten Stand zu spielen und gar Projekte umzusetzen, und man hat einen Riesenaufwand beim Migrieren.

                Typo3 hat übrigens auch so eine Export-Funktion, die Datensätze und Dateistrukturen/Bilder in eine Datei packt.
                Vielleicht kannst du was rausholen.
                Ich versuch mal mein Glück mit dem eigenen Dateiformat, dann sieht man weiter!

                Kommentar


                • #9
                  statische Websites bi[COLOR=red]s[/COLOR] hin zu komplexen

                  Kommentar


                  • #10
                    Upps Danke!

                    Kommentar


                    • #11
                      Juhu, Erfolg!
                      Statt eines proprietären Dateiformats wollte ich letztlich doch unbedingt ZIPs produzieren. Zusammen mit einer XML-Datei für die Datenbankdaten - offener gehts nicht mehr

                      Der Code selbst ist viel zu Sepia-spezifisch, als daß ihn hier zu posten Sinn machen würde. Aber so hats geklappt:

                      Diese Zip-Klasse erzeugt Zip-Archive und unterstützt das reine "storen" großer Dateien ohne Kompression.

                      Im Ursprungszustand erzeugt die Klasse die Zip-Datei on the fly und gibt sie in 1-MB-Blöcken mittels echo() als Dateidownload aus. Dateien kleiner als 20 MB werden mittels gzdeflate() komprimiert, Dateien darüber nicht. Die diesbezügliche Einstellung stellt man für den hier besprochenen Zweck auf 1 Byte, damit nie komprimiert, sondern immer nur ge"stored" wird.

                      Ich habe die Klasse so erweitert, daß sie statt direkter Ausgabe alternativ mit fwrite() in eine Datei schreibt. Wenn es in der direkten Ausgabe Verzögerungen gibt, stößt das Skript nämlich schneller an das max_execution_time-Limit.

                      Mit direkter Ausgabe zum Download habe ich auf dem Testserver (WAMP, 512 MB RAM, AMD Sempron 1800+, max_execution_time = 60, memory_limit = 8M) bis zu 60 MB Dateidaten in ein Zip bekommen; Mit Schreiben in eine Datei bis zu 600 MB!!!! Bei 800 war dann Schluß wegen des 60-sekunden-Limits, da stoßen fread() und fwrite() an ihre Grenzen.

                      Also - das sieht bisher wie eine praxistaugliche und Provider-Kompatible Exportmethode aus, die solide ZIP-Archive produziert und durch den Verzicht auf Kompression nicht mal auf das Vorhandensein der gzip-Funktionen angewiesen ist!

                      Solche Klassen gibt es bestimmt viele, aber diese hier hat mir gleich gefallen.

                      Fixes:

                      Ich mußte in Zeile 343 der zipstream.php das fgets() durch ein fread() ersetzen, davor war die Performance katastrophal. Hab nicht genau geblickt warum aber es ist mir grad auch egal

                      ... und eben das Umschreiben des Outputs von echo() auf fwrite().

                      EDIT:

                      Wichtig: Die Checksumme für die ins Archiv gepackten Dateien wird mit der PHP5-Funktion hash_file() und der Methode "CRC32b" gebildet.
                      Ich habe auf die Schnelle kein PHP4-Workaround gefunden, das eine CRC32b-Checksumme so produziert, daß der Speicher bei großen Dateien nicht überläuft. Im Momentanen Zustand ist das ganze also PHP5 only und abhängig von den Hash-Funktionen, was mich eigentlich ärgert... Mal schauen, ob sich da noch ein Workaround findet.


                      Zuletzt geändert von pekka; 11.06.2008, 20:07.

                      Kommentar

                      Lädt...
                      X