Datenhaltung

Proggen.org - Lernprojekt: Duplikatefinder
Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: Umstrukturierung der Datenbank

Beitrag von fat-lobyte » So Apr 15, 2012 7:08 pm

Bebu hat geschrieben:Ich habe drei Möglichkeiten, um darauf zu reagieren:
Escapesequenzen um solche Fehler im Pfadstring abzufangen
Pro:
Wohl die schnellste Lösung
Ich glaube, das Problem ist weniger Grundsätzlich als den Anschein hat. Im Grunde reduziert es sich auf das Escapen von Sonderzeichen.
Bebu hat geschrieben:Contra: Gibt es bei Sqlite überhaupt solche Sequenzen?
Im Notfall kannst du das selber einbauen, denn du hast ja bereits einen Wrapper um SQLite! Du musst nur beim speichern alle Zeichen escapen und beim laden alle wieder zurückumwandeln.

Übrigens, warum speicherst du die Strings nicht einfach als "Blob" Datentyp? Gibts da irgendwelche Probleme?
Die Umwandlung in diesen String resultiert bei Windows zu einem Problem, weil hier intern ein wchar benutzt wird und das sowieso störend auffällt.
Warte...
Boost.Filesystem gibt auf Linux UTF-8 mit char und auf Windows UTF-16 mit wchar_t zurück, richtig?
Ich glaube übrigens, das ist gar nicht so heikel... Ich hätte da ne Idee.
Die Nutzung einer Serialisierungsbibliothek um den Zustand der Klassen direkt abzuspeichern.
Pro: Von Boost verfügbar.
Contra: Eine Datenbankänderung bedeutet, das jedesmal die gesamte Datenbank neu geschrieben werden muss.
Also dieses Contra ist schon ein ziemliches Killer-Contra.
Selbstschreiben eines Binärdateiparsers mit Jornalfunktion.
Pro: Flexibel und Platzsparend.
Contra: Hoher Aufwand, praktisch ein eigenes kleines Dateisystem nötig. Wie lässt sich so etwas gestalten, damit es wiederverwendbar ist? Boost::Spirit? Template Klassen?
Im Endeffekt müsstest du eine Datenbankbibliothek nachprogrammieren. "That doesn't scale well", wenn man auf zeitliche Ressourcen achtet.
Das waren meine Gedankengänge zum Thema bisher. Habt ihr noch eine andere Idee? Sonstige Anregungen?
Ein kleiner Comic zum Thema: http://xkcd.com/327/ ;-)
Haters gonna hate, potatoes gonna potate.

Benutzeravatar
Bebu
Beiträge: 562
Registriert: Mi Okt 21, 2009 6:19 pm
Wohnort: In der Nähe von Salzburg - Bin aber kein Österreicher!

Re: Umstrukturierung der Datenbank

Beitrag von Bebu » So Apr 15, 2012 10:19 pm

fat-lobyte hat geschrieben: Ich glaube, das Problem ist weniger Grundsätzlich als den Anschein hat. Im Grunde reduziert es sich auf das Escapen von Sonderzeichen.
...
Im Notfall kannst du das selber einbauen, denn du hast ja bereits einen Wrapper um SQLite! Du musst nur beim speichern alle Zeichen escapen und beim laden alle wieder zurückumwandeln.

Übrigens, warum speicherst du die Strings nicht einfach als "Blob" Datentyp? Gibts da irgendwelche Probleme?
Ja, aber das kommt mir wie ein schlechter Workaround vor. Ich muss mich wohl noch tiefer in Sqlite eingraben. Als Blob, mhh ja und nein. Das speichern als Blob dürfte Select Befehle nach dem Pfad ziemlich nutzlos machen.
fat-lobyte hat geschrieben: Warte...
Boost.Filesystem gibt auf Linux UTF-8 mit char und auf Windows UTF-16 mit wchar_t zurück, richtig?
Ich glaube übrigens, das ist gar nicht so heikel... Ich hätte da ne Idee.
Das ist richtig. Diese Problem habe ich auch schon mal temporär gelöst. Mit Xins Hilfe habe ich einen Konverter geschrieben, der von UTF16 wchar_t auf UTF8 char umwandeln kann.

