Libelektra: mmapstorage funktioniert nicht mit dem kdb-Export

Erstellt am 15. Feb. 2019  ·  22Kommentare  ·  Quelle: ElektraInitiative/libelektra

Schritte zum Reproduzieren des Problems

kdb set user/tests/hello world
#> Create a new key user/tests/hello with string "world"

kdb export user/tests/hello mmapstorage > test.mmap

erwartetes Ergebnis

Es wird eine Datei mit dem Namen test.mmap erstellt, die mit kdb import erneut importiert werden kann.

Tatsächliche Ergebnis

Eine leere Datei mit dem Namen test.mmap wird erstellt und die folgende Nachricht wird gedruckt (einschließlich Protokollen von ENABLE_LOGGER ):

src/plugins/mmapstorage/mmapstorage.c:944:libelektra_mmapstorage_LTX_elektraPluginset: could not unlink
src/plugins/mmapstorage/mmapstorage.c:1003:libelektra_mmapstorage_LTX_elektraPluginset: strerror: Permission denied
Sorry, the error (#9) occurred ;(
Description: Insufficient permissions to open configuration file for writing. You might want to retry as root.
Reason: Permission denied
Ingroup: kdb
Module: 
At: /home/klemens/data/bsc/libelektra/src/plugins/mmapstorage/mmapstorage.c:1004
Mountpoint: user
Configfile: /dev/stdout

System Information

  • Elektra Version: Meister

Weitere Informationen

~ Funktioniert, wenn kdb export als root aufgerufen wird. ~ (BEARBEITEN: siehe Kommentar unten) kdb export user/tests/hello mmapstorage test.mmap funktioniert ebenfalls, ist jedoch eine völlig undokumentierte Funktion von kdb export . Eine bessere Fehlermeldung und eine aktualisierte Dokumentation könnten also alles sein, was wir brauchen.

bug

Hilfreichster Kommentar

Danke für Ihre Antwort!

Die mmap-Fehlermeldungen sind möglicherweise irreführend.

Bitte verbessern Sie die Fehlermeldungen.

Meines Wissens wird es auf stdout nicht funktionieren. Es funktioniert auch nicht mit Rohren

Bitte fügen Sie diese Informationen zu den Fehlermeldungen hinzu.

Die obigen Lösungen ändern nicht viel an der mmapstorage-Logik.

Da Ihr Plugin derzeit das einzige betroffene ist, ist es sinnvoll, dass Sie die Statistik ausführen und bei Bedarf alles kopieren. Dann könnten wir dieses Problem ohne größere Änderungen im Framework schließen.

Alle 22 Kommentare

Vielen Dank, dass Sie dies versucht haben und für diesen detaillierten Bericht!

Eine bessere Fehlermeldung und eine aktualisierte Dokumentation könnten also alles sein, was wir brauchen.

Ja, ich stimme voll und ganz zu.

Vielleicht sollten wir sogar ein serializable in infos / status # 666 haben und explizit fehlschlagen, wenn die Datei / dev / stdout ist? ( @mpranj Oder gibt es eine Möglichkeit zu erkennen, ob eine Datei nicht mmapable ist? Entspricht sie wirklich einer verweigerten Berechtigung?)

Wenn ich mir den Code (und die Fehlermeldung) ansehe, denke ich, dass das aktuelle Problem darin besteht, dass wir unlink auf stdout ohne Root-Zugriff nicht aufrufen können. Auch open wird wahrscheinlich ebenfalls scheitern, da stdout bereits geöffnet ist. Und ob stdout mmapable ist oder nicht, hängt davon ab, mit was stdout verbunden ist, denke ich.
Verwenden Sie fstat(fileno(stdout), &stat) , um zu überprüfen, ob es sich möglicherweise um eine reguläre Datei handelt. Vielleicht funktioniert auch isatty(3) .

In jedem Fall könnten wir einfach überprüfen, ob die Ausgabedatei /dev/stdout (oder CON für _WIN32 ) und eine temporäre Datei zur Verwendung mit mmap erstellen und diese anschließend einfach nach stdout kopieren kdb export .

Vielleicht sollten wir sogar ein serializable in infos / status # 666 haben und explizit fehlschlagen, wenn die Datei / dev / stdout ist?

Wenn überhaupt, würde ich den Status humanreadable und mich weigern, in ein tty stdout zu exportieren, wenn das Format nicht für Menschen lesbar ist.

Funktioniert, wenn kdb export als root aufgerufen wird.

Ich nehme das zurück ... VERSUCHEN SIE DAS NICHT! Das Aufrufen von kdb export <something> mmapstorage als Root-Benutzer (auch wenn stdout umgeleitet wird) zerstört /dev/stdout . Die Verwendung von /dev/stdout (z. B. über fopen ) funktioniert auf Ihrem System erst, wenn Sie den Standard-Symlink mit sudo rm /dev/stdout && sudo ln -s /dev/stdout /proc/self/fd/1 neu erstellen.

Ich denke, die beste Lösung ist, dass kdb export und kdb import immer für temporäre Dateien funktionieren. Dann ähnelt kdb export eher dem, was KDB tut. Dies würde das Problem der Aufhebung der Verknüpfung lösen (das für mmaped-Dateien erforderlich ist). Der Nachteil ist nur ein Leistungsverlust (Kopie des gesamten benötigten Inhalts), aber dann funktioniert der Import / Export mit allen Speicher-Plugins, was imho viel wichtiger ist.

Ich denke, die beste Lösung ist, dass kdb export und kdb import immer für temporäre Dateien funktionieren.

Ich denke, Plugins sollten die temporäre Datei bei Bedarf selbst erstellen. Auf diese Weise vermeiden wir Leistungseinbußen bei Plugins, die direkt an TTYs ausgegeben werden können. AFAIK mmapstorage ist derzeit das einzige Plugin, das mit TTYs nicht funktioniert. Wir könnten auch einen einfachen Shell-Test hinzufügen, der sicherstellt, dass alle Speicher-Plugins über kdb export /some/key plugin > export.file aufgerufen werden können. Die Logik ist auch eigenständiger, da es in der Verantwortung des Plugins liegt, zu wissen, wie die erwartete Ausgabe erzeugt wird.

Auch für kdb import temporäre Dateien nicht erforderlich, da das Lesen einer Datei auch für TTYs immer funktionieren sollte (wenn Sie über die richtigen Berechtigungen verfügen).

Ich denke, Plugins sollten die temporäre Datei bei Bedarf selbst erstellen.

Dann müssten die Plugins (oder genauer gesagt mmap) wissen, ob sie in KDB oder kdb export .

@mpranj Was ist deine Meinung? Kann dies im mmap Plugin behoben werden?

Auf diese Weise vermeiden wir Leistungseinbußen bei Plugins, die direkt an TTYs ausgegeben werden können.

In welchen Fällen ist diese Leistungsminderung ein Problem? Vielleicht in der Sicherung / Wiederherstellung für jeden Testfall?

AFAIK mmapstorage ist derzeit das einzige Plugin, das mit TTYs nicht funktioniert.

Für den Export ja. Aber für den Import hatten wir mehrere Plugins, die nicht funktionieren. Wenn ein Plugin fseek oder ähnliches verwendet, kann es offensichtlich nicht funktionieren, z. B. csvstorage oder mozprefs. (Dump sollte jetzt behoben sein)

Wir könnten auch einen einfachen Shell-Test hinzufügen, der sicherstellt, dass alle Speicher-Plugins über kdb export / some / key plugin> export.file aufgerufen werden können.

Du meinst tests / shell / check_export.sh Zeile 46?

In welchen Fällen ist diese Leistungsminderung ein Problem?

Eigentlich wahrscheinlich nie. Solange Sie die 3 Argumentversionen von Export / Import anstelle von Piping verwenden. Siehe Vorschlag unten.

Du meinst tests / shell / check_export.sh Zeile 46?

Ja, aber das ist kaputt, weil is_not_rw_storage nicht funktioniert. Nicht einmal dump wird als Speicher-Plugin erkannt.


Ich denke, um dies schnell und einfach zu lösen, sollten wir Folgendes tun:

  1. Korrigieren Sie is_not_rw_storage in include_common.sh.in tests/shell/check_export.sh damit wir in Zukunft solche Probleme erkennen.
  2. Erstellen Sie in kdb export eine temporäre Datei, nur wenn kein drittes Argument angegeben wird. Verwenden Sie diese Datei in den kdbSet -Aufrufen und kopieren Sie anschließend den Druck nach stdout (sollte in C ++ nicht mehr als ein oder zwei Zeilen umfassen).
  3. In ähnlicher Weise erstellen Sie für kdb import eine temporäre Datei, wenn stdin verwendet wird. Kopieren Sie das gesamte stdin in die temporäre Datei und rufen Sie kdbGet dieser Datei
  4. Aktualisieren Sie die Dokumentation von kdb import und kdb export um festzustellen, dass das dritte Argument vorhanden ist. Geben Sie außerdem an, dass bei Verwendung der Version mit zwei Argumenten eine temporäre Datei erstellt wird.

PS. Dies könnte good first issue

Vielen Dank für die Meldung, dass is_not_rw_storage defekt ist. Ich habe # 2423 geöffnet

Entschuldigung , ich war eine Woche weg, also konnte ich mich nicht darum kümmern.

Die mmap-Fehlermeldungen sind möglicherweise irreführend. mmap() schlägt mit EACCES mmap() fehl, wenn versucht wird, nicht reguläre Dateien zuzuordnen. Meines Wissens wird es auf stdout nicht funktionieren. Es funktioniert auch nicht mit Rohren, wie in # 2209 beschrieben.

Von POSIX:

Die Funktion mmap () soll für folgende Speicherobjekte unterstützt werden:

  • Normale Dateien
  • [SHM] Shared Memory-Objekte
  • [TYM] Typisierte Speicherobjekte

Bei Lösungen in mmapstorage können wir überprüfen, ob es sich um eine reguläre Datei mit stat und dann:

  • Schreiben Sie in eine temporäre reguläre Datei, wie oben vorgeschlagen
  • Schreiben Sie in einen temporären Speicherort (einfach malloc anstelle von mmap) und kopieren Sie dann in die nicht reguläre Datei (pipe, stdout, ..).

Ich bin auch offen für andere Lösungen. Die obigen Lösungen ändern nicht viel an der mmapstorage-Logik. Die Überarbeitung von mmapstorage, um direkt mit Rohren oder Standard zu arbeiten, macht für mich nicht allzu viel Sinn.

Danke für Ihre Antwort!

Die mmap-Fehlermeldungen sind möglicherweise irreführend.

Bitte verbessern Sie die Fehlermeldungen.

Meines Wissens wird es auf stdout nicht funktionieren. Es funktioniert auch nicht mit Rohren

Bitte fügen Sie diese Informationen zu den Fehlermeldungen hinzu.

Die obigen Lösungen ändern nicht viel an der mmapstorage-Logik.

Da Ihr Plugin derzeit das einzige betroffene ist, ist es sinnvoll, dass Sie die Statistik ausführen und bei Bedarf alles kopieren. Dann könnten wir dieses Problem ohne größere Änderungen im Framework schließen.

Dann könnten wir dieses Problem ohne größere Änderungen im Framework schließen.

Wir sollten auch die Manpages für kdb import und kdb export aktualisieren. Derzeit erwähnen sie nicht die 3 Argumentversionen, die nicht auf stdin / stdout basieren.

Vielen Dank für die Meldung des Problems und für die Eingabe!

Leider druckt strerror diese irreführenden Fehlermeldungen. In diesem Fall kann ich einen Hinweis hinzufügen.

Ich werde diese Woche die gewünschten Änderungen in einer PR vornehmen.

Wir sollten auch die Manpages für den kdb-Import und den kdb-Export aktualisieren. Derzeit erwähnen sie nicht die 3 Argumentversionen, die nicht auf stdin / stdout basieren.

Vielleicht brauchen wir das Argument nicht, um die Datei anzugeben? Das Argument würde in Konflikt geraten, sobald kdb import/export mehrere Plugins unterstützt.

Ich werde diese Woche die gewünschten Änderungen in einer PR vornehmen.

Danke!

Vielleicht brauchen wir das Argument nicht, um die Datei anzugeben?

Dann müssen wir in allen Plugins stdin und stdout (umgeleitet in eine reguläre Datei) unterstützen. Andernfalls könnten sie niemals mit kdb import/export . Das macht Sinn für mmapstorage weil es nicht portabel ist, aber andere Plugins, die portabel sind (vielleicht sogar für Menschen lesbar), benötigen möglicherweise auch eine reguläre Datei (z. B. wenn sie fseek ).

Das Argument würde in Konflikt geraten, sobald kdb import/export mehrere Plugins unterstützt.

Wir könnten leicht dazu übergehen, die Optionen -i FILE, --input=FILE , -o FILE, --ouput=FILE wenn wir zu elektraGetOpts wechseln.

Ja, wir können -i, -o Optionen hinzufügen. Aber die Plugins (oder das Import / Export-Framework) so zu reparieren, dass auch stdin / stdout funktioniert, wäre auf jeden Fall schön.

Um dieses Problem mit kdb export zu beheben, reicht es aus, die Problemumgehung in der Funktion plugin-> kdbSet () zu implementieren. Ich habe dies bereits implementiert, PR wird bald kommen.

Dies funktioniert jetzt: kdb import user/tests/ mmapstorage < test.mmap ,
aber das geht nicht: cat test.mmap | kdb import user/tests/ mmapstorage , da mmap wieder nicht damit umgehen kann.

Um die Lösung konsistent zu machen (und somit vollständig mit nicht regulären Dateien kompatibel zu sein), müsste sie auch für die Funktion kdbGet () gelöst werden. Hierfür gibt es ungefähr drei Lösungen:

  1. schreibe in ein tempfile und hebe die Verknüpfung auf (etwas hässliche, aber einfache Lösung)
  2. Überarbeitung der Hälfte meiner mmap-Arbeit (hässlich & viel Arbeit)
  3. Erstellen Sie viele Kopien und implementieren Sie ksDeepDup erneut, um auch Kopien von Meta-Keysets zu erstellen (wirklich hässlicher, halb einfacher Code).

Ist irgendetwas davon wünschenswert oder ignorieren wir es?

Ich denke, wir können es vorerst ignorieren, da wir bereits einen QuickDump haben. Dokumentieren Sie es einfach als nicht für die Serialisierung geeignet. Wir werden jetzt das Import / Export-Framework trotzdem überarbeiten und dann eine geeignete Lösung finden. @mpranj Ich habe dich

Eigentlich ist es vielleicht besser, wenn # 2639 dieses Problem schließt und @mpranj ein neues für das Problem cat ... .

2639 schließt hier alle Probleme. Es funktioniert gut unter Linux, ich muss nur einen Fehler beheben, damit es auch auf den BSDs funktioniert.

Ich hatte eine wirklich schöne Lösung (mit realpath und stat ), die bei BSDs leider nicht funktioniert. Es macht keinen Sinn, viel mehr Zeit in sie zu investieren.

Ich habe beschlossen, es wegzuwerfen, damit mmapstorage nicht vollständig mit nicht regulären Dateien kompatibel ist. Es funktioniert nur mit kdb Import / Export. Die neue Lösung überprüft einfach, ob der kdb-Import / Export verwendet wird, indem überprüft wird, ob die Datei " /dev/stdin " oder " /dev/stdout " ist. Ähnlich verhält es sich in quickdump .

Ich hatte eine wirklich schöne Lösung (mit realpath und stat), die auf BSDs leider nicht funktioniert.

Dies ist die auskommentierte Lösung?

Es macht keinen Sinn, viel mehr Zeit in sie zu investieren.

Sie haben Recht, das Framework sollte damit umgehen. Ich habe # 2640 erstellt.

funktioniert nur mit kdb import / export

Auch mit der Variante cat | kdb import ?

Ähnlich verhält es sich mit QuickDump.

Wo sind die Unterschiede?

Kann dieser Code in das Import / Export-Framework verschoben werden?

Dies ist die auskommentierte Lösung?

Ich habe es in der Geschichte belassen, aber die Zeilen später entfernt. Die imho bessere Lösung war bis https://github.com/ElektraInitiative/libelektra/pull/2639/commits/a523f9b38b56687d532f5101c7ef44c078e2308d. Beachten Sie, dass es unter Linux gut funktioniert hat, aber nicht unter BSD.

Ein Problem, auf das ich gestoßen bin, ist, dass stdin / stdout auf BSDs nicht geöffnet () sein kann. Das andere ist, dass Sie wirklich den Realpath verwenden müssen, um die Datei zu stat () und festzustellen, ob es sich um eine reguläre Datei handelt. Ansonsten hat stat nur eine Ebene von Symlinks für mich aufgelöst. Dieser Ansatz schlug bei BSDs für mich fehl, weil realpath irgendwie in eine nicht vorhandene Datei aufgelöst wurde.

Auch mit der Katze | kdb import variante?

Ja!

Wo sind die Unterschiede?

Der relevante Teil ist der gleiche, entschuldigen Sie die Verwirrung. Was ich damit gemeint habe ist, dass wir strcmp für / dev / stdin verwenden, anstatt stat zu verwenden, um festzustellen, ob es sich um eine reguläre Datei handelt. Das bedeutet, dass es immer noch fehlschlägt, wenn wir / dev / fd / verwenden.. Meine andere Lösung verwendete stat anstelle von strcmp, sodass es mit jedem Pfad funktionierte.

Bearbeiten :

Kann dieser Code in das Import / Export-Framework verschoben werden?

Ja, ich denke, der Code war fast vollständig vorhanden, aber ich hatte keine Zeit, die BSD-Probleme richtig zu beheben.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

markus2330 picture markus2330  ·  4Kommentare

markus2330 picture markus2330  ·  4Kommentare

mpranj picture mpranj  ·  3Kommentare

mpranj picture mpranj  ·  3Kommentare

mpranj picture mpranj  ·  4Kommentare