1 #LyX 1.3 created this file. For more info see http://www.lyx.org/
11 \paperpackage widemarginsa4
15 \use_numerical_citations 0
16 \paperorientation portrait
19 \paragraph_separation indent
21 \quotes_language english
25 \paperpagestyle default
30 \begin_inset Formula $\mu$
61 es la estuctura principal que encapsula todas las funciones para el manejo
62 de un archivo de datos.
65 Esta estructura consta de:
68 EMUFS_Tipo que es un tipo enumerado que indica cual es la organización.
71 EMUFS_BLOCK_SIZE indica el tamaño del bloque para los tipos 1 y 3.
74 EMUFS_REG_SIZE indica el tamaño del registro, para el tipo 3 que posee tamaño
81 no me convence esta descripcion.
98 \begin_inset LatexCommand \label{sec:cabecera_gral}
102 Organización física general de un archivo E
103 \begin_inset Formula $\mu$
110 \begin_inset Formula $\mu$
113 FS está compuesto por 4 archivos a nivel de sistema operativo: archivo de
114 datos (con 3 formatos posibles, ver páginas
115 \begin_inset LatexCommand \pageref{cha:tipo1}
120 \begin_inset LatexCommand \pageref{cha:tipo2}
125 \begin_inset LatexCommand \pageref{cha:tipo3}
129 ), archivo de índice (ver página
130 \begin_inset LatexCommand \pageref{sec:idx}
134 ), archivo de control de espacio libre (ver página
135 \begin_inset LatexCommand \pageref{sec:fsc}
139 ) y archivo de índices recuperables (ver página
140 \begin_inset LatexCommand \pageref{sec:did}
147 El archivo de datos está compuesto por:
158 (4 bytes en plataformas Linux de 32 bits) que representa el tipo de archivo.
161 Datos dependientes del tipo de archivo.
168 es utilizada para poder detectar el formato de un archivo al abrirlo.
169 Los datos dependientes del tipo de archivo serán explicados en sus secciones
176 +-----------+--------------------------------------------//-+
179 | tipo | Datos dependientes del tipo de archivo ...
187 +-----------+--------------------------------------------//-+
196 Por que los 3 tipos usan lo mismo.
197 Ventajas y desventajas.
201 \begin_inset LatexCommand \label{sec:idx}
208 Con la ayuda de un archivo de bloques y registros (de extensión .idx), podremos
209 ubicar cualquier registro existente dentro del archivo.
212 El archivo de índice contiene una estructura que contiene el id de un registro
213 y el número de bloque al que pertenece.
214 Este archivo esta ordenado por
218 , de modo que incrementa su tamaño cada vez que se grabe en el archivo de
219 datos un nuevo registro, excepto que un registro haya sido borrado con
220 anterioridad lo cual produce que al guardar un nuevo registro se actualice
224 Si un registro es borrado del archivo de datos, debe actualizarse el índice,
225 esto se logra colocando un flag que indique que el id no pertenece a ningún
226 bloque, hemos adoptado poner -1 en el campo location de la estructura
233 Es necesario que este archivo esté ordenado por
237 de registro, ya que esto permitirá el acceso directo para la búsqueda de
238 un registro en el archivo de datos.
244 El tipo EMUFS_IDX define la estuctura de los registros de este archivo.
247 Esta estructura está compuesta por don enteros (long).
250 EMUFS_REG_ID reg_id indica el
257 EMUFS_BLOCK_ID location número de bloque donde se encuentra el registro.
260 EMUFS_REG_ID y EMUFS_BLOCK_ID son
268 Comportamiento (funciones generales)
272 \begin_inset LatexCommand \label{sec:fsc}
276 Archivo de control de espacio libre
282 La estuctura que define este archivo es la siguiente:
285 EMUFS_FSC que contiene
288 EMUFS_BLOCK_ID indica el número de bloque
291 EMUFS_FREE freespace indica la cantidad de espacio libre que queda en el
296 \begin_inset LatexCommand \label{sec:did}
300 Archivo de índices recuperables
310 \begin_inset LatexCommand \label{cha:tipo1}
314 Archivo con bloques parametrizados y registros de longitud variable
317 Este tipo de archivo tiene varias complicaciones, al tratarse de un punto
319 \begin_inset LatexCommand \ref{cha:tipo2}
324 \begin_inset LatexCommand \ref{cha:tipo3}
328 (cuenta tanto con bloques como con registros variables), hereda los inconvenien
329 tes (y ventajas) de ambos, más los propios.
330 Al implementar este tipo de archivo se puso enfásis en la eficiencia mientras
331 esta no comprometa la mantenibilidad del código, es por esto que en algunas
332 circunstancias no se hace un uso óptimo del espacio.
335 La implementación de este tipo de archivo puede ser encontrada en
339 mientras que su interfaz pública está disponible en
349 El archivo está compuesto por la
354 \begin_inset LatexCommand \pageref{sec:cabecera_gral}
359 El valor que toma en este tipo de archivo es 0 (o el valor simbólico
368 Luego le sigue una cabecera propia del archivo (un EMUFS_BLOCK_SIZE, 4
369 bytes) que almacena el tamaño del bloque que usa el archivo.
370 De esta menera, al abrir un archivo de este tipo no se necesita tener ninguna
371 información sobre él.
372 A esta cabecera le siguen cero o más bloques del tamaño fijo especificado
373 en la cabecera antes mencionada.
379 +-----------+-----------+------------------------//-+
382 | tipo | tam bloque| Cero o más bloques ...
390 +-----------+-----------+------------------------//-+
393 /- 4 bytes -/- 4 bytes -/
396 Organización física de un bloque
399 Cada bloque no guarda información en sí, sólo se comporta como un contenedor
401 Esto no significa que un bloque no tenga utilidad, el bloque es utilizado
402 para proveer un acceso semi-aleatorio a los registros.
403 Para esto se utiliza el archivo de índice (ver página
404 \begin_inset LatexCommand \ref{sec:idx}
408 ), que almacena pares (identificador de registro, número de bloque).
409 Para que sea suficiente este único índice para hallar un registro (siendo
410 que puede haber más de un registro por bloque), es necesario
412 alinear los registros a izquierda
417 bloque N-1 | bloque N | bloque N+1
420 /----------+------------+------------+-------------------+-----------/
425 | registro 1 | registro 2 | espacio libre ...
428 /----------+------------+------------+-------------------+-----------/
431 De forma tal que una vez obtenido el número de bloque se pueda recorrer
432 secuencialmente hasta encontrar el registro deseado.
433 A fin de llevar el conteo de espacio libre se utiliza el archivo de control
434 de espacio libre (ver página
435 \begin_inset LatexCommand \ref{sec:fsc}
439 ), de forma tal que no sea necesario recorrer secuencialmente en busca de
440 espacio libre al hacer una inserción.
443 Puede darse un caso excepcional en el que un registro sea más grande que
444 un bloque, en este caso el registro se almacenará en N bloques consecutivos
445 (siendo N la cantidad de bloques que necesita el registro), ocupando completos
446 los todos los bloques a excepción del último, en el que posteriormente
447 se pueden agregar más registros.
450 Comportamiento (funciones de la interfáz)
453 Detalles de implementación (funciones internas, ver si lo ponemos o no)
457 \begin_inset LatexCommand \label{cha:tipo2}
461 Archivo sin bloques y registros de longitud variable
464 Este tipo de archivo nos traerá a la mesa la particularidad de grabar registros
465 de longitud variable sin realizar su agrupación en bloques, y como veremos
466 en la siguiente sección, tambien permitirá la administración de gaps que
467 queden en el archivo luego de operaciones de baja de registros.
473 Este tipo de archivo realizará el almacenamiento de registros de longitud
474 variable en disco, su borrado y modificación sin la utilización de bloques
476 Su implementación se encuentra en los archivos fuente (
487 Los archivos del tipo 2, presentarán al comienzo del mismo un header compuesto
488 simplemente por un dato del tipo EMUFS_Tipo (int) el cual indicará el tipo
489 de archivo en cuestión.
492 Para poder entender mejor la organización fisica de este tipo de archivo,
493 tomemos el caso hipotético en el que se encuentran grabados
497 (comenzando desde registro 0) de
506 Supongamos también que entre el registro 0 y 1 se encontraba un
523 Si miramos al archivo de datos (.dat) en el disco nos encontraremos con
525 \begin_inset Float figure
532 NOMBRE, ARREGLAME!!!!
536 \begin_inset Graphics
537 filename graphics/Example1.png
548 Como se puede observar, a nivel físico cada registro grabado esta compuesto
549 por un Header cuyo tamaño total es de 8 bytes (
557 ), y posteriormente el registro (bloque de datos) en sí.
558 Luego se encuentra el espacio libre de 18 bytes dejado por el registro
559 de 10 bytes eliminado (10 bytes de datos + header de 8 bytes) y finalmente
560 el segundo registro mencionado.dsds
563 Comportamiento (funciones de la interfaz)
578 se encuentran las cabeceras y la implementación de las funciones principales
579 respectivamente, las cuales dan funcionalidad a esta organización.
583 A continuación se comentará el funcionamiento algunas de las mas importantes.
589 Como se vió al comienzo, los registros en este tipo de archivo no se encuentran
590 agrupados en bloques de ninguna índole y estan dispersos a lo largo del
591 archivo, con la particularidad de que pueden existir gaps o espacio libre,
592 entre dos registros dados.
595 Por ende la lectura de registros en este tipo de organización es muy simple
596 y dada la inexistencia de bloques, el procedimiento será el siguiente:
599 Se determina el offset en bytes, donde comienza el registro deseado, a través
600 de su ID, buscando la misma en el archivo índice (
607 Ya determinada la posición física del registro dentro del archivo de datos
612 ), nos posicionamos en la misma, y leemos el header del registro (
621 Contando así con el tamaño del registro, procedemos a leer el mismo (los
622 datos), dando por finalizada la lectura.
628 En el proceso de alta de registros entrarán en juego dos archivos descriptos
631 sección de archivos auxiliares
633 , siendo estos el archivo índice (
637 ), y el archivo de gaps / espacios libres (
644 Así pues, a la hora de realizar una inserción de un registro en el archivo
645 de datos, el procedimiento será el siguiente:
648 Calculamos el espacio que necesitaremos para el registro: sizeof(
656 ) + sizeof(registro).
659 Determinamos donde debemos insertar el registro, ya sea un gap donde entre,
660 o bien al final del archivo.
663 Insertamos el registro e información de control (
671 ), en la posición indicada en el paso 2.
674 En caso de haber utilizado un GAP, actualizamos el espacio libre restante
675 en el mismo y en caso de que se haya utilizado al totalidad del GAP, se
676 lo elimina del archivo (
683 Actualizamos la entrada correspondiente al registro ingresado (determinada
684 por su RegID), en el archivo índice (
688 ), indicando su offset donde podrá ser accedido luego.
694 En el proceso de baja de registros entrarán en juego los tres archivos descripto
697 sección de archivos auxiliares
699 , siendo estos el archivo índice (
703 ), el archivo de gaps / espacios libres (
707 ) y el archivo de ID's liberados (
714 Dado que en la implementación de este tipo de organización física contamos
715 con los gaps o espacios libres entre registros, no se eliminará fisicamente
716 el registro del archivo de datos (
720 ), pues entonces carecería de sentido el archivo anteriormente mencionado
726 En cambio, se agrega el gap dejado por la eliminación a dicho archivo,
727 y se marca fisicamente en el archivo de datos la eliminación mediante un
728 fill de los bytes correspondientes con un caracter nulo.
729 (hexa 00 y con el propósito de probar fehacientemente que el sistema funciona).
732 El proceso de baja o eliminación de un registro constará luego de los siguientes
736 Se obtiene el offset o posición relativa en donde se encuentra grabado el
737 registro dentro del archivo de datos.
740 Se obtiene el tamaño del registro y se realiza un dummyfill del sector del
741 archivo correspondiente al registro que se está dando de baja.
742 (Se rellena la zona correspondiente a su header+data).
745 Se agrega el GAP generado al archivo de gaps o espacios libres, y en caso
746 de haberse generado un GAP lindante con otro GAP, se realizará un merge
747 de los mismos y se los registrará bajo una única entrada en el archivo
748 de espacios libres (.fsc).
751 Se agrega el ID que fue liberado, al archivo de ID's liberados (
755 ), al final del mismo (
762 Se marca en el archivo índice (
766 ) la eliminación, mediante el valor ¨-1¨ en el registro correspondiente
767 al registro recién eliminado (se le cambia el valor al n-esimo registro,
768 donde N = IDReg del reg eliminado).
771 Modificación de registros
774 Dada la naturaleza del archivo de ID's liberados, y el manejo de espacio
775 libre del que consta esta organización de archivo, el proceso de modificación
776 de un registro se limita a los siguientes pasos:
779 Se realiza la lectura del registro, mediante el respectivo procedimiento
780 ya desarollado anteriormente.
783 Una vez que se cuenta con los nuevos datos modificados, se procede a dar
784 de baja el registro que ha sido modificado, e inmediatamente después se
785 realiza una inserción con los nuevos datos.
794 Como fue indicado, dada la naturaleza de PILA del subsistema de administración
795 de ID liberados, es asegurado que la nueva inserción del registro modificado
796 se realizará con el mismo RegID.
799 Obtención de estadísticas
802 Compactación del archivo de datos
805 Asi como los otros dos tipos de datos, el que nos compete también cuenta
806 con la posibilidad de realizar la compactación de datos cuando el usuario
807 lo desee, justificando todos los registros a izquierda, eliminando así
808 los gaps existentes y decrementando el tamaño del archivo en disco (truncandolo
812 Para poder comprender como hemos implementado el proceso de recompactación
813 en nuestro tipo de archivo 2, nos ayudaremos de esquemas a través de los
814 cuales iremos describiendo el proceso.
815 Notemos antes, que el proceso de compactación esta directamente ligado
816 con el archivo de gaps o espacios libres (
823 Comenzemos con el siguiente cuadro situacional:
824 \begin_inset Float figure
831 NOMBRE, ARREGLAMEE!!!
835 \begin_inset Graphics
836 filename graphics/Compact1.png
848 Partiendo de esta base, el algoritmo de compactación tomará en su inicio
849 al primer gap existente dentro del archivo de datos, en este caso llamado
855 Luego, establecerá que el
859 a partir de donde se quieren mover datos, sera:
862 StartGap0 + SizeGap0 = EndGap0 = Source
865 Lo cual no es nada más y nada menos que lo obvio, la fuente a partir de
866 donde se mueven los datos, sera el fin del primer gap, donde comienzan
872 ) del movimiento, se establece inicialmente, el inicio del gap, o sea
874 StartGap0 = Destination
879 Luego, el algoritmo entrara en un bucle while (mientras haya bucles por
880 levantar), el cual trabajara hasta el final de la compactación de la siguiente
891 Se levanta el proximo gap al levantado en una instancia previa.
892 En este ejemplo, durante el primer loop del while, se levantará
897 Luego, se calcula cuantos bytes hay que mover hacia el Destination de la
921 Lo cual nuevamente es lógico pues querremos mover lo que se encuentra entre
922 el final del primer gap levantado y el inicio del siguiente).
925 Se realiza el movimiento de los datos, utilizando las direcciones
933 , así como la variable
937 que nos indica cuantos bytes transferir.
943 La transferencia se hace de a chunks de 25 bytes + un resto segun el valor
947 Se establece como gap de referencia, al ultimo gap leido (En este caso se
960 ) y termina el código de repetición del bucle, dando lugar a la carga del
961 siguiente gap en el inicio del mismo.
969 Luego del primer bucle, el archivo se vera de la siguiente forma:
970 \begin_inset Float figure
977 NOMBRE, ARREGLAME!!!!
981 \begin_inset Graphics
982 filename graphics/Compact2.png
993 Notemos que al final de la porción de datos de los bytes movidos (donde
998 ), hay basura que será pisada por el próximo movimiento.
1001 En el próximo loop, el bucle levantará un nuevo gap, y utilizando el gap
1002 anterior (En esta caso el Gap anterior será
1006 ) como referencia, realizará los mismos cálculos, desde donde transferir
1007 y cuantos bytes mover.
1008 (El destino es solo establecido inicialmente por código, y para el resto
1009 del algoritmo es el lugar donde quedo el puntero destination luego de la
1013 Una vez que se salga del bucle while, se realizará un último movimiento
1014 preprogramado, donde la fuente (
1018 ) será el final del ultimo gap, y la cantidad de bytes a mover será lo que
1019 se encuentre luego del mismo hasta el fin de archivo.
1022 Source = StartLastGap + SizeLastGap = EndLastGap
1025 Mustmove_bytes = Datsize - Source
1028 Damos por terminada así, la explicación del algoritmo de compresión el cual
1029 para el caso del tipo 2, es realmente bastante sencillo.
1033 \begin_inset LatexCommand \label{cha:tipo3}
1037 Archivo con bloques parametrizados y registros de longitud constante
1040 Las distintas organizaciones de archivos buscan aprovechar al máximo el
1041 espacio del archivo.
1044 En este caso veremos que sucede luego de agregar y borrar una gran cantidad
1045 de registros del archivo, lo que provoca como consecuencia directa la fragmenta
1046 ción del archivo, es decir, quedan huecos entre un registro y otro, lo que
1047 produce un desperdicio de espacio.
1053 Esta organización guarda los registros pertenecientes al archivo en bloques
1054 de tamaño parametrizado, de modo que intentará guardar la mayor cantidad
1055 de registros que quepan en un bloque.
1059 Así como los graba, también tendrá la posibilidad de leer registros y borrarlos
1063 Comportamiento Particular de los Archivos Auxiliares
1064 \layout Subsubsection
1066 Archivo de Bloques y Registros (.idx)
1069 buscar algun caso extraordinario.
1070 \layout Subsubsection
1072 Archivo de Bloques y Espacio Libre (.fsc)
1075 El archivo de de espacios libres permite decidir a la hora de guardar un
1076 registro, donde será guardado.
1080 La estructura de este archivo está formada por un número que indica el bloque
1081 y otro que indica el espacio libre en él.
1084 De esta manera al querer guardar un registro este archivo informará donde
1085 cabe el mismo, previa invocación al la función
1087 EMUFS_BLOCK_ID emufs_fsc_buscar_lugar(EMUFS *, EMUFS_FREE, EMUFS_FREE*)
1089 perteneciente a fsc.h, la cual devuelve el número de bloque donde entra
1090 el registro o -1 si no hay un bloque con lugar suficiente, y toma como
1091 parámetros una estructura
1099 donde el segndo parámetro es el tamaño buscado, y el tercero devuelve el
1103 De la misma manera, al borrar un registro este archivo debe ser actualizado
1104 colocando el nuevo espacio libre en el bloque.
1105 \layout Subsubsection
1107 Archivo de Id`s Borrados (.did)
1110 Este archivo funciona como una pila de id`s borrados, es decir, cuando se
1111 borra un registro el id se almacena en este archivo y será recuperado cuando
1112 se desee grabar un registro nuevo, de esta manera se aprovechan todos los
1113 id`s sin necesidad de crear uno nuevo cada vez que se borra y graba un
1117 Funciones Principales
1131 se encuentran las cabeceras y la implementación de las funciones principales
1132 respectivamente, las cuales dan funcionalidad a esta organización.
1135 A continuación se comentará la descripción de algunas acciones importantes.
1136 \layout Subsubsection
1141 La lectura de un registro se realiza con la ayuda del archivo .
1145 el cual contiene la información de la posición del registro dentro del
1147 Una vez leida esta información, se recupera el bloque (en su totalidad)
1148 del archivo y se busca secuencialmente el registro con el
1157 emufs_tipo3_leer_registro()
1158 \layout Subsubsection
1163 Graba un registro en un bloque donde haya espacio suficiente, y si no crea
1164 un nuevo bloque y lo agrega al final del archivo.
1167 Luego de grabar un registro, actualiza los archivos de índice .idx y .fsc
1168 para mantener la coherencia.
1173 emufs_tipo3_grabar_registro()
1174 \layout Subsubsection
1179 Borra un registro del archivo de datos, para esto levanta el bloque al que
1180 pertenece el archivo y ajusta los demás registros justificandolos hacia
1184 Cabe destacar que para dar de baja un registro no hace falta borrarlo del
1185 archivo de datos, solo es necesario borrar las entradas en los archivos
1187 \layout Subsubsection
1192 Se puede tener acceso a las estadísticas generales del archivo, por ejemplo,
1193 cantidad de bloques, cantidad de registros, espacio libre total, espacio
1194 libre promedio, espacio libre máximo y mínimo, etc.
1197 Esta información es el resultado de ciertos cálculos realizados tanto en
1198 el archivo de datos como en los archivos índice.
1201 Completa una estructura del tipo EMUFS_Estadisticas con las estadísticas
1202 del archivo de datos, espacio libre total, cantidad de registros, cantidad
1203 de bloques, tamaño del archivo en bytes, relaciones entre tamaños y espacios
1209 emufs_tipo3_leer_estadisticas()
1210 \layout Subsubsection
1212 Compactar el Archivo
1215 Esta función intenta reorganizar el archivo de manera que el espacio libre
1216 sea lo menor posible, recordando siempre que un registro no puede ser almacenad
1217 o en mas de un bloque excepto que el tamaño del registro sea mayor que el
1221 Para realizar esto, se aprovecha la funcionalidad de
1223 emufs_tipo3_grabar_registro()
1225 ya que esta tiene la capacidad de determinar una posición mas eficiente
1226 en el archivo para un registro.
1227 Por esto lo que se hace es levantar uno por uno los registros y volverlos
1228 a grabar, de ese modo todos los
1232 que pudieron haberse formado por la eliminación de registros serán cubiertos
1236 Al finalizar este proceso se verifica si existen bloques vacios para truncar
1238 Lo mismo se debe hacer con el archivo de espacios libres .
1242 el cual disminuye su tamaño también.
1247 void emufs_tipo3_compactar()
1250 Consideraciones y Políticas de Diseño
1253 Esto para mi va en organización física.
1256 Se han tomado ciertas consideraciones para algunos casos particulares que
1257 se pueden presentar durante el uso/ejecución de la aplicación.
1260 Cada registro tiene un encabezado que indica el
1267 Si el tamaño del registro es mayor que el tamaño del bloque el registro
1268 se particionará en la cantidad de bloques que sea necesario, pero siempre
1269 se guardará desde el comienzo de un bloque, esto quiere decir que nunca
1270 se podrá encontrar un comienzo de registro en algún lugar de un bloque
1271 que no sea el comienzo del mismo.
1274 Si el registro se divide en mas de un bloque, se le coloca el id como encabezado
1275 igualmente, pero en el archivo .
1279 solo se guarda el primer bloque.
1284 se actualizan todos los bloques con el espacio libre que realmente tienen.
1290 Las comparaciones, pruebas, etc...