Die Serialisierungsmöglichkeit habe ich auch schon wieder verworfen. Das ist nicht effizient, vor allem wenn die Datenbank ziemlich groß ist.

Ich muss zugeben, das mich der Binärparser ziemlich gereizt hat. Allerdings ist der zeitaufwand brutal. Dazu kommt, das man nicht einfach Datenfelder hinzufügen kann, ohne die Daten zu gefährden. Man müsste also immer einen Konverter zur Verfügung stellen, wenn eine Funktion dazukommt, die Daten speichern will.
Also werde ich mich jetzt nochmal durch die englische Doku von Sqlite durchbeißen und dann den Wrapper überarbeiten. Vielleicht schreibe ich auch einen höher auf Dedupe optimierten Wrapper. Mal sehen, was ich noch entdecke. Fast wie die Schatzinsel ;)
Wer immer nach dem Unerreichbaren jagt, der wird irgendwann auf die Schnauze fallen!

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Umstrukturierung der Datenbank

Beitrag von Xin » Mo Apr 16, 2012 10:15 am

Bebu hat geschrieben:Ich muss zugeben, das mich der Binärparser ziemlich gereizt hat. Allerdings ist der zeitaufwand brutal. Dazu kommt, das man nicht einfach Datenfelder hinzufügen kann, ohne die Daten zu gefährden. Man müsste also immer einen Konverter zur Verfügung stellen, wenn eine Funktion dazukommt, die Daten speichern will.
Nein, da gibt es bereits Lösungen für. Chunk-Basierte Binärformate speichern in der Regel zuerst was nachfolgend einzulesen ist (eben den Chunktyp) und dann die Länge, anschließend folgt die Daten.
Hat man die Chunk-Länge eingelesen, gibt's keine Daten mehr. Wenn eine neue Version also noch ein Datum erwartet, muss sie jetzt den Defaultwert annehmen.
Eine alte Version, liest alle Daten, die sie braucht und prüft, ob sie die Länge des Chunks damit vollständig gelesen hat. Wenn nicht, sind da zusätzliche Daten, die von einer neueren Versionen geschrieben wurden, die man überspringen muss, um beim nächsten Chunk anzukommen.
Geschichtlich gesehen wäre das Interchange File Format hier interessant (siehe CMAP).


Aber lass uns das Ding erstmal ans Laufen bringen.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: Umstrukturierung der Datenbank

Beitrag von fat-lobyte » Mo Apr 16, 2012 10:38 am

Bebu hat geschrieben:Ja, aber das kommt mir wie ein schlechter Workaround vor. Ich muss mich wohl noch tiefer in Sqlite eingraben.
Ich hab irgendwo in der Doku gelesen, dass es *keinen* escape-Mechanismus in SQLite gibt. Der Workaround ist jetzt nicht so unglaublich elegant, aber wenn man das Escapen sauber hinkriegen würde, wäre es durchaus legitim. Was ist so falsch daran den Input zu prüfen und in ein für dich lesbares Format umzuwandeln?
Als Blob, mhh ja und nein. Das speichern als Blob dürfte Select Befehle nach dem Pfad ziemlich nutzlos machen.
Wieso denn? Die eineindeutige Zuordnung funktioniert immer noch, und du kannst immer noch mit Wildcards suchen, nur muss man den Pfad vorher eben in "Blob" kodieren. Oder hab ich da was falsch verstanden?
Mit Xins Hilfe habe ich einen Konverter geschrieben, der von UTF16 wchar_t auf UTF8 char umwandeln kann.
Ok, aber braucht man das unbedingt? SQLite kann sowohl UTF-8 als auch UTF-16 speichern, habe ich glesen. Kann man nicht mithilfe von Funktionsüberladung einfach das nehmen was rauskommt und in die Datenbank stopfen?
Also werde ich mich jetzt nochmal durch die englische Doku von Sqlite durchbeißen und dann den Wrapper überarbeiten. Vielleicht schreibe ich auch einen höher auf Dedupe optimierten Wrapper. Mal sehen, was ich noch entdecke. Fast wie die Schatzinsel ;)
Hehe, klingt ja so als ob du wieder Spaß dran hast. Das ist gut :-)
Haters gonna hate, potatoes gonna potate.

