Opened 14 years ago
Closed 14 years ago
#1069 closed enhancement (fixed)
Error al guardar un archivo muy pesado
Reported by: | imendez | Owned by: | Víctor de Buen Remiro |
---|---|---|---|
Priority: | highest | Milestone: | Mantainance |
Component: | OIS | Version: | 2.0.1 |
Severity: | blocker | Keywords: | |
Cc: | atorre@…, irobles@… |
Description
Hola, al intentar guardar en un fichero .oza un objeto muy pesado, ocurren dos cosas nada deseables:
- Da un error por falta de memoria ("not enough memory").
- Crea el archivo con 0 KB.
Respecto a lo primero: ¿no es posible liberar memoria conforme se va realizando el volcado?
En cuanto a lo segundo, si el archivo ya existía lo borra y por tanto se pierden ambos, tanto el antiguo como el nuevo (que crea con 0 KB). ¿Se puede hacer que, si da error, mantenga el archivo anterior?
No tengo ahora mismo ningún ejemplo que permita reproducirlo rápidamente, pero es tan sencillo como crear un objeto TOL muy pesado (pero que TOL "soporte") e intentar guardarlo con Ois.Store
Muchas gracias.
Change History (7)
comment:1 Changed 14 years ago by
Status: | new → accepted |
---|
comment:2 Changed 14 years ago by
Buenos días,
para reproducirlo con un código simple:
Matrix a = Rand(100000,300,0,1); Set b = [[a, a*2]]; Real Ois.Store(b, "C:/matriz.oza");
Espero que sirva este ejemplo.Nos pasa al guardar otro objeto, pero creo que lo que esta pasando internamente es algo similar a este ejemplo.
Si no os vale con esto, os pasamos el código que nos esta dando problemas, pero se necesita tener instalado MMS
Un cordial saludo
comment:3 Changed 14 years ago by
Milestone: | → Mantainance |
---|---|
Type: | defect → enhancement |
Lo que se propone como solución es una nueva función de creación de OIS que según los parámetros puede hacer ditintas cosas
1 | directorio plano | Real Ois.StoreEngine(b, "matriz", "");
|
2 | OZA en RAM | Real Ois.StoreEngine(b, "matriz.oza", "");
|
3 | OZA con direcotrio temporal | Real Ois.StoreEngine(b, "matriz.oza", "ZipArchive");
|
cuando tengamos más motores podrá hacer otras más.
El problema era que lo que tenemos de ZipArchive en OIS usa la clase CZipMemFile de ZipArchive que no hace volcados a disco hasta el final así que tiene que estar todo en RAM al mismo tiempo por eso si el Set
es muy grande es necesario crear el OZA como un directorio temporal, luego comprimir por fuera usando PackArchive
y después borrar ese directorio temporal.
El resultado es el mismo que usando CZipMemFile así que el Ois.Load lo lee igual sin embargo, para ficheros muy grandes pasa lo mismo y hay que descomprimir primero, cargar el OIS del directorio plano y borrarlo después.
comment:4 Changed 14 years ago by
Resolution: | → fixed |
---|---|
Status: | accepted → closed |
comment:5 Changed 14 years ago by
Resolution: | fixed |
---|---|
Status: | closed → reopened |
Reabro el tique para revisar el método Ois.StoreEngine
generado aquí.
En su versión "ZipArchive" el método escribe el OIS no archivado (como carpeta) en la misma ruta donde luego creará el OZA. Si esto es una ruta remota el trabajo será triple, llevar allí los archivos sin comprimir, traerlos convenientemente a RAM para comprimirlos y llevarlo allí de nuevo comprimido. Se sugiere cambiar el lugar donde se ubica temporalmente la carpeta a una ruta local.
También se sugiere comprobar la no existencia de la ruta (versión carpeta del ois) antes de escribir en ella, y por supuesto de borrarla. Ya que puede borrar algo que no le corresponde, sobre todo a causa del comportamiento inadecuado de la función GetFilePrefix
(véase #1089).
comment:6 Changed 14 years ago by
Lo de crear el directorio temporal en local es sencillo, estoy en ello.
El path donde le mandan escribir puede existir o no y si existe puede que le sirva a alguien o no, no hay forma de saberlo desde dentro. Es imposible que esta función ni ninguna otra evite que el usuario le pida cosas que realmente no quiere hacer. Si el usuario le dice que guarde ahí tiene que hacerle caso, es responsabilidad del ordenante comprobar lo que haya que comprobar.
Otra cosa es que haya un error en GetFilePrefix
que produzca confusiones, eso se arregla y ya está. Cuando se hizo esa función los nombres de los archivos tenían un sólo punto y una extensión de tres letras, así que es normal que no se previera este problema.
comment:7 Changed 14 years ago by
Resolution: | → fixed |
---|---|
Status: | reopened → closed |
Nunca me ha pasado tal cosa y he guradado en OIS cosas muy gordas.
Los errores de memoria no pueden ser previstos y cuando ocurren ya no hay nada que hacer. Si quieres hacer copias de seguridad eso no es tarea de OIS, debes hacerlo tú. Renombra el antiguo antes o lo mandas a un directorio de backup.
Para saber qué memoria liberar tendría que poder reproducirlo para observar dónde se está gastando, o al menos saber qué tipo de objetos es el que está gastando esa RAM en el proceso de guardado. Quizás viendo el código o el proceso antes del guardado podría hacerme una idea.