kdb set user/tests/hello world
#> Create a new key user/tests/hello with string "world"
kdb export user/tests/hello mmapstorage > test.mmap
Se crea un archivo llamado test.mmap
, que se puede volver a importar con kdb import
.
Se crea un archivo vacío llamado test.mmap
y se imprime el siguiente mensaje (incluye registros de 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
~ Funciona cuando se llama a kdb export
como root. ~ (EDITAR: ver comentario a continuación) kdb export user/tests/hello mmapstorage test.mmap
también funciona, pero es una característica completamente indocumentada de kdb export
. Entonces, un mejor mensaje de error y documentación actualizada podría ser todo lo que necesitamos.
¡Gracias por probar esto y por este informe detallado!
Entonces, un mejor mensaje de error y documentación actualizada podría ser todo lo que necesitamos.
Sí, estoy totalmente de acuerdo.
¿Quizás incluso deberíamos tener un serializable
en infos / status # 666 y fallar explícitamente si el archivo es / dev / stdout? ( @mpranj ¿ O hay alguna manera de detectar si un archivo no es mmapable? ¿Es realmente idéntico a un permiso denegado?)
Mirando el código (y el mensaje de error), creo que el problema actual es que no podemos llamar a unlink
en stdout
sin acceso de root. Además, open
probablemente también fallará, porque stdout
ya está abierto. Y si stdout
es mmapable o no depende de lo que stdout
esté conectado, creo.
Usar fstat(fileno(stdout), &stat)
para verificar si es un archivo normal podría funcionar. Quizás isatty(3)
también funcione.
En cualquier caso, podríamos simplemente verificar si el archivo de salida es /dev/stdout
(o CON
por _WIN32
) y crear un archivo temporal para usar con mmap y luego simplemente copiarlo en stdout
. Por supuesto, sería más lento pero mantendríamos la posibilidad de canalizar la salida de kdb export
.
¿Quizás incluso deberíamos tener un
serializable
en infos / status # 666 y fallar explícitamente si el archivo es / dev / stdout?
En todo caso, tendría un estado humanreadable
y me negaría a exportar a un stdout tty, si el formato no es legible por humanos.
Funciona cuando se llama a
kdb export
como root.
Retiro eso ... ¡NO INTENTE ESO! Llamar a kdb export <something> mmapstorage
como usuario root (incluso si se redirige stdout) destruye /dev/stdout
. El uso de /dev/stdout
(por ejemplo, a través de fopen
) no funcionará en su sistema hasta que vuelva a crear el enlace simbólico predeterminado con sudo rm /dev/stdout && sudo ln -s /dev/stdout /proc/self/fd/1
.
Creo que la mejor solución es que kdb export
y kdb import
siempre funcionan en archivos temporales. Entonces kdb export
será más similar a lo que hace KDB. Esto resolvería el problema de desvinculación (que es necesario para archivos mmaped). La desventaja es solo la pérdida de rendimiento (se necesita una copia de todo el contenido), pero luego la importación / exportación funcionará con todos los complementos de almacenamiento, lo cual es en mi humilde opinión mucho más importante.
Creo que la mejor solución es que
kdb export
ykdb import
siempre funcionan en archivos temporales.
Creo que los complementos deberían crear el archivo temporal ellos mismos, si es necesario. De esa forma, evitamos las penalizaciones de rendimiento de los complementos que pueden enviar directamente a TTY. AFAIK mmapstorage
es actualmente el único complemento que no funciona con TTY. También podríamos agregar una prueba de shell simple que garantice que todos los complementos de almacenamiento se puedan llamar a través de kdb export /some/key plugin > export.file
. La lógica también es más autónoma, porque realmente es responsabilidad de los complementos saber cómo producir el resultado esperado.
Además, para kdb import
los archivos temporales son innecesarios porque leer un archivo siempre debería funcionar, incluso para TTY (si tiene los permisos correctos).
Creo que los complementos deberían crear el archivo temporal ellos mismos, si es necesario.
Entonces los complementos (o más específicamente mmap) necesitarían saber si se usa dentro de KDB o kdb export
.
@mpranj ¿Cuál es tu opinión? ¿Se puede solucionar esto dentro del complemento mmap?
De esa forma, evitamos las penalizaciones de rendimiento de los complementos que pueden enviar directamente a TTY.
¿En qué casos es un problema esta penalización por desempeño? ¿Quizás en la copia de seguridad / restauración para cada caso de prueba?
AFAIK mmapstorage es actualmente el único complemento que no funciona con TTY.
Para exportar si. Pero para la importación teníamos varios complementos que no funcionan. Si un complemento usa fseek o similar, obviamente no puede funcionar, por ejemplo, csvstorage o mozprefs. (el volcado ahora debería estar arreglado)
También podríamos agregar una prueba de shell simple que garantice que todos los complementos de almacenamiento se puedan llamar a través de kdb export / some / key plugin> export.file.
¿Te refieres a tests / shell / check_export.sh línea 46?
¿En qué casos es un problema esta penalización por desempeño?
De hecho, probablemente nunca. Siempre que utilice las versiones de 3 argumentos de exportación / importación en lugar de canalizar. Vea la propuesta a continuación.
¿Te refieres a tests / shell / check_export.sh línea 46?
Sí, pero eso está roto, porque is_not_rw_storage
no funciona. Ni siquiera dump
se reconoce como un complemento de almacenamiento.
Creo que para solucionar esto rápida y fácilmente deberíamos hacer lo siguiente:
is_not_rw_storage
en include_common.sh.in
tests/shell/check_export.sh
para que detectemos problemas como este en el futuro.kdb export
cree un archivo temporal, solo si no se proporciona un tercer argumento. Utilice este archivo en las llamadas kdbSet
y luego copie, imprima su contenido en la salida estándar (no debe tener más de una o dos líneas en C ++).kdb import
cree un archivo temporal si se usa stdin. Copie todo stdin en el archivo temporal y use este archivo para llamar a kdbGet
.kdb import
y kdb export
para indicar que existe el tercer argumento. Indique también que si se usa la versión de dos argumentos, creamos un archivo temporal.PD. Esto podría ser good first issue
Gracias por informar que is_not_rw_storage está roto, abrí # 2423
Lo siento , estuve fuera una semana, así que no pude investigarlo.
Los mensajes de error de mmap pueden ser engañosos. mmap()
falla con EACCES
al intentar mapear archivos no regulares. Que yo sepa, no funcionará en stdout. Tampoco funciona con tuberías, como se explica en el n. ° 2209.
Desde POSIX:
La función mmap () será compatible con los siguientes objetos de memoria:
- Archivos regulares
- [SHM] Objetos de memoria compartida
- [TYM] Objetos de memoria escritos
En cuanto a las soluciones dentro de mmapstorage, podemos verificar si es un archivo normal con stat
y luego:
También estoy abierto a otras soluciones. Las soluciones anteriores no cambian mucho la lógica de mmapstorage. Reelaborar mmapstorage para trabajar con tuberías o stdout directamente no tiene mucho sentido para mí.
¡Gracias por su respuesta!
Los mensajes de error de mmap pueden ser engañosos.
Mejore los mensajes de error.
Que yo sepa, no funcionará en stdout. Tampoco funciona con tuberías.
Agregue esa información a los mensajes de error.
Las soluciones anteriores no cambian mucho la lógica de mmapstorage.
Como su complemento es actualmente el único afectado, tiene sentido que haga la estadística y copie todo si es necesario. Entonces podríamos cerrar este problema sin mayores cambios en el marco.
Entonces podríamos cerrar este problema sin mayores cambios en el marco.
También deberíamos actualizar las páginas de manual para kdb import
y kdb export
. Actualmente no mencionan las 3 versiones de argumentos que no se basan en stdin / stdout.
¡Gracias por informar del problema y por los comentarios!
Desafortunadamente, strerror
imprime estos mensajes de error engañosos. Puedo agregar una pista en ese caso.
Haré los cambios solicitados en un PR esta semana.
También deberíamos actualizar las páginas man para kdb import y kdb export. Actualmente no mencionan las 3 versiones de argumentos que no se basan en stdin / stdout.
¿Quizás no necesitamos el argumento para especificar el archivo? El argumento entraría en conflicto una vez que kdb import/export
admita múltiples complementos.
Haré los cambios solicitados en un PR esta semana.
¡Gracias!
¿Quizás no necesitamos el argumento para especificar el archivo?
Luego, tenemos que admitir stdin
y stdout
(redirigidos a un archivo normal) en todos los complementos. De lo contrario, nunca podrían usarse con kdb import/export
. Eso tiene sentido para mmapstorage
porque no es portátil, pero otros complementos que son portátiles (tal vez incluso legibles por humanos) también pueden necesitar un archivo normal (por ejemplo, si usan fseek
).
El argumento entraría en conflicto una vez que
kdb import/export
admita múltiples complementos.
Podríamos pasar fácilmente a usar las opciones -i FILE, --input=FILE
, -o FILE, --ouput=FILE
cuando cambiemos a usar elektraGetOpts
.
Sí, podemos agregar las opciones -i, -o. Pero arreglar los complementos (o el marco de importación / exportación) para que también funcione stdin / stdout sería bueno en cualquier caso.
Para solucionar este problema con kdb export
es suficiente implementar la solución en la función plugin-> kdbSet (). Ya he implementado esto, PR pronto vendrá.
Esto funciona ahora: kdb import user/tests/ mmapstorage < test.mmap
,
pero esto no: cat test.mmap | kdb import user/tests/ mmapstorage
, ya que nuevamente mmap no puede manejarlo.
Para que la solución sea consistente (por lo tanto, completamente compatible con archivos no regulares) también sería necesario resolverla para la función kdbGet (). Hay aproximadamente tres soluciones para esto:
¿Es algo de esto deseable o lo ignoramos?
Creo que podemos ignorarlo por ahora, ya que tenemos quickdump. Simplemente documente que no es adecuado para la serialización. Ahora volveremos a trabajar el marco de importación / exportación de todos modos, luego encontraremos una solución adecuada. @mpranj Te
En realidad, quizás sea mejor si # 2639 cierra este problema y @mpranj crea uno nuevo para el problema cat ...
.
Tuve una solución realmente agradable (usando realpath
y stat
) que desafortunadamente no funcionará en BSD. No tiene sentido invertir mucho más tiempo en ello.
He decidido tirarlo, por lo que mmapstorage no es completamente compatible con archivos no regulares. Solo funcionará con kdb import / export. La nueva solución simplemente comprobará si se utiliza kdb import / export, comprobando si el archivo es " /dev/stdin
" o " /dev/stdout
". Se hace de manera similar en quickdump
.
Tuve una solución realmente buena (usando realpath y stat) que desafortunadamente no funcionará en BSD.
¿Esta es la solución comentada?
No tiene sentido invertir mucho más tiempo en ello.
Tienes razón, el marco debería manejar esto. Creé el # 2640.
solo funcionará con kdb import / export
¿También con la variante cat | kdb import
?
Se hace de manera similar en quickdump.
¿Dónde están las diferencias?
¿Se puede mover este código al marco de importación / exportación?
¿Esta es la solución comentada?
Lo dejé en la historia pero eliminé las líneas más tarde. La mejor solución en mi humilde opinión fue hasta https://github.com/ElektraInitiative/libelektra/pull/2639/commits/a523f9b38b56687d532f5101c7ef44c078e2308d. Tenga en cuenta que funcionó bien en Linux pero no en BSD.
Un problema que encontré es que stdin / stdout no se puede abrir () ed en BSD. La otra es que realmente tienes que usar la ruta real para stat () el archivo y determinar si es un archivo normal. De lo contrario, las estadísticas solo resolvieron un nivel de enlaces simbólicos para mí. Este enfoque falló en los BSD para mí, porque realpath se resolvió de alguna manera en un archivo inexistente.
También con el gato | variante de importación kdb?
¡Sí!
¿Dónde están las diferencias?
La parte relevante es la misma, perdón por la confusión. Lo que quise decir es que strcmp para / dev / stdin en lugar de usar stat para determinar si es un archivo normal. Eso significa que aún fallará si usamos / dev / fd /
Editar :
¿Se puede mover este código al marco de importación / exportación?
Sí, creo que el código estaba casi por completo, pero no tuve tiempo de solucionar los problemas de BSD correctamente.
Comentario más útil
¡Gracias por su respuesta!
Mejore los mensajes de error.
Agregue esa información a los mensajes de error.
Como su complemento es actualmente el único afectado, tiene sentido que haga la estadística y copie todo si es necesario. Entonces podríamos cerrar este problema sin mayores cambios en el marco.