nufan
Wiki-Moderator
Beiträge: 2557
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Umstrukturierung der Datenbank

Beitrag von nufan » Mo Apr 16, 2012 10:43 am

fat-lobyte hat geschrieben:
Bebu hat geschrieben:Ja, aber das kommt mir wie ein schlechter Workaround vor. Ich muss mich wohl noch tiefer in Sqlite eingraben.
Ich hab irgendwo in der Doku gelesen, dass es *keinen* escape-Mechanismus in SQLite gibt.
Anscheinend gibt es sowas wie Prepared Statements in Java auch in SQLite:
http://stackoverflow.com/questions/4820 ... e-string-c

Benutzeravatar
Bebu
Beiträge: 562
Registriert: Mi Okt 21, 2009 6:19 pm
Wohnort: In der Nähe von Salzburg - Bin aber kein Österreicher!

Re: Datenhaltung

Beitrag von Bebu » Do Apr 26, 2012 12:42 pm

Die prepared Statements sind auch die letztliche Lösung für das Problem. Ich habe gerade ein entsprechendes Experiment abgeschlossen und hoffe mal, dass ich es die Tage schaffe eine entsprechendes Update ins Repo einzupflegen. Das sollte auch das Problem mit den Hochkommas lösen.
Wer immer nach dem Unerreichbaren jagt, der wird irgendwann auf die Schnauze fallen!

Benutzeravatar
Bebu
Beiträge: 562
Registriert: Mi Okt 21, 2009 6:19 pm
Wohnort: In der Nähe von Salzburg - Bin aber kein Österreicher!

Re: Datenhaltung

Beitrag von Bebu » Do Mai 10, 2012 8:17 pm

Revision 268 hochgeladen. Dieser Upload sollte den Bug mit den Hochkommas und Anführungszeichen im Dateinamen fixen. Bitte um Rückmeldung.

Bebu
Wer immer nach dem Unerreichbaren jagt, der wird irgendwann auf die Schnauze fallen!

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: Datenhaltung

Beitrag von fat-lobyte » Fr Mai 11, 2012 1:56 pm

So, es kompiliert schon mal.

Ich habe die Datenbank upgedatet, hier ein paar performance-Daten:

Für ein Verzeichniß mit 2995 Dateien und Gesamtgröße von 42 GB, benötigte das Datenbankupdate folgende Zeit:

Code: Alles auswählen

real	32m30.010s
user	3m26.090s
sys	4m24.370s
.

Das Menü ist zwar noch nicht das bequemste, aber es scheint zu funktionieren! Zwei Daumen!
Eine kleine Anmerkung: hat man alle bis auf ein Duplikat zum löschen ausgewählt, sollte das letzte Duplikat nicht mehr zum löschen angeboten werden. So kanns passieren dass man statt 2 Dateien auf einmal keine mehr hat.

Allerdings sieht es so aus, als würden die Dateien nach dem Löschen nicht aus der Datenbank gelöscht werden.
Es steht zwar bei darauffolgenden Aufrufen "Deleting file...", aber das kommt eben immer. Auch werden die Duplikate jedes mal zum löschen angeboten. Irgendwas passt da nicht. Ich bin auf Skype, falls du mit mir "Realtime-debugging" machen willst.
Haters gonna hate, potatoes gonna potate.

Benutzeravatar
Bebu
Beiträge: 562
Registriert: Mi Okt 21, 2009 6:19 pm
Wohnort: In der Nähe von Salzburg - Bin aber kein Österreicher!

Re: Datenhaltung

Beitrag von Bebu » Sa Mai 12, 2012 11:50 pm

Ich habe gerade einen Fix hochgeladen. Es war eine schwere Geburt und wie so oft ein relativ trivialer Fehler :? Bei mir funktioniert es so, wie es sollte, wenn es bei dir auch so sein sollte, dann bin ich ganz zufrieden.
Wer immer nach dem Unerreichbaren jagt, der wird irgendwann auf die Schnauze fallen!

