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:
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
279 El archivo de de espacios libres permite decidir a la hora de guardar un
280 registro, donde será guardado.
284 La estructura de este archivo está formada por un número que indica el bloque
285 y otro que indica el espacio libre en él.
288 De esta manera al querer guardar un registro este archivo informará donde
289 cabe el mismo, previa invocación al la función
291 EMUFS_BLOCK_ID emufs_fsc_buscar_lugar(EMUFS *, EMUFS_FREE, EMUFS_FREE*)
293 perteneciente a fsc.h, la cual devuelve el número de bloque donde entra
294 el registro o -1 si no hay un bloque con lugar suficiente, y toma como
295 parámetros una estructura
303 donde el segndo parámetro es el tamaño buscado, y el tercero devuelve el
307 De la misma manera, al borrar un registro este archivo debe ser actualizado
308 colocando el nuevo espacio libre en el bloque.
314 La estuctura que define este archivo es la siguiente:
317 EMUFS_FSC que contiene:
320 EMUFS_BLOCK_ID indica el número de bloque
323 EMUFS_FREE freespace indica la cantidad de espacio libre que queda en el
327 EMUFS_FSC y EMUFS_FREE son
336 \begin_inset LatexCommand \label{sec:did}
340 Archivo de índices recuperables
343 Este archivo funciona como una pila de id`s borrados, es decir, cuando se
348 se almacena en este archivo y será recuperado cuando se desee grabar un
349 registro nuevo, de esta manera se aprovechan todos los
353 sin necesidad de crear uno nuevo cada vez que se borra y graba un registro.
359 Este archivo tiene registros de un solo campo, EMUFS_REG_ID el cual simboliza
366 Las declaraciones e implementación se pueden encontrar en
385 al archivo, el cual será el primero recuperado.
388 ver: emufs_did_agregar()
399 que se guardó en el archivo (o se eliminó del archivo de datos), y trunca
403 ver: emufs_did_get_last()
407 \begin_inset LatexCommand \label{cha:tipo1}
411 Archivo con bloques parametrizados y registros de longitud variable
414 Este tipo de archivo tiene varias complicaciones, al tratarse de un punto
416 \begin_inset LatexCommand \ref{cha:tipo2}
421 \begin_inset LatexCommand \ref{cha:tipo3}
425 (cuenta tanto con bloques como con registros variables), hereda los inconvenien
426 tes (y ventajas) de ambos, más los propios.
427 Al implementar este tipo de archivo se puso enfásis en la eficiencia mientras
428 esta no comprometa la mantenibilidad del código, es por esto que en algunas
429 circunstancias no se hace un uso óptimo del espacio.
432 La implementación de este tipo de archivo puede ser encontrada en
436 mientras que su interfaz pública está disponible en
446 El archivo está compuesto por la
451 \begin_inset LatexCommand \pageref{sec:cabecera_gral}
456 El valor que toma en este tipo de archivo es 0 (o el valor simbólico
465 Luego le sigue una cabecera propia del archivo (un EMUFS_BLOCK_SIZE, 4
466 bytes) que almacena el tamaño del bloque que usa el archivo.
467 De esta menera, al abrir un archivo de este tipo no se necesita tener ninguna
468 información sobre él.
469 A esta cabecera le siguen cero o más bloques del tamaño fijo especificado
470 en la cabecera antes mencionada.
476 +-----------+-----------+------------------------//-+
479 | tipo | tam bloque| Cero o más bloques ...
487 +-----------+-----------+------------------------//-+
490 /- 4 bytes -/- 4 bytes -/
493 Organización física de un bloque
496 Cada bloque no guarda información en sí, sólo se comporta como un contenedor
498 Esto no significa que un bloque no tenga utilidad, el bloque es utilizado
499 para proveer un acceso semi-aleatorio a los registros.
500 Para esto se utiliza el archivo de índice (ver página
501 \begin_inset LatexCommand \ref{sec:idx}
505 ), que almacena pares (identificador de registro, número de bloque).
506 Para que sea suficiente este único índice para hallar un registro (siendo
507 que puede haber más de un registro por bloque), es necesario
509 alinear los registros a izquierda
514 bloque N-1 | bloque N | bloque N+1
517 /----------+------------+------------+-------------------+-----------/
522 | registro 1 | registro 2 | espacio libre ...
525 /----------+------------+------------+-------------------+-----------/
528 De forma tal que una vez obtenido el número de bloque se pueda recorrer
529 secuencialmente hasta encontrar el registro deseado.
530 A fin de llevar el conteo de espacio libre se utiliza el archivo de control
531 de espacio libre (ver página
532 \begin_inset LatexCommand \ref{sec:fsc}
536 ), de forma tal que no sea necesario recorrer secuencialmente en busca de
537 espacio libre al hacer una inserción.
540 Puede darse un caso excepcional en el que un registro sea más grande que
541 un bloque, en este caso el registro se almacenará en N bloques consecutivos
542 (siendo N la cantidad de bloques que necesita el registro), ocupando completos
543 los todos los bloques a excepción del último, en el que posteriormente
544 se pueden agregar más registros.
547 Comportamiento (funciones de la interfáz)
550 Detalles de implementación (funciones internas, ver si lo ponemos o no)
554 \begin_inset LatexCommand \label{cha:tipo2}
558 Archivo sin bloques y registros de longitud variable
561 Este tipo de archivo nos traerá a la mesa la particularidad de grabar registros
562 de longitud variable sin realizar su agrupación en bloques, y como veremos
563 en la siguiente sección, tambien permitirá la administración de gaps que
564 queden en el archivo luego de operaciones de baja de registros.
570 Este tipo de archivo realizará el almacenamiento de registros de longitud
571 variable en disco, su borrado y modificación sin la utilización de bloques
573 Su implementación se encuentra en los archivos fuente (
584 Los archivos del tipo 2, presentarán al comienzo del mismo un header compuesto
585 simplemente por un dato del tipo EMUFS_Tipo (int) el cual indicará el tipo
586 de archivo en cuestión.
589 Para poder entender mejor la organización fisica de este tipo de archivo,
590 tomemos el caso hipotético en el que se encuentran grabados
594 (comenzando desde registro 0) de
603 Supongamos también que entre el registro 0 y 1 se encontraba un
620 Si miramos al archivo de datos (.dat) en el disco nos encontraremos con
622 \begin_inset Float figure
629 NOMBRE, ARREGLAME!!!!
633 \begin_inset Graphics
634 filename graphics/Example1.png
645 Como se puede observar, a nivel físico cada registro grabado esta compuesto
646 por un Header cuyo tamaño total es de 8 bytes (
654 ), y posteriormente el registro (bloque de datos) en sí.
655 Luego se encuentra el espacio libre de 18 bytes dejado por el registro
656 de 10 bytes eliminado (10 bytes de datos + header de 8 bytes) y finalmente
657 el segundo registro mencionado.dsds
660 Comportamiento (funciones de la interfaz)
675 se encuentran las cabeceras y la implementación de las funciones principales
676 respectivamente, las cuales dan funcionalidad a esta organización.
680 A continuación se comentará el funcionamiento algunas de las mas importantes.
686 Como se vió al comienzo, los registros en este tipo de archivo no se encuentran
687 agrupados en bloques de ninguna índole y estan dispersos a lo largo del
688 archivo, con la particularidad de que pueden existir gaps o espacio libre,
689 entre dos registros dados.
692 Por ende la lectura de registros en este tipo de organización es muy simple
693 y dada la inexistencia de bloques, el procedimiento será el siguiente:
696 Se determina el offset en bytes, donde comienza el registro deseado, a través
697 de su ID, buscando la misma en el archivo índice (
704 Ya determinada la posición física del registro dentro del archivo de datos
709 ), nos posicionamos en la misma, y leemos el header del registro (
718 Contando así con el tamaño del registro, procedemos a leer el mismo (los
719 datos), dando por finalizada la lectura.
725 En el proceso de alta de registros entrarán en juego dos archivos descriptos
728 sección de archivos auxiliares
730 , siendo estos el archivo índice (
734 ), y el archivo de gaps / espacios libres (
741 Así pues, a la hora de realizar una inserción de un registro en el archivo
742 de datos, el procedimiento será el siguiente:
745 Calculamos el espacio que necesitaremos para el registro: sizeof(
753 ) + sizeof(registro).
756 Determinamos donde debemos insertar el registro, ya sea un gap donde entre,
757 o bien al final del archivo.
760 Insertamos el registro e información de control (
768 ), en la posición indicada en el paso 2.
771 En caso de haber utilizado un GAP, actualizamos el espacio libre restante
772 en el mismo y en caso de que se haya utilizado al totalidad del GAP, se
773 lo elimina del archivo (
780 Actualizamos la entrada correspondiente al registro ingresado (determinada
781 por su RegID), en el archivo índice (
785 ), indicando su offset donde podrá ser accedido luego.
791 En el proceso de baja de registros entrarán en juego los tres archivos descripto
794 sección de archivos auxiliares
796 , siendo estos el archivo índice (
800 ), el archivo de gaps / espacios libres (
804 ) y el archivo de ID's liberados (
811 Dado que en la implementación de este tipo de organización física contamos
812 con los gaps o espacios libres entre registros, no se eliminará fisicamente
813 el registro del archivo de datos (
817 ), pues entonces carecería de sentido el archivo anteriormente mencionado
823 En cambio, se agrega el gap dejado por la eliminación a dicho archivo,
824 y se marca fisicamente en el archivo de datos la eliminación mediante un
825 fill de los bytes correspondientes con un caracter nulo.
826 (hexa 00 y con el propósito de probar fehacientemente que el sistema funciona).
829 El proceso de baja o eliminación de un registro constará luego de los siguientes
833 Se obtiene el offset o posición relativa en donde se encuentra grabado el
834 registro dentro del archivo de datos.
837 Se obtiene el tamaño del registro y se realiza un dummyfill del sector del
838 archivo correspondiente al registro que se está dando de baja.
839 (Se rellena la zona correspondiente a su header+data).
842 Se agrega el GAP generado al archivo de gaps o espacios libres, y en caso
843 de haberse generado un GAP lindante con otro GAP, se realizará un merge
844 de los mismos y se los registrará bajo una única entrada en el archivo
845 de espacios libres (.fsc).
848 Se agrega el ID que fue liberado, al archivo de ID's liberados (
852 ), al final del mismo (
859 Se marca en el archivo índice (
863 ) la eliminación, mediante el valor ¨-1¨ en el registro correspondiente
864 al registro recién eliminado (se le cambia el valor al n-esimo registro,
865 donde N = IDReg del reg eliminado).
868 Modificación de registros
871 Dada la naturaleza del archivo de ID's liberados, y el manejo de espacio
872 libre del que consta esta organización de archivo, el proceso de modificación
873 de un registro se limita a los siguientes pasos:
876 Se realiza la lectura del registro, mediante el respectivo procedimiento
877 ya desarollado anteriormente.
880 Una vez que se cuenta con los nuevos datos modificados, se procede a dar
881 de baja el registro que ha sido modificado, e inmediatamente después se
882 realiza una inserción con los nuevos datos.
891 Como fue indicado, dada la naturaleza de PILA del subsistema de administración
892 de ID liberados, es asegurado que la nueva inserción del registro modificado
893 se realizará con el mismo RegID.
896 Obtención de estadísticas
899 Compactación del archivo de datos
902 Asi como los otros dos tipos de datos, el que nos compete también cuenta
903 con la posibilidad de realizar la compactación de datos cuando el usuario
904 lo desee, justificando todos los registros a izquierda, eliminando así
905 los gaps existentes y decrementando el tamaño del archivo en disco (truncandolo
909 Para poder comprender como hemos implementado el proceso de recompactación
910 en nuestro tipo de archivo 2, nos ayudaremos de esquemas a través de los
911 cuales iremos describiendo el proceso.
912 Notemos antes, que el proceso de compactación esta directamente ligado
913 con el archivo de gaps o espacios libres (
920 Comenzemos con el siguiente cuadro situacional:
921 \begin_inset Float figure
928 NOMBRE, ARREGLAMEE!!!
932 \begin_inset Graphics
933 filename graphics/Compact1.png
945 Partiendo de esta base, el algoritmo de compactación tomará en su inicio
946 al primer gap existente dentro del archivo de datos, en este caso llamado
952 Luego, establecerá que el
956 a partir de donde se quieren mover datos, sera:
959 StartGap0 + SizeGap0 = EndGap0 = Source
962 Lo cual no es nada más y nada menos que lo obvio, la fuente a partir de
963 donde se mueven los datos, sera el fin del primer gap, donde comienzan
969 ) del movimiento, se establece inicialmente, el inicio del gap, o sea
971 StartGap0 = Destination
976 Luego, el algoritmo entrara en un bucle while (mientras haya bucles por
977 levantar), el cual trabajara hasta el final de la compactación de la siguiente
988 Se levanta el proximo gap al levantado en una instancia previa.
989 En este ejemplo, durante el primer loop del while, se levantará
994 Luego, se calcula cuantos bytes hay que mover hacia el Destination de la
1018 Lo cual nuevamente es lógico pues querremos mover lo que se encuentra entre
1019 el final del primer gap levantado y el inicio del siguiente).
1022 Se realiza el movimiento de los datos, utilizando las direcciones
1030 , así como la variable
1034 que nos indica cuantos bytes transferir.
1040 La transferencia se hace de a chunks de 25 bytes + un resto segun el valor
1044 Se establece como gap de referencia, al ultimo gap leido (En este caso se
1057 ) y termina el código de repetición del bucle, dando lugar a la carga del
1058 siguiente gap en el inicio del mismo.
1066 Luego del primer bucle, el archivo se vera de la siguiente forma:
1067 \begin_inset Float figure
1074 NOMBRE, ARREGLAME!!!!
1078 \begin_inset Graphics
1079 filename graphics/Compact2.png
1090 Notemos que al final de la porción de datos de los bytes movidos (donde
1095 ), hay basura que será pisada por el próximo movimiento.
1098 En el próximo loop, el bucle levantará un nuevo gap, y utilizando el gap
1099 anterior (En esta caso el Gap anterior será
1103 ) como referencia, realizará los mismos cálculos, desde donde transferir
1104 y cuantos bytes mover.
1105 (El destino es solo establecido inicialmente por código, y para el resto
1106 del algoritmo es el lugar donde quedo el puntero destination luego de la
1110 Una vez que se salga del bucle while, se realizará un último movimiento
1111 preprogramado, donde la fuente (
1115 ) será el final del ultimo gap, y la cantidad de bytes a mover será lo que
1116 se encuentre luego del mismo hasta el fin de archivo.
1119 Source = StartLastGap + SizeLastGap = EndLastGap
1122 Mustmove_bytes = Datsize - Source
1125 Damos por terminada así, la explicación del algoritmo de compresión el cual
1126 para el caso del tipo 2, es realmente bastante sencillo.
1130 \begin_inset LatexCommand \label{cha:tipo3}
1134 Archivo con bloques parametrizados y registros de longitud constante
1137 Las distintas organizaciones de archivos buscan aprovechar al máximo el
1138 espacio del archivo.
1141 En este caso veremos que sucede luego de agregar y borrar una gran cantidad
1142 de registros del archivo, lo que provoca como consecuencia directa la fragmenta
1143 ción del archivo, es decir, quedan huecos entre un registro y otro, lo que
1144 produce un desperdicio de espacio.
1150 Esta organización guarda los registros pertenecientes al archivo en bloques
1151 de tamaño parametrizado, de modo que intentará guardar la mayor cantidad
1152 de registros que quepan en un bloque.
1156 Así como los graba, también tendrá la posibilidad de leer registros y borrarlos
1160 Comportamiento Particular de los Archivos Auxiliares
1161 \layout Subsubsection
1163 Archivo de Bloques y Registros (.idx)
1166 buscar algun caso extraordinario.
1167 \layout Subsubsection
1169 Archivo de Bloques y Espacio Libre (.fsc)
1170 \layout Subsubsection
1172 Archivo de Id`s Borrados (.did)
1175 El comportamiento de este archivo, es común para todas las organizaciones
1176 y se ha explicado en 3.3.2.
1179 Funciones Principales
1193 se encuentran las cabeceras y la implementación de las funciones principales
1194 respectivamente, las cuales dan funcionalidad a esta organización.
1197 A continuación se comentará la descripción de algunas acciones importantes.
1198 \layout Subsubsection
1203 La lectura de un registro se realiza con la ayuda del archivo .
1207 el cual contiene la información de la posición del registro dentro del
1209 Una vez leida esta información, se recupera el bloque (en su totalidad)
1210 del archivo y se busca secuencialmente el registro con el
1219 emufs_tipo3_leer_registro()
1220 \layout Subsubsection
1225 Graba un registro en un bloque donde haya espacio suficiente, y si no crea
1226 un nuevo bloque y lo agrega al final del archivo.
1229 Luego de grabar un registro, actualiza los archivos de índice .idx y .fsc
1230 para mantener la coherencia.
1235 emufs_tipo3_grabar_registro()
1236 \layout Subsubsection
1241 Borra un registro del archivo de datos, para esto levanta el bloque al que
1242 pertenece el archivo y ajusta los demás registros justificandolos hacia
1246 Cabe destacar que para dar de baja un registro no hace falta borrarlo del
1247 archivo de datos, solo es necesario borrar las entradas en los archivos
1248 de índice, pero cuando se realiza el ajuste el algoritmo toma porciones
1249 del bloque del tamaño de un registro mas su encabezado - comenzando desde
1250 el siguiente al que fue borrado - y copia (sobreescribe) sobre el anterior.
1251 De esta manera, la información correspondiente al registro borrado no estará
1252 presente en el archivo de datos.
1253 Esto es una consecuencia del ajuste al borrar un registro, pudiendo no
1254 ser así, si no se realizara el mismo.
1255 \layout Subsubsection
1260 Se puede tener acceso a las estadísticas generales del archivo, por ejemplo,
1261 cantidad de bloques, cantidad de registros, espacio libre total, espacio
1262 libre promedio, espacio libre máximo y mínimo, etc.
1265 Esta información es el resultado de ciertos cálculos realizados tanto en
1266 el archivo de datos como en los archivos índice.
1269 Completa una estructura del tipo EMUFS_Estadisticas con las estadísticas
1270 del archivo de datos, espacio libre total, cantidad de registros, cantidad
1271 de bloques, tamaño del archivo en bytes, relaciones entre tamaños y espacios
1277 emufs_tipo3_leer_estadisticas()
1278 \layout Subsubsection
1280 Compactar el Archivo
1283 Esta función intenta reorganizar el archivo de manera que el espacio libre
1284 sea lo menor posible, recordando siempre que un registro no puede ser almacenad
1285 o en mas de un bloque excepto que el tamaño del registro sea mayor que el
1289 Para realizar esto, se aprovecha la funcionalidad de
1291 emufs_tipo3_grabar_registro()
1293 ya que esta tiene la capacidad de determinar una posición mas eficiente
1294 en el archivo para un registro.
1295 Por esto lo que se hace es levantar uno por uno los registros y volverlos
1296 a grabar, de ese modo todos los
1300 que pudieron haberse formado por la eliminación de registros serán cubiertos
1304 Al finalizar este proceso se verifica si existen bloques vacios para truncar
1306 Lo mismo se debe hacer con el archivo de espacios libres .
1310 el cual disminuye su tamaño también.
1315 void emufs_tipo3_compactar()
1318 Consideraciones y Políticas de Diseño
1321 Esto para mi va en organización física.
1324 Se han tomado ciertas consideraciones para algunos casos particulares que
1325 se pueden presentar durante el uso/ejecución de la aplicación.
1328 Cada registro tiene un encabezado que indica el
1335 Si el tamaño del registro es mayor que el tamaño del bloque el registro
1336 se particionará en la cantidad de bloques que sea necesario, pero siempre
1337 se guardará desde el comienzo de un bloque, esto quiere decir que nunca
1338 se podrá encontrar un comienzo de registro en algún lugar de un bloque
1339 que no sea el comienzo del mismo.
1342 Si el registro se divide en mas de un bloque, se le coloca el id como encabezado
1343 igualmente, pero en el archivo .
1347 solo se guarda el primer bloque.
1352 se actualizan todos los bloques con el espacio libre que realmente tienen.
1358 Las comparaciones, pruebas, etc...