Libelektra: mmapstorage не работает с экспортом kdb

Созданный на 15 февр. 2019  ·  22Комментарии  ·  Источник: ElektraInitiative/libelektra

Шаги по воспроизведению проблемы

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

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

ожидаемый результат

Создается файл с именем test.mmap , который можно повторно импортировать с помощью kdb import .

Фактический результат

Создается пустой файл с именем test.mmap и печатается следующее сообщение (включая журналы из 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

Системная информация

  • Электра Версия: мастер

Дальнейшая информация

~ Работает, когда kdb export вызывается как root. ~ (EDIT: см. Комментарий ниже) kdb export user/tests/hello mmapstorage test.mmap также работает, но это полностью недокументированная функция kdb export . Так что более подробное сообщение об ошибке и обновленная документация могут быть всем, что нам нужно.

Самый полезный комментарий

Спасибо за ваш ответ!

Сообщения об ошибках mmap могут вводить в заблуждение.

Пожалуйста, исправьте сообщения об ошибках.

Насколько мне известно, это не будет работать на stdout. Так же не работает с трубами

Добавьте эту информацию в сообщения об ошибках.

Приведенные выше решения не сильно меняют логику mmapstorage.

Поскольку ваш плагин в настоящее время является единственным затронутым, имеет смысл выполнить статистику и скопировать все, если необходимо. Тогда мы могли бы закрыть эту проблему без больших изменений в структуре.

Все 22 Комментарий

Спасибо, что попробовали это и за этот подробный отчет!

Так что более подробное сообщение об ошибке и обновленная документация могут быть всем, что нам нужно.

Да, полностью согласен.

Может быть, нам даже стоит иметь serializable в infos / status # 666 и явно терпеть неудачу, если файл / dev / stdout? ( @mpranj Или есть способ определить, не поддерживает ли файл mmapable? Действительно ли он идентичен запрещенному разрешению?)

Глядя на код (и сообщение об ошибке), я думаю, что текущая проблема в том, что мы не можем вызвать unlink для stdout без корневого доступа. Также open , вероятно, тоже не сработает, потому что stdout уже открыт. И то, является ли stdout mmapable, зависит от того, к чему, я думаю, подключен stdout .
Использование fstat(fileno(stdout), &stat) чтобы проверить, может ли это обычный файл работать. Может быть, isatty(3) тоже работает.

В любом случае мы могли бы просто проверить, является ли выходной файл /dev/stdout (или CON для _WIN32 ) и создать временный файл для использования с mmap, а затем просто скопировать его в stdout . Конечно, это будет медленнее, но мы сохраним возможность передачи вывода kdb export по конвейеру.

Может быть, нам даже стоит иметь serializable в infos / status # 666 и явно терпеть неудачу, если файл / dev / stdout?

Во всяком случае, у меня будет статус humanreadable и я откажусь от экспорта в tty stdout, если формат не читается человеком.

Работает, когда kdb export вызывается от имени root.

Я беру это обратно ... НЕ ПЫТАЙТЕСЬ ЭТО! Вызов kdb export <something> mmapstorage от имени пользователя root (даже если stdout перенаправлен) уничтожает /dev/stdout . Использование /dev/stdout (например, через fopen ) не будет работать в вашей системе, пока вы не воссоздадите символическую ссылку по умолчанию с помощью sudo rm /dev/stdout && sudo ln -s /dev/stdout /proc/self/fd/1 .

Я думаю, что лучшим решением будет то, что kdb export и kdb import всегда работают с временными файлами. Тогда kdb export будет больше похоже на то, что делает KDB. Это решит проблему отсоединения (которая необходима для файлов mmaped). Обратной стороной является только потеря производительности (требуется копия всего содержимого), но тогда импорт / экспорт будет работать со всеми плагинами хранилища, что, по-моему, гораздо важнее.

Я думаю, что лучшим решением будет то, что kdb export и kdb import всегда работают с временными файлами.

Я думаю, плагины должны сами создавать временный файл, если это необходимо. Таким образом мы избегаем снижения производительности плагинов, которые могут напрямую выводить данные в TTY. AFAIK mmapstorage в настоящее время является единственным плагином, который не работает с TTY. Мы также могли бы добавить простой тест оболочки, который гарантирует, что все плагины хранилища могут быть вызваны через kdb export /some/key plugin > export.file . Логика также более автономна, потому что на самом деле плагины обязаны знать, как произвести ожидаемый результат.

Также для kdb import временные файлы не нужны, потому что чтение файла всегда должно работать, даже для TTY (если у вас есть правильные разрешения).

Я думаю, плагины должны сами создавать временный файл, если это необходимо.

Затем плагины (или, точнее, mmap) должны будут знать, используется ли он в KDB или kdb export .

@mpranj Каково ваше мнение? Можно ли это исправить с помощью плагина mmap?

Таким образом мы избегаем снижения производительности плагинов, которые могут напрямую выводить данные в TTY.

В каких случаях это снижение производительности является проблемой? Может быть, в резервной копии / восстановлении для каждого теста?

AFAIK mmapstorage в настоящее время является единственным плагином, который не работает с TTY.

На экспорт да. Но для импорта у нас было несколько плагинов, которые не работают. Если плагин использует fseek или аналогичный, он явно не может работать, например csvstorage или mozprefs. (дамп теперь должен быть исправлен)

Мы также могли бы добавить простой тест оболочки, который гарантирует, что все плагины хранения могут быть вызваны через kdb export / some / key plugin> export.file.

Вы имеете ввиду tests / shell / check_export.sh строка 46?

В каких случаях это снижение производительности является проблемой?

На самом деле, наверное, никогда. Пока вы используете 3-х аргументные версии экспорта / импорта вместо конвейера. См. Предложение ниже.

Вы имеете ввиду tests / shell / check_export.sh строка 46?

Да, но это не работает, потому что is_not_rw_storage не работает. Даже dump не распознается как плагин хранилища.


Я думаю, чтобы решить эту проблему быстро и легко, мы должны сделать следующее:

  1. Исправьте is_not_rw_storage в include_common.sh.in tests/shell/check_export.sh чтобы мы могли обнаруживать подобные проблемы в будущем.
  2. В kdb export создать временный файл, только если не указан третий аргумент. Используйте этот файл в вызовах kdbSet а затем скопируйте его содержимое в стандартный вывод (не более одной или двух строк в C ++).
  3. Аналогично для kdb import создайте временный файл, если используется stdin. Скопируйте весь стандартный ввод во временный файл и используйте этот файл для вызова kdbGet .
  4. Обновите документацию для kdb import и kdb export чтобы указать, что существует третий аргумент. Также укажите, что если используется версия с двумя аргументами, мы создаем временный файл.

PS. Это может быть good first issue

Спасибо, что сообщили, что is_not_rw_storage не работает, я открыл # 2423

Извините , меня не было на неделю, поэтому я не мог разобраться в этом.

Сообщения об ошибках mmap могут вводить в заблуждение. mmap() не работает с EACCES при попытке сопоставить нестандартные файлы. Насколько мне известно, это не будет работать на stdout. Он также не работает с трубами, как обсуждалось в # 2209.

Из POSIX:

Функция mmap () должна поддерживаться для следующих объектов памяти:

  • Обычные файлы
  • [SHM] Объекты общей памяти
  • [TYM] Типизированные объекты памяти

Что касается решений в mmapstorage, мы можем проверить, является ли это обычным файлом с stat а затем:

  • записать во временный обычный файл, как предложено выше
  • запись во временную ячейку памяти (просто malloc вместо mmap), а затем копирование в нестандартный файл (pipe, stdout, ..)

Я открыт и для других решений. Приведенные выше решения не сильно меняют логику mmapstorage. Переделка mmapstorage для работы с конвейерами или stdout напрямую не имеет для меня особого смысла.

Спасибо за ваш ответ!

Сообщения об ошибках mmap могут вводить в заблуждение.

Пожалуйста, исправьте сообщения об ошибках.

Насколько мне известно, это не будет работать на stdout. Так же не работает с трубами

Добавьте эту информацию в сообщения об ошибках.

Приведенные выше решения не сильно меняют логику mmapstorage.

Поскольку ваш плагин в настоящее время является единственным затронутым, имеет смысл выполнить статистику и скопировать все, если необходимо. Тогда мы могли бы закрыть эту проблему без больших изменений в структуре.

Тогда мы могли бы закрыть эту проблему без больших изменений в структуре.

Мы также должны обновить страницы руководства для kdb import и kdb export . В настоящее время они не упоминают версии с 3 аргументами, которые не зависят от stdin / stdout.

Благодарим вас за сообщение о проблеме и за ваш вклад!

К сожалению, strerror выводит эти вводящие в заблуждение сообщения об ошибках. В этом случае я могу добавить подсказку.

На этой неделе я внесу требуемые изменения в PR.

Мы также должны обновить справочные страницы для импорта и экспорта kdb. В настоящее время они не упоминают версии с 3 аргументами, которые не зависят от stdin / stdout.

Может нам не нужен аргумент для указания файла? Аргумент будет конфликтовать, если kdb import/export поддерживает несколько плагинов.

На этой неделе я внесу требуемые изменения в PR.

Спасибо!

Может нам не нужен аргумент для указания файла?

Затем мы должны поддерживать stdin и stdout (перенаправленные на обычный файл) во всех плагинах. В противном случае их нельзя было бы использовать с kdb import/export . Это делает разумным для mmapstorage потому что он не переносится, но и другие переносимые плагины (возможно, даже читаемые человеком) могут также нуждаться в обычном файле (например, если они используют fseek ).

Аргумент будет конфликтовать, если kdb import/export поддерживает несколько плагинов.

Мы могли бы легко перейти к использованию параметров -i FILE, --input=FILE , -o FILE, --ouput=FILE когда переключимся на использование elektraGetOpts .

Да, мы можем добавить параметры -i, -o. Но исправление плагинов (или структуры импорта / экспорта), чтобы также работал stdin / stdout, в любом случае было бы неплохо.

Чтобы решить эту проблему с помощью kdb export достаточно реализовать обходной путь в функции plugin-> kdbSet (). Я это уже реализовал, скоро PR.

Теперь это работает: kdb import user/tests/ mmapstorage < test.mmap ,
но это не так: cat test.mmap | kdb import user/tests/ mmapstorage , так как снова mmap не может с этим справиться.

Чтобы решение было согласованным (а значит, полностью совместимым с нестандартными файлами), необходимо было бы решить его и для функции kdbGet (). Для этого есть примерно три решения:

  1. напишите во временный файл и отключите его (несколько уродливое, но простое решение)
  2. переделать половину моей работы с mmap (уродливо и много работы)
  3. сделайте много копий и переопределите ksDeepDup, чтобы также сделать копии мета-ключей (действительно уродливый, полупростой код)

Желательно ли это или мы игнорируем это?

Думаю, пока мы можем проигнорировать это, так как у нас уже есть квикдамп. Просто задокументируйте его как неподходящий для сериализации. Мы сейчас все равно переделаем структуру импорта / экспорта, а затем найдем подходящее решение. @mpranj Я

На самом деле, может быть лучше, если # 2639 закроет эту проблему, а @mpranj вы cat ... .

2639 закрывает здесь все проблемы. Он отлично работает в Linux, мне просто нужно исправить ошибку, чтобы он работал и на BSD.

У меня было действительно хорошее решение (с использованием realpath и stat ), которое, к сожалению, не будет работать на BSD. Нет смысла тратить на это много времени.

Я решил выбросить его, чтобы не сделать mmapstorage полностью совместимым с нестандартными файлами. Он будет работать только с импортом / экспортом kdb. Новое решение просто проверяет, используется ли импорт / экспорт kdb, проверяя, является ли файл « /dev/stdin » или « /dev/stdout ». Аналогично это делается в quickdump .

У меня было действительно хорошее решение (с использованием realpath и stat), которое, к сожалению, не будет работать на BSD.

Это закомментированное решение?

Нет смысла тратить на это много времени.

Вы правы, фреймворк должен с этим справиться. Я создал # 2640.

будет работать только с импортом / экспортом kdb

Также с вариантом cat | kdb import ?

Аналогично это делается в quickdump.

Где отличия?

Можно ли переместить этот код в структуру импорта / экспорта?

Это закомментированное решение?

Я оставил это в истории, но удалил строки позже. Лучшее решение imho было до https://github.com/ElektraInitiative/libelektra/pull/2639/commit/a523f9b38b56687d532f5101c7ef44c078e2308d. Обратите внимание, что он хорошо работал в Linux, но не в BSD.

Одна проблема, с которой я столкнулся, заключается в том, что stdin / stdout не может быть open () ed на BSD. Во-вторых, вам действительно нужно использовать реальный путь для stat () файла и определить, является ли он обычным файлом. В противном случае stat разрешил для меня только один уровень символических ссылок. Этот подход не удался для меня в BSD, потому что realpath каким-то образом разрешается в несуществующий файл.

Тоже с кошкой | вариант импорта kdb?

Да!

Где отличия?

Соответствующая часть такая же, извините за путаницу. Я имел в виду, что мы strcmp для / dev / stdin вместо использования stat, чтобы определить, является ли это обычным файлом. Это означает, что он все равно не сработает, если мы будем использовать / dev / fd /. В другом моем решении используется stat вместо strcmp, поэтому он работает с любым путем.

Редактировать :

Можно ли переместить этот код в структуру импорта / экспорта?

Да, я думаю, что код был почти полностью там, но у меня не было времени исправлять проблемы BSD должным образом.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

markus2330 picture markus2330  ·  4Комментарии

dmoisej picture dmoisej  ·  3Комментарии

sanssecours picture sanssecours  ·  3Комментарии

mpranj picture mpranj  ·  3Комментарии

sanssecours picture sanssecours  ·  3Комментарии