Benutzeravatar
fat-lobyte
Beiträge: 1398
Registriert: Sa Jul 05, 2008 12:23 pm
Wohnort: ::1
Kontaktdaten:

Re: Datenhaltung

Beitrag von fat-lobyte » So Mai 13, 2012 7:04 pm

Bebu hat geschrieben:Ich habe gerade einen Fix hochgeladen. Es war eine schwere Geburt und wie so oft ein relativ trivialer Fehler :? Bei mir funktioniert es so, wie es sollte, wenn es bei dir auch so sein sollte, dann bin ich ganz zufrieden.
Ähem...

Code: Alles auswählen

[ 54%] Building CXX object userinterface/gui/ncurses/CMakeFiles/dedupe-ncurses.dir/implementation.cpp.o
In file included from /home/alexander/dedupe-svn/userinterface/gui/ncurses/implementation.h:3:0,
                 from /home/alexander/dedupe-svn/userinterface/gui/ncurses/implementation.cpp:5:
/home/alexander/dedupe-svn/userinterface/interface.h: In Elementfunktion »void Dedupe::GUI::Main::OnTrack()«:
/home/alexander/dedupe-svn/userinterface/interface.h:104:20: Fehler: »class Dedupe::Core::Kernel« hat kein Element namens »AppendFile«
/home/alexander/dedupe-svn/userinterface/interface.h: In Elementfunktion »void Dedupe::GUI::Main::OnUntrack()«:
/home/alexander/dedupe-svn/userinterface/interface.h:120:20: Fehler: »class Dedupe::Core::Kernel« hat kein Element namens »RemoveFile«
In file included from /home/alexander/dedupe-svn/userinterface/gui/ncurses/implementation.h:8:0,
                 from /home/alexander/dedupe-svn/userinterface/gui/ncurses/implementation.cpp:5:
/home/alexander/dedupe-svn/userinterface/gui/ncurses/markable.h: In Elementfunktion »bool Dedupe::GUI::Markable::SetMark(bool)«:
/home/alexander/dedupe-svn/userinterface/gui/ncurses/markable.h:56:9: Warnung: keine return-Anweisung in nicht void zurückgebender Funktion [-Wreturn-type]
In file included from /home/alexander/dedupe-svn/userinterface/gui/ncurses/implementation.cpp:5:0:
/home/alexander/dedupe-svn/userinterface/gui/ncurses/implementation.h: In Elementfunktion »virtual std::vector<Dedupe::FileInfo> Dedupe::GUI::NCursesMain::GetFiles()«:
/home/alexander/dedupe-svn/userinterface/gui/ncurses/implementation.h:73:52: Warnung: keine return-Anweisung in nicht void zurückgebender Funktion [-Wreturn-type]
/home/alexander/dedupe-svn/userinterface/gui/ncurses/implementation.h: In Elementfunktion »virtual std::vector<Dedupe::FileInfo> Dedupe::GUI::NCursesMain::GetSelectedTrackedFiles()«:
/home/alexander/dedupe-svn/userinterface/gui/ncurses/implementation.h:74:67: Warnung: keine return-Anweisung in nicht void zurückgebender Funktion [-Wreturn-type]
/home/alexander/dedupe-svn/userinterface/gui/ncurses/implementation.cpp: In Elementfunktion »virtual bool Dedupe::GUI::NCursesMain::IsRecursive()«:
/home/alexander/dedupe-svn/userinterface/gui/ncurses/implementation.cpp:154:5: Warnung: keine return-Anweisung in nicht void zurückgebender Funktion [-Wreturn-type]
make[2]: *** [userinterface/gui/ncurses/CMakeFiles/dedupe-ncurses.dir/implementation.cpp.o] Fehler 1
make[1]: *** [userinterface/gui/ncurses/CMakeFiles/dedupe-ncurses.dir/all] Fehler 2

Code: Alles auswählen

$ c++ --version
c++ (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2)
Haters gonna hate, potatoes gonna potate.

Antworten