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$
54 Se detallan a continuación los tipos de datos definidos y utilizados en
55 las distintas implementaciones que conforman nuestro sistema, siendo el
56 más importante de ellos, la estructura
60 que actúa como interfaz común para el manejo de cualquier tipo de archivo
61 (no importa que tipo de organización física posea un archivo, esta estructura
62 prooverá una interfaz (funciones) para su manejo).
75 es la estuctura principal que encapsula todas las funciones para el manejo
76 de un archivo de datos.
77 Posee punteros a funciones que dependiendo de la organización fisica por
78 la cual se opte dentro del sistema, serán asignados de acorde.
82 Su declaración puede ser observada en el archivo
86 y la misma cuenta con los siguiente campos:
93 que es un tipo enumerado que indica cual es la organización.
100 indica el tamaño del bloque para los tipos 1 y 3.
107 indica el tamaño del registro, para el tipo 3 que posee tamaño constante.
114 puntero a la función para leer un bloque.
119 void *leer_bloque_raw()
121 puntero a la función para leer un bloque, el anterior y el siguiente.
126 void **leer_registro()
128 puntero a la función para leer un registro.
133 void **leer_registro_raw()
135 puntero a la función para leer un registro con su encabezado.
140 EMUFS_REG_ID *grabar_registro()
142 puntero a la función para grabar un registro.
147 EMUFS_REG_ID *modificar_registro()
149 puntero a la función para modificar un registro.
154 int *borrar_registro()
156 puntero a la función para borrar un registro.
161 EMUFS_Estadisticas *leer_estadisticas()
163 puntero a la función para cargar una estructura con las estadísticas.
170 puntero a la función para compactar un archivo.
177 almacena el nombre del archivo sin extensión.
180 Esta estructura define los valores de sus punteros según el tipo de organización
181 que se desee manejar y esto se realiza a través del API emufs, implementado
186 , que se describirá posteriormente.
189 Por ejemplo si se desea crear un archivo de nombre
190 \begin_inset Quotes eld
194 \begin_inset Quotes erd
197 organizado de la forma 3, se invoca a la función:
202 emufs_crear(filename,tipo,tam_bloque,tam_reg),
208 es el nombre que tendrán los archivos de datos e índice,
212 es el tipo de organización - bloques parametrizados y registros constantes
217 es el tamaño del bloque, y
221 es el tamaño del registro.
224 Para las diferentes organizaciones puede ser que alguno de estos 2 últimos
225 valores no tengan sentido almacenarlas y tomaran un valor por defecto igual
229 Según el tipo de organización, se inicializan los punteros a las funciones.
236 emufs_tipo3_leer_bloque()
238 , y lo mismo sucede con los demás.
248 es un tipo de dato enum, el cual será utilizado en la cabecera de todo
253 ), para indicar los distintos tipos de organización física.
254 Su declaración puede verse en el archivo
259 A saberse los valores y significado correspondiente que puede tomar este
267 : Archivos con registros de longitud variable y bloques parametrizables.
274 : Archivos con registros de longitud variable sin bloques.
281 : Archivos con registros de longitud fija y bloques parametrizables.
291 es una estructura que almacenará los datos pertinentes a las estadísticas
292 de un archivo dado, y será utilizada para visualizar dichas observaciones
296 Su declaración puede ser observada en el archivo
300 y la misma cuenta con los siguiente campos:
307 tam_archivo: indica el tamaño del archivo de datos (.dat) en bytes.
314 tam_archivos_aux: indica el tamaño de los archivos auxiliares sumados en
322 tam_info_control_dat: indica la cantidad de bytes en información de control
323 utilizados para el archivo.
330 media_fs: promedio de espacio libre en el archivo de datos (por bloque
331 o gap promedio segun la org)
338 total_fs: total de espacio libre en el archivo de datos.
345 max_fs: máximo espacio libre en el archivo de datos (en un bloque o máximo
353 min_fs: idem pero mínimo.
360 cant_bloques: cantidad de bloques en el archivo de datos (.
371 cant_registros: cantidad de registros en el archivo de datos (
378 En base a la estructura descripta anteriormente y mediante la utilización
379 de la función de lectura de estadísticas l
381 emufs_leer_estadisticas()
383 disponible en la estructura común
387 handler de cualquier tipo de archivo, podremos obtener una serie de estadística
388 s que pasamos a detallar (más alla de los datos básicos como cant registros,
389 cant bloques, tam archivo, etc):
392 Relación entre espacio libre y el tamaño del archivo de datos (
399 Relación entre el espacio ocupado por información de control y el tamaño
400 del archivo de datos (
407 Cantidad promedio de espacio libre (en bloque o gap promedio)
410 Desviaciones extremas de espacio libre (máximo/mínimo espacio libre en bloque
417 En la implementación de cada tipo de organización física, así como tambien
418 en las API de los archivos auxiliares comunes a ellas, se da la utilización
419 de tipo definidos para una clara interfaz entre las mismas, los cuales
420 son brevemente descriptos a continuación y pueden ser hallados en el archivo
432 : usado para representar un
443 : usado para representar el tamaño en bytes de un registro.
450 : usado para representar un número de bloque.
457 : usado para representar el tamaño en bytes de un bloque.
464 : usado para representar espacio libre en bytes.
471 : usado para representar un offset.
482 \begin_inset LatexCommand \label{sec:cabecera_gral}
486 Organización física general de un archivo E
487 \begin_inset Formula $\mu$
494 \begin_inset Formula $\mu$
497 FS está compuesto por 4 archivos a nivel de sistema operativo: archivo de
498 datos (con 3 formatos posibles, ver páginas
499 \begin_inset LatexCommand \pageref{cha:tipo1}
504 \begin_inset LatexCommand \pageref{cha:tipo2}
509 \begin_inset LatexCommand \pageref{cha:tipo3}
513 ), archivo de índice (ver página
514 \begin_inset LatexCommand \pageref{sec:idx}
518 ), archivo de control de espacio libre (ver página
519 \begin_inset LatexCommand \pageref{sec:fsc}
523 ) y archivo de índices recuperables (ver página
524 \begin_inset LatexCommand \pageref{sec:did}
531 El archivo de datos está compuesto por:
542 (4 bytes en plataformas Linux de 32 bits) que representa el tipo de archivo.
545 Datos dependientes del tipo de archivo.
552 es utilizada para poder detectar el formato de un archivo al abrirlo.
553 Los datos dependientes del tipo de archivo serán explicados en sus secciones
560 +-----------+--------------------------------------------//-+
563 | tipo | Datos dependientes del tipo de archivo ...
571 +-----------+--------------------------------------------//-+
577 Uso de la estructura EMUFS
580 Como fue mencionado anteriormente en la descripción de la estructura EMUFS,
581 la misma proporciona al usuario una interfaz a través de la cual puede
582 realizar el manejo de archivos en forma genérica, abstrayéndose del tipo
583 de organización física en particular que dicho archivo posea.
588 y las funciones que inicializan la estructura se encuentran en
593 Es decir que a traves de esta estructura, podemos manejar cualquier tipo
594 de archivo, mediante una misma interfaz en común.
599 posee además de ciertos datos que describen la organización física de un
600 archivo dado como por ejemplo
618 , una serie de punteros a funciones para el manejo del archivo del cual
622 Entre dichos funciones se encuentran:
628 leer_bloque(), borrar_registro()
636 modificar_registro, leer_estadisticas()
643 Para entender mejor el uso de esta estructura para el manejo de los archivos,
644 mostraremos un ejemplo concreto.
645 Supongamos que tenemos el siguiente código:
648 EMUFS *efs = emufs_crear(¨articulos.dat¨,T3,200,50);
651 Esto hará que se cree el archivo de datos
655 , con la organización física tipo 3 con registros de longitud fija de 50
656 bytes y bloques de 200 bytes.
657 Al mismo tiempo, los se asginarán valores a los punteros a funciones que
658 posee dicha estructura, la cual de ahora en más estará en condiciones de
659 manejar un archivo del tipo 3.
660 Gráficamente lo que sucede es:
664 \begin_inset Float figure
671 Inicialización de estructura EMUFS para un caso Archivo Tipo 3
675 \begin_inset Graphics
676 filename graphics/Emufsinit.png
687 Así pues, cuando se utilize la estructura para por ejemplo leer un registro,
688 sucedera lo siguiente:
691 efs->leer_registro(params) -- calls --> emufs_tipo3_leer_registro(params)
694 Como se puede observar, la estructura
698 permitirá el manejo de cualquier tipo de archivo, a través del mismo código,
699 dandole gran flexibilidad a nuestro sistema, que podrá expandirse a más
700 tipos de archivos de ser necesario.
706 Acompañando al archivo de datos (
710 ) el cual es responsable de la contención de los registros, tendremos tres
711 archivos auxiliares (
723 ) cuya funcionalidad y propósito pasamos a describir a continuación, sin
724 antes remarcar que los tres archivos poseen una sola implementación para
725 las distintas formas de organización física que hemos implementado (tres
726 para ser mas exactos).
729 Entre las ventajas de poseer la misma implementación se encuentra el tener
730 un API común entre los tres tipos para el manejo de la localización de
731 sus registros, administración de espacio libre e Id's liberados, sin necesidad
732 de realizar n-implementaciones para un mismo objetivo final.
735 Además, la obtención de ciertos datos estadísticos como espacio libre, o
736 cantidad de registros, se realiza a través de la misma interfaz, y también
737 se ha facilitado en cierto grado la re-organización física de un archivo
738 (pasar de un tipo a otro), dado el uso de estos tres archivos auxiliares
739 en común para funciones tan predominantes como índexación, administración
740 de espacio libre y recuperación de Id's.
744 \begin_inset LatexCommand \label{sec:idx}
751 El archivo índice (.idx), permite la localización de los registros en el
752 .DAT de forma directa, mediante la obtención de su offset respecto del inicio
753 del .dat, o nro bloque (segun el tipo de organización física) en donde se
754 encuentra un registro dado, indicado por su
759 Los registros de este archivo se encuentran representados una estructura
760 que indica un número de registro y el bloque u offset en donde se encuentra
764 Es necesario que este archivo esté ordenado por
768 , ya que esto permitirá el acceso directo al mismo, para la rápida obtención
769 del nro de bloque u offset y posterior búsqueda de un registro en el archivo
776 Los registros de este archivo se encuentran representados a nivel codigo
777 por el siguiente tipo de dato interno (
784 typedef unsigned long EMUFS_REG_ID;
787 typedef unsigned long EMUFS_OFFSET;
790 typedef struct emufs_idx_t {
796 EMUFS_OFFSET location;
803 \begin_inset Float table
810 Ejemplo de registro en archivo índice (.idx), para un archivo de organizacion
816 <lyxtabular version="3" rows="2" columns="3">
818 <column alignment="center" valignment="top" leftline="true" width="0">
819 <column alignment="center" valignment="top" leftline="true" width="0">
820 <column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
821 <row topline="true" bottomline="true">
822 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
830 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
838 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
846 <row topline="true" bottomline="true">
847 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
855 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
863 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
868 Indica que el registro de id_reg = 5, se encuentra en el bloque 54
880 \begin_inset Float table
887 Ejemplo de registro en archivo índice (.idx), para un archivo de organizacion
893 <lyxtabular version="3" rows="2" columns="3">
895 <column alignment="center" valignment="top" leftline="true" width="0">
896 <column alignment="center" valignment="top" leftline="true" width="0">
897 <column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
898 <row topline="true" bottomline="true">
899 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
907 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
915 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
923 <row topline="true" bottomline="true">
924 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
932 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
940 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
945 Indica que el registro de id_reg = 5, se encuentra en el bloque 54
965 Como se puede observar, para distintas organizaciones el significado de
966 los registros en este archivo es diferente y se utilizará de distinta manera
973 Las declaraciones e implementación se pueden encontrar en
987 \labelwidthstring 00.00.0000
995 Los registros del archivo indice (
999 ), poseen una correspondencia 1 a 1, con los Id's de los registros en el
1005 Con esto, queremos decir que el N-ésimo registro del archivo índice, será
1006 aquél que posea la información para localizar al registro cuyo
1010 es N, dentro del archivo de datos (
1020 Cabe aclarar que por si bien el indice se encuentra ordenado por
1024 , los registros en el archivo de datos, por lo general no lo estarán.
1030 emufs_idx_buscar_registro()
1032 \labelwidthstring 00.00.0000
1038 Ante la alta de un registro en el archivo de datos, se insetará un nuevo
1039 registro en el archivo índice, con el id_reg del registro en cuestion,
1040 y el offset u bloque donde se lo haya grabado en disco.
1046 \labelwidthstring 00.00.0000
1052 Ante el borrado de un registro del archivo de datos, se accederá el registro
1053 correspondiente en el índice, y se actualizara su LOCATION, estableciendolo
1054 en el valor -1 UL, el cual indica que ese registro ha sido eliminado y
1055 por ende no se lo podrá localizar en el futuro.
1056 Como se verá mas adelante, según el tipo de organización física, el registro
1057 puede ser borrado concretamente del .
1068 \labelwidthstring 00.00.0000
1074 Ante la modificación en la posición física de un registro dentro del archivo
1075 de datos (por ejemplo luego del proceso de recompactación, se realizará
1076 la modificación respectiva del campo
1084 emufs_idx_actualizar()
1088 \begin_inset LatexCommand \label{sec:fsc}
1092 Archivo de control de espacio libre
1095 El archivo de espacio libre (
1099 ) (espacio por bloque o gaps en archivo, según el tipo de organización física),
1100 tiene como función la administración del espacio libre, generado por previas
1101 eliminaciones de registros en el archivo de datos.
1102 El mismo, nos indicará donde hay lugar para insertar un nuevo registro.
1105 Para el caso de una organización por bloque, nos dirá en que bloque o si
1106 se debe generar un nuevo bloque.
1107 En el caso de la organización sin bloques, nos indicará en que gap o si
1108 al final del archivo.
1111 Los registros de este archivo se encuentran representados una estructura
1112 que indica un número de bloque u offset y el espacio libre disponible en
1113 el mismo (o apartir del mismo en el caso del offset).
1120 : Por requerimiento del algoritmo de compactación el tipo de organización
1121 física con reg long var, sin bloques, los gaps se graban en forma ordenada
1123 (El orden se corresponde con lo que hay en el .dat).
1129 Los registros de este archivo se encuentran representados a nivel codigo
1130 por el siguiente tipo de dato interno (
1137 typedef struct emufs_fsc_t {
1140 unsigned long int marker;
1143 unsigned long int freespace;
1153 \begin_inset Float table
1160 Ejemplo de registro en archivo de control de espacio libre para un archivo
1165 \begin_inset Tabular
1166 <lyxtabular version="3" rows="2" columns="3">
1168 <column alignment="center" valignment="top" leftline="true" width="0">
1169 <column alignment="center" valignment="top" leftline="true" width="0">
1170 <column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
1171 <row topline="true" bottomline="true">
1172 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
1180 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
1188 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
1196 <row topline="true" bottomline="true">
1197 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
1205 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
1213 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
1218 Indica que en el bloque 12, hay 120 bytes libres al final del mismo.
1230 \begin_inset Float table
1237 Ejemplo de registro en archivo de
1241 para un archivo sin bloques
1245 \begin_inset Tabular
1246 <lyxtabular version="3" rows="2" columns="3">
1248 <column alignment="center" valignment="top" leftline="true" width="0">
1249 <column alignment="center" valignment="top" leftline="true" width="0">
1250 <column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
1251 <row topline="true" bottomline="true">
1252 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
1260 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
1268 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
1276 <row topline="true" bottomline="true">
1277 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
1285 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
1293 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
1298 Indica que a partir del byte 12 del archivo de datos, hay 120 bytes libres.
1318 Como se puede observar, para distintas organizaciones el significado de
1319 los registros en este archivo es diferente y se utilizará de distinta manera
1323 Funciones principales
1326 Las declaraciones e implementación se pueden encontrar en
1340 \labelwidthstring 00.00.0000
1346 Ante la operación de alta de un registro en el archivo de datos, se realizará
1347 la búsqueda de espacio libre donde este podrá ser insertado.
1348 En el caso de organizaciones con bloques, se buscará en que
1352 se posee espacio suficiente para albergar el nuevo registro.
1353 En el caso de organizacion sin bloque, se buscará un gap o espacio libre
1354 en el archivo, obteniéndose en consecuencia, el
1362 emufs_fsc_buscar_lugar()
1364 \labelwidthstring 00.00.0000
1370 Luego de una operación de baja o alta de un registro en el archivo de datos
1375 ), incrementará o decrementará respectivamente el espacio libre en el archivo
1376 de datos, y esto deberá ser registrado, agregando un nuevo registro en
1377 el archivo de espacios libres (
1381 ) o bien modificandoló.
1385 En el caso de organizaciónes con bloques, se actualizará el valor del espacio
1390 en el bloque (ya sea incrementandoló o decrementandoló) o bien se insertará
1391 un nuevo registro en caso de que se esté creando un nuevo bloque en el
1392 archivo de datos (en este caso no será debido a un alta o baja de registro
1393 como se mencionó al principio).
1397 Para el caso de organización sin bloques, en el caso de baja de un registro
1402 ) se insertará un nuevo registro en el
1406 dando cuenta de la aparición de un nuevo gap en el archivo de datos (
1410 ), y en caso de estar este lindante con otro gap, se realizará el merge
1412 (esto esta explicado más en profundidad en los casos particulares de organizaci
1413 ón fisica, registros variables sin bloques).
1414 Para el caso de una alta en el archivo de datos (
1418 ), el valor del gap donde se haya insertado se actualizará.
1423 emufs_fsc_agregar(), emufs_fsc_agregar_gap(), emufs_fsc_actualizar(), emufs_fsc_
1426 \labelwidthstring 00.00.0000
1432 : Unicamente para el caso de una organización que presente gaps en el archivo,
1433 se podrá dar a lugar la eliminación de un registro del archivo de espacios
1439 Esta situación tendrá efecto cuando se inserte un registro que entre perfecto
1440 en un gap disponible, y por ende el gap desaparecerá.
1444 emufs_fsc_borrar_gap()
1448 \begin_inset LatexCommand \label{sec:did}
1452 Archivo de id's recuperables
1455 El archivo de Id's liberado (
1459 ) llevará cuenta de aquellos Id's de registros (
1463 ) que ya no se encuentran siendo utilizados y fueron liberados por registros
1464 eliminados previamente.
1465 A través del mismo, se podrá realizar la reutilización de Id's ante la
1466 alta de nuevos registros.
1469 A nivel físico, este archivo poseerá una secuencia de datos del tipo EMUFS_REG_I
1470 D, y el comportamiento del sistema de recuperación de Id's será el de una
1472 Es decir, ante el requerimiento de un
1476 libre por una función del sistema como por ejemplo la alta de un nuevo
1477 registro, el API del archivo (
1481 ), obtendrá el último dato del mismo (el
1485 que fue liberado mas recientemente), y truncará el archivo eliminando el
1490 recuperado de la tabla.
1491 (LIFO, Last in First Out).
1497 Este archivo tiene registros de un solo campo,
1501 el cual simboliza al id que fue liberado en un proceso de baja de registros.
1504 Funciones principales
1507 Las declaraciones e implementación se pueden encontrar en
1521 \labelwidthstring 00.00.0000
1527 Ante la eliminación de un registro del archivo de datos (
1531 ) se procederá al agregado del correspondiente
1535 que fue liberado por dicha operación, al archivo
1549 \labelwidthstring 00.00.0000
1555 Cuando el sistema desee grabar un nuevo registro en el archivo de datos,
1560 disponible para el mismo.
1561 El sistema de administración de Id's libres, obtendrá el último
1565 que se guardó en el archivo (o se eliminó del archivo de datos), y truncará
1566 el archivo eliminandolo.
1574 emufs_did_get_last()
1578 \begin_inset LatexCommand \label{cha:tipo1}
1582 Archivo con bloques parametrizados y registros de longitud variable
1585 Este tipo de archivo tiene varias complicaciones, al tratarse de un punto
1587 \begin_inset LatexCommand \ref{cha:tipo2}
1592 \begin_inset LatexCommand \ref{cha:tipo3}
1596 (cuenta tanto con bloques como con registros variables), hereda los inconvenien
1597 tes (y ventajas) de ambos, más los propios.
1598 Al implementar este tipo de archivo se puso enfásis en la eficiencia mientras
1599 esta no comprometa la mantenibilidad del código, es por esto que en algunas
1600 circunstancias no se hace un uso óptimo del espacio.
1603 La implementación de este tipo de archivo puede ser encontrada en
1607 mientras que su interfaz pública está disponible en
1617 El archivo está compuesto por la
1622 \begin_inset LatexCommand \pageref{sec:cabecera_gral}
1627 El valor que toma en este tipo de archivo es 0 (o el valor simbólico
1636 Luego le sigue una cabecera propia del archivo (un
1640 , 4 bytes) que almacena el tamaño del bloque que usa el archivo.
1641 De esta menera, al abrir un archivo de este tipo no se necesita tener ninguna
1642 información sobre él.
1643 A esta cabecera le siguen cero o más bloques del tamaño fijo especificado
1644 en la cabecera antes mencionada.
1650 +-----------+-----------+------------------------//-+
1653 | tipo | tam bloque| Cero o más bloques ...
1661 +-----------+-----------+------------------------//-+
1664 /- 4 bytes -/- 4 bytes -/
1667 Organización física de un bloque
1670 Cada bloque no guarda información en sí, sólo se comporta como un contenedor
1672 Esto no significa que un bloque no tenga utilidad, el bloque es utilizado
1673 para proveer un acceso semi-aleatorio a los registros.
1674 Para esto se utiliza el archivo de índice (ver página
1675 \begin_inset LatexCommand \ref{sec:idx}
1679 ), que almacena pares [identificador de registro, número de bloque].
1680 Para que sea suficiente este único índice para hallar un registro (siendo
1681 que puede haber más de un registro por bloque), es necesario
1683 alinear los registros a izquierda
1686 Esto significa que hay que asegurar que siempre los registros en un bloque
1687 se presenten de forma consecutiva, jamás permitiendo que haya un espacio
1688 libre entre registros (en un mismo bloque).
1691 Podemos ver un ejemplo de esto en forma gráfica:
1694 bloque N-1 | bloque N | bloque N+1
1697 /----------+------------+------------+---------------+-----------/
1702 | registro 1 | registro 2 | espacio libre |
1707 /----------+------------+------------+---------------+-----------/
1710 /------------- tamaño del bloque ---------/
1713 De esta forma, una vez obtenido el número de bloque, se pueda recorrer secuencia
1714 lmente hasta encontrar el registro deseado.
1715 A fin de llevar el conteo de espacio libre se utiliza el archivo de control
1716 de espacio libre (ver página
1717 \begin_inset LatexCommand \ref{sec:fsc}
1721 ), de forma tal que no sea necesario recorrer secuencialmente en busca de
1722 espacio libre al hacer una inserción.
1725 Puede darse un caso excepcional en el que un registro sea más grande que
1726 un bloque, en este caso el registro se almacenará en N bloques consecutivos
1727 (siendo N la cantidad de bloques que necesita el registro), ocupando completos
1728 los todos los bloques a excepción del último, en el que posteriormente
1729 se pueden agregar más registros.
1730 \layout Subsubsection
1733 \begin_inset LatexCommand \label{sub:tipo1_reg}
1737 Organización física de un registro.
1740 El registro es el que representa al dato realmente que se quiere almacenar.
1741 Para representar ese dato se necesita una determinada información de control,
1742 tanto para poder identificar el registro en un bloque (en búsquedas secuenciale
1743 s dentro del bloque) como para saber su longitud (dado que este tipo de
1744 archivo utiliza registros de tamaño variable).
1747 Siguiendo la metodología general de E
1748 \begin_inset Formula $\mu$
1751 FS, se optó por incluir esta información de control como una cabecera al
1752 comienzo del registro, siguiendo a esta los datos en sí.
1753 La cabecera está compuesta por un identificador (
1757 ) de registro (EMUFS_REG_ID, 4 bytes) seguido por el tamaño (
1761 ) del registros (EMUFS_REG_SIZE, 4 bytes).
1762 Podemos ver gráficamente como se se compone un registro:
1768 +-----------+-----------+------------------+
1771 | id | tamaño | datos ...
1775 +-----------+-----------+------------------+
1778 /- 4 bytes -/- 4 bytes -/- [tamaño] bytes -/
1779 \layout Subsubsection
1782 \begin_inset LatexCommand \label{sub:tipo1_reg_multi}
1786 Organización física de un registro más grande que un bloque (registro
1793 Puede darse el caso excepcional en que un registro sea de mayor longitud
1795 Al ser una situación excepcional, no siempre se resuelve de la forma más
1796 eficiente ni se mínimiza el espacio ocupado por datos de control (como
1797 se dijo anteriormente, se prefirió conservar la simpleza del código, adoptando
1798 algoritmos generales aunque no sea de la forma más eficiente o maximizando
1799 el uso del espacio para no perjudicar la mantenibilidad).
1802 Para menejar un registro
1806 se optó por limitarlo a la siguiente estructura (suponiendo que el registro
1807 ocupa N bloques, con N > 1 y que un
1811 es una porción del registro que entra en un bloque):
1818 se almacenan en bloques completos consecutivos.
1821 El último fragmento se almacena al comienzo del bloque inmediatamente posterior
1825 Cada framento posee las cabeceras mencionadas en la sección
1826 \begin_inset LatexCommand \ref{sub:tipo1_reg}
1830 , cuyo contenido es el siguiente:
1838 se almacena el identificador único obtenido al hacer el alta.
1845 se almacena el tamaño del
1849 actual más los tamaños de los
1853 posteriores, quedando en el primer
1857 el tamaño completo del registro y en el último sólo el tamaño del
1865 Como puede observarse, la información de control en los
1869 intermedios puede ser redundante, pero se conserva para poder realizar
1870 algoritmos genéricos (que se basan en que al principio de un bloque, si
1871 no está vacío, hay una cabecera de un registro) y para facilitar chequeos
1872 de integridad del archivo.
1875 A continuación se presenta un ejemplo gráfico de un registro multibloque
1876 de 10 bytes (de contenido
1877 \begin_inset Quotes eld
1881 \begin_inset Quotes erd
1884 ) almacenado en un archivo con bloques de 4 bytes:
1887 | bloque 0 | bloque 1 | bloque 2
1890 +-------------------+-------------------+-------------------+-//-+
1893 | registro 0 - 1/3 | registro 0 - 2/3 | registro 0 - 3/3..|
1900 |+----+-----+------+|+----+-----+------+|+----+-----+----+..| // |
1903 || id | tam | datos||| id | tam | datos||| id | tam |dato|..|
1910 ||----+-----+------+||----+-----+------+||----+-----+----+..| // |
1913 || 0 | 10 | 1234 ||| 0 | 6 | 5678 ||| 0 | 2 | 90 |..|
1920 |+----+-----+------+|+----+-----+------+|+----+-----+----+..| // |
1923 +-------------------+-------------------+-------------------+-
1930 Funciones principales
1933 Las funciones principales son las necesarias para completar la estructura
1935 \begin_inset LatexCommand \pageref{sub:EMUFS}
1942 Lectura de registros
1945 Para leer un registro se hace uso del archivo de índice (ver página
1946 \begin_inset LatexCommand \pageref{sec:idx}
1950 ), obteniéndose el número de bloque en donde está almacenado el registro
1952 Una vez obtenido, se carga en memoria el bloque entero y se busca secuencialmen
1953 te en él (leyendo la cabecera de cada registro y salteando los datos) hasta
1954 encontrar el registro pedido.
1955 Una vez encontrado se lo copia y devuelve.
1958 Si se tratara de un registro
1963 \begin_inset LatexCommand \ref{sub:tipo1_reg_multi}
1967 ), se procede forma similar, sólo que se cargan en memoria uno a uno los
1968 bloques que componen el registro y se van copiando (y uniendo) los
1977 emufs_tipo1_leer_registro()
1983 Para realizar el alta de un registro, lo primero que se obtiene es un identifica
1984 dor, buscando primero en el archivo de identificadores recuperables (pág.
1986 \begin_inset LatexCommand \ref{sec:did}
1990 ) y de no haber ninguno, buscando el mayor identificador presente en el
1991 archivo de índice (pág.
1993 \begin_inset LatexCommand \ref{sec:idx}
1998 El paso siguiente es buscar un bloque con espacio libre suficiente como
1999 para almacenar el registro (y su cabecera) en el archivo de control de
2002 \begin_inset LatexCommand \ref{sec:fsc}
2006 ) y cargarlo completo en memoria.
2007 De no encontrarse, se crea un bloque nuevo al final de archivo.
2008 En el bloque cargado en memoria, se agrega el registro nuevo (con su cabecera)
2009 al comienzo del espacio libre (calculado a partir del tamaño del bloque
2010 y el espacio libre en bloque) y se lo graba en disco.
2011 Finalmente se agrega (o actualiza) el identificador al archivo índice y
2012 el espacio libre en el bloque.
2015 Si el registro ocupara más de un bloque (ver sección
2016 \begin_inset LatexCommand \ref{sub:tipo1_reg_multi}
2020 ), se buscan N bloques consecutivos (todos los que necesite el registro)
2021 absolutamente libres
2027 Incluso el último bloque debe estar absolutamente libre para cumplir con
2028 las condiciones presentadas en la sección
2029 \begin_inset LatexCommand \ref{sub:tipo1_reg_multi}
2036 y graba bloque a bloque cada
2040 del registro (con sus cabeceras intermedias), al último
2044 se lo trata de forma análoga a un registro
2049 Por cada bloque utilizado se actualiza el archivo de control de espacio
2055 emufs_tipo1_agregar_registro()
2061 Al eliminar un registro lo primero que se hace es actualizar los archivos
2062 de índice y de indentificadores recuperables, poniendo como número de bloque
2067 y agregando el identificador del registro a borrar respectivamente.
2068 También se actualiza el archivo de control de espacio libre por cada bloque
2069 (en caso de ser más de uno, en registros
2073 , se actualizan todos los bloques) y se carga el bloque en memoria para
2076 alinear los datos a izquierda
2078 (en caso de ser un registro
2082 , esto se realiza sólo para el último bloque).
2083 Para alinear los datos, se recorre secuencialmente en bloque (leyendo la
2084 cabecera de cada registro y salteando los datos) hasta encontrar el registro
2086 Encontrado el registro, se copian todos los bytes que se encuentran entre
2087 el fin del registro a borrar y el fin del bloque, en el comienzo del bloque
2093 emufs_tipo1_borrar_registro()
2096 Modificación de registros
2099 Se optó por un algoritmo simple y general, que usa las funciones de alto
2100 nivel mencionadas hasta ahora.
2101 Simplemento borra el registro y vuelve a crearlo.
2102 Al recuperar el último identificador de registro borrado, nos aseguramos
2103 de que se mantenga el identificador del registro.
2108 emufs_tipo1_modificar_registro()
2111 Obtención de estadísticas
2114 Es una función bastante simple, con una única complicación que mencionaremos
2118 Para obtener las máximas desviaciones, cantidad total de espacio libre,
2119 cantidad de registros y tamaño de los archivos auxiliares se utilizan las
2120 funciones apropiadas de los archivos auxiliares (ver secciones
2121 \begin_inset LatexCommand \ref{sec:idx}
2126 \begin_inset LatexCommand \ref{sec:fsc}
2131 \begin_inset LatexCommand \ref{sec:did}
2138 Para obtener la cantidad de bloques se hace el siguiente calculo:
2141 cant_bloques = (tamaño_archivo_datos - tamaño_cabecera_archivo_datos)
2147 Hasta aquí no hay mayores inconvenientes.
2148 El problema se presenta para calcular el tamaño de la información de control
2149 utilizada por el archivo de datos; se utiliza el siguiente cálculo:
2152 tam_info_control_datos = tamaño_cabecera_archivo_datos
2155 + cant_registros * tamaño_cabecera_registro;
2158 Aunque a simple vista esto parece acertado, no contempla el caso de los
2164 \begin_inset LatexCommand \pageref{sub:tipo1_reg_multi}
2168 ), estos registros almacenan
2170 tamaño_cabecera_registro * N
2176 es la cantidad de bloques que ocupan.
2177 Salvar este caso sería muy costoso, porque habría que recorrer el archivo
2178 registro a registro,
2186 e ir contando todas las cabeceras de registro que aparecen (similar a lo
2187 que se hace en la compactación, ver sección
2188 \begin_inset LatexCommand \ref{sub:tipo1_compact}
2193 Al tratarse este de un caso excepcional, se optó por mantener la función
2194 simple ya que funciona bien en la mayoría de los casos.
2199 emufs_tipo1_leer_estadisticas()
2203 \begin_inset LatexCommand \label{sub:tipo1_compact}
2207 Compactación del archivo de datos
2210 Esta función es una de las más simples, porque se limita a un algoritmo
2211 muy simple que utiliza las funciones de
2215 antes nombradas para realizar su tarea.
2216 Básicamente recorre el archivo de índices de registros, de comienzo a fin,
2217 leyendo el registro, borrándolo y volviéndolo a insertar.
2218 Si había espacio libre en un bloque anterior al que estaba, será insertado
2219 en él, si no volverá a grabarse en el lugar en que estaba.
2220 De esta forma se aprovechan todos los espacios libres intermedios, concluyendo
2221 con un archivo igual o más pequeño que el original.
2224 Esta implementación no es la más eficiente, pero siendo que esta es una
2225 operación costosa y excepcional por naturaleza, se optó por mantener el
2226 algoritmo simple a costo de un poco de eficiencia.
2231 emufs_tipo1_compactar()
2234 Detalles de implementación (funciones internas, ver si lo ponemos o no)
2238 \begin_inset LatexCommand \label{cha:tipo2}
2242 Archivo sin bloques y registros de longitud variable
2245 Este tipo de archivo nos traerá a la mesa la particularidad de grabar registros
2246 de longitud variable sin realizar su agrupación en bloques, y como veremos
2247 en la siguiente sección, tambien permitirá la administración de gaps que
2248 queden en el archivo luego de operaciones de baja de registros.
2254 Este tipo de archivo realizará el almacenamiento de registros de longitud
2255 variable en disco, su borrado y modificación sin la utilización de bloques
2257 Su implementación se encuentra en los archivos fuente (
2268 Los archivos del tipo 2, presentarán al comienzo del mismo un header compuesto
2269 simplemente por un dato del tipo EMUFS_Tipo (int) el cual indicará el tipo
2270 de archivo en cuestión.
2273 Para poder entender mejor la organización fisica de este tipo de archivo,
2274 tomemos el caso hipotético en el que se encuentran grabados
2278 (comenzando desde registro 0) de
2287 Supongamos también que entre el registro 0 y 1 se encontraba un
2289 registro de 10 bytes
2304 Si miramos al archivo de datos (.dat) en el disco nos encontraremos con
2306 \begin_inset Float figure
2313 Organización física de los registros en disco
2317 \begin_inset Graphics
2318 filename graphics/Example1.png
2329 Como se puede observar, a nivel físico cada registro grabado esta compuesto
2330 por un Header cuyo tamaño total es de 8 bytes (
2338 ), y posteriormente el registro (bloque de datos) en sí.
2339 Luego se encuentra el espacio libre de 18 bytes dejado por el registro
2340 de 10 bytes eliminado (10 bytes de datos + header de 8 bytes) y finalmente
2341 el segundo registro mencionado.dsds
2344 Comportamiento Particular de los Archivos Auxiliares
2347 Como fue explicado al inicio de la documentación, la implementación de cualquier
2348 a de las tres organizaciones físicas de archivos presenta la necesidad de
2349 poseer tres archivos auxiliares que actuarán como índice de direcciones
2354 ), administrador de espacio libre (
2358 ) y administrador de Id's liberados (
2365 No obstante, cada tipo de organización presentara sus particularidades respecto
2366 de estos tres archivos, las cuales describiremos a continuación en caso
2368 \layout Subsubsection
2370 Archivo índice o de posiciones relativas (.idx)
2377 ), permite la localización de los registros en el .DAT de forma directa,
2378 mediante la obtención de su offset o posición relativa respecto del inicio
2383 en donde se encuentra un registro dado, indicado por su ID.
2386 Así pues, si tomamos el ejemplo descripto al inicio de este capítulo, tendremos
2387 las siguientes entradas en el archivo índice
2392 \begin_inset Float table
2399 Organización física del archivo de índice o posiciones relativas.
2403 \begin_inset Tabular
2404 <lyxtabular version="3" rows="3" columns="3">
2406 <column alignment="center" valignment="top" leftline="true" width="0">
2407 <column alignment="center" valignment="top" leftline="true" width="0">
2408 <column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
2409 <row topline="true" bottomline="true">
2410 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2420 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2430 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
2438 <row topline="true">
2439 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2449 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2459 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
2464 El primer registro (reg0) comienza en el byte 4
2468 <row topline="true" bottomline="true">
2469 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2477 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2487 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
2492 El segundo registro (reg1) comienza en el byte 60
2512 LOCATION indica donde comienza el header del registro buscado, y por consiguien
2513 te luego del header tendremos el registro en sí (los datos).
2514 \layout Subsubsection
2516 Achivo de Gaps / Espacios Libres (.fsc)
2519 El archivo de espacios libres o gaps (.fsc), tiene como función la administración
2520 del espacio libre o gaps (agujeros), generados por previas eliminaciones
2521 de registros en el archivo de datos.
2522 El mismo, nos indicará donde hay lugar para insertar un nuevo registro
2523 (se podrán insertar en algún gap acorde, o bien al final del archivo).
2524 Este archivo será utilizado tambien para el proceso de compactación de
2525 un archivo, explicado luego.
2528 Así pues, si tomamos el ejemplo descripto al inicio del documento, tendremos
2529 las siguientes entradas en el archivo índice
2534 \begin_inset Float table
2541 Organización física del archivo de
2545 o control de espacio libre.
2549 \begin_inset Tabular
2550 <lyxtabular version="3" rows="2" columns="3">
2552 <column alignment="center" valignment="top" leftline="true" width="0">
2553 <column alignment="center" valignment="top" leftline="true" width="0">
2554 <column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
2555 <row topline="true" bottomline="true">
2556 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2566 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2576 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
2584 <row topline="true" bottomline="true">
2585 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2595 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2605 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
2610 18 bytes libres a partir del byte 42 del .dat
2630 Por requerimiento del algoritmo de compactación, los gaps se graban en
2631 forma ordenada en el (.fsc).
2632 (El orden se corresponde con lo que hay en el
2637 \layout Subsubsection*
2642 Si bien la utilización concreta de los GAPS será explicada posteriormente
2643 en la ALTA y BAJA de registros, debemos remarcar la funcionalidad de MERGING
2644 que posee nuestro sistema FSC.
2647 Ante la eliminación de un registro del archivo de datos, se generara por
2648 consiguiente un gap o espacio libre en alguna posición del archivo.
2649 Ese gap deberá ser registrado en el archivo de gaps (.fsc).
2650 Ahora bien, nuestro sistema de gaps, contemplará como es debido, la posibilidad
2651 de que se haya eliminado un registro que posee un GAP por delante, un GAP
2652 por detrás, o bien un GAP por delante y por detrás del mismo.
2655 Nuestro sistema actuará en consecuencia, realizando un merge de los espacios
2656 libres, y unificándolos en una UNICA entrada en el archivo .fsc, que contendrá
2657 como dato de freespace, la suma correspondiente de los espacios libres
2659 \layout Subsubsection
2661 Archivo de ID's liberados (.did)
2664 El archivo de ID's liberados no presenta ningún aspecto particular en este
2665 tipo de organización.
2666 Remitirse al capítulo correspondiente a los archivos auxiliares para consultar
2667 su estructura y funcionamiento.
2670 Funciones Principales
2685 se encuentran las cabeceras y la implementación de las funciones principales
2686 respectivamente, las cuales dan funcionalidad a esta organización.
2690 A continuación se comentará el funcionamiento algunas de las mas importantes.
2693 Lectura de registros
2696 Como se vió al comienzo, los registros en este tipo de archivo no se encuentran
2697 agrupados en bloques de ninguna índole y estan dispersos a lo largo del
2698 archivo, con la particularidad de que pueden existir gaps o espacio libre,
2699 entre dos registros dados.
2702 Por ende la lectura de registros en este tipo de organización es muy simple
2703 y dada la inexistencia de bloques, el procedimiento será el siguiente:
2706 Se determina el offset en bytes, donde comienza el registro deseado, a través
2707 de su ID, buscando la misma en el archivo índice (
2714 Ya determinada la posición física del registro dentro del archivo de datos
2719 ), nos posicionamos en la misma, y leemos el header del registro (
2728 Contando así con el tamaño del registro, procedemos a leer el mismo (los
2729 datos), dando por finalizada la lectura.
2734 emufs_tipo2_leer_registro()
2740 En el proceso de alta de registros entrarán en juego dos archivos descriptos
2743 sección de archivos auxiliares
2745 , siendo estos el archivo índice (
2749 ), y el archivo de gaps / espacios libres (
2756 Así pues, a la hora de realizar una inserción de un registro en el archivo
2757 de datos, el procedimiento será el siguiente:
2760 Calculamos el espacio que necesitaremos para el registro: sizeof(
2768 ) + sizeof(registro).
2771 Determinamos donde debemos insertar el registro, ya sea un gap donde entre,
2772 o bien al final del archivo.
2775 Insertamos el registro e información de control (
2783 ), en la posición indicada en el paso 2.
2786 En caso de haber utilizado un GAP, actualizamos el espacio libre restante
2787 en el mismo y en caso de que se haya utilizado al totalidad del GAP, se
2788 lo elimina del archivo (
2795 Actualizamos la entrada correspondiente al registro ingresado (determinada
2796 por su RegID), en el archivo índice (
2800 ), indicando su offset donde podrá ser accedido luego.
2805 emufs_tipo2_agregar_registro()
2811 En el proceso de baja de registros entrarán en juego los tres archivos descripto
2814 sección de archivos auxiliares
2816 , siendo estos el archivo índice (
2820 ), el archivo de gaps / espacios libres (
2824 ) y el archivo de ID's liberados (
2831 Dado que en la implementación de este tipo de organización física contamos
2832 con los gaps o espacios libres entre registros, no se eliminará fisicamente
2833 el registro del archivo de datos (
2837 ), pues entonces carecería de sentido el archivo anteriormente mencionado
2843 En cambio, se agrega el gap dejado por la eliminación a dicho archivo,
2844 y se marca fisicamente en el archivo de datos la eliminación mediante un
2845 fill de los bytes correspondientes con un caracter nulo.
2846 (hexa 00 y con el propósito de probar fehacientemente que el sistema funciona).
2849 El proceso de baja o eliminación de un registro constará luego de los siguientes
2853 Se obtiene el offset o posición relativa en donde se encuentra grabado el
2854 registro dentro del archivo de datos.
2857 Se obtiene el tamaño del registro y se realiza un dummyfill del sector del
2858 archivo correspondiente al registro que se está dando de baja.
2859 (Se rellena la zona correspondiente a su header+data).
2862 Se agrega el GAP generado al archivo de gaps o espacios libres, y en caso
2863 de haberse generado un GAP lindante con otro GAP, se realizará un merge
2864 de los mismos y se los registrará bajo una única entrada en el archivo
2865 de espacios libres (.fsc).
2868 Se agrega el ID que fue liberado, al archivo de ID's liberados (
2872 ), al final del mismo (
2879 Se marca en el archivo índice (
2883 ) la eliminación, mediante el valor ¨-1¨ en el registro correspondiente
2884 al registro recién eliminado (se le cambia el valor al n-esimo registro,
2885 donde N = IDReg del reg eliminado).
2890 emufs_tipo2_borrar_registro()
2893 Modificación de registros
2896 Dada la naturaleza del archivo de ID's liberados, y el manejo de espacio
2897 libre del que consta esta organización de archivo, el proceso de modificación
2898 de un registro se limita a los siguientes pasos:
2901 Se realiza la lectura del registro, mediante el respectivo procedimiento
2902 ya desarollado anteriormente.
2905 Una vez que se cuenta con los nuevos datos modificados, se procede a dar
2906 de baja el registro que ha sido modificado, e inmediatamente después se
2907 realiza una inserción con los nuevos datos.
2916 Como fue indicado, dada la naturaleza de PILA del subsistema de administración
2917 de ID liberados, es asegurado que la nueva inserción del registro modificado
2918 se realizará con el mismo RegID.
2923 emufs_tipo2_modificar_registro()
2926 Obtención de estadísticas
2929 Se puede tener acceso a las estadísticas generales del archivo, por ejemplo,
2930 cantidad de bloques, cantidad de registros, espacio libre total, espacio
2931 libre promedio, espacio libre máximo y mínimo, etc.
2934 Esta información es el resultado de ciertos cálculos realizados tanto en
2935 el archivo de datos como en los archivos índice.
2938 Completa una estructura del tipo EMUFS_Estadisticas con las estadísticas
2939 del archivo de datos, espacio libre total, cantidad de registros, cantidad
2940 de bloques, tamaño del archivo en bytes, relaciones entre tamaños y espacios
2946 emufs_tipo2_leer_estadisticas()
2949 Compactación del archivo de datos
2952 Asi como los otros dos tipos de datos, el que nos compete también cuenta
2953 con la posibilidad de realizar la compactación de datos cuando el usuario
2954 lo desee, justificando todos los registros a izquierda, eliminando así
2955 los gaps existentes y decrementando el tamaño del archivo en disco (truncandolo
2959 Para poder comprender como hemos implementado el proceso de recompactación
2960 en nuestro tipo de archivo 2, nos ayudaremos de esquemas a través de los
2961 cuales iremos describiendo el proceso.
2962 Notemos antes, que el proceso de compactación esta directamente ligado
2963 con el archivo de gaps o espacios libres (
2970 Comenzemos con el siguiente cuadro situacional:
2971 \begin_inset Float figure
2978 Archivo con gaps entre registros previo a compactación
2982 \begin_inset Graphics
2983 filename graphics/Compact1.png
2995 Partiendo de esta base, el algoritmo de compactación tomará en su inicio
2996 al primer gap existente dentro del archivo de datos, en este caso llamado
3002 Luego, establecerá que el
3006 a partir de donde se quieren mover datos, sera:
3009 StartGap0 + SizeGap0 = EndGap0 = Source
3012 Lo cual no es nada más y nada menos que lo obvio, la fuente a partir de
3013 donde se mueven los datos, sera el fin del primer gap, donde comienzan
3019 ) del movimiento, se establece inicialmente, el inicio del gap, o sea
3021 StartGap0 = Destination
3026 Luego, el algoritmo entrara en un bucle while (mientras haya bucles por
3027 levantar), el cual trabajara hasta el final de la compactación de la siguiente
3038 Se levanta el proximo gap al levantado en una instancia previa.
3039 En este ejemplo, durante el primer loop del while, se levantará
3044 Luego, se calcula cuantos bytes hay que mover hacia el Destination de la
3068 Lo cual nuevamente es lógico pues querremos mover lo que se encuentra entre
3069 el final del primer gap levantado y el inicio del siguiente).
3072 Se realiza el movimiento de los datos, utilizando las direcciones
3080 , así como la variable
3084 que nos indica cuantos bytes transferir.
3090 La transferencia se hace de a chunks de 25 bytes + un resto segun el valor
3094 Se establece como gap de referencia, al ultimo gap leido (En este caso se
3107 ) y termina el código de repetición del bucle, dando lugar a la carga del
3108 siguiente gap en el inicio del mismo.
3116 Luego del primer bucle, el archivo se vera de la siguiente forma:
3117 \begin_inset Float figure
3124 Archivo con gaps en disco luego del primer bucle de compactación
3128 \begin_inset Graphics
3129 filename graphics/Compact2.png
3140 Notemos que al final de la porción de datos de los bytes movidos (donde
3145 ), hay basura que será pisada por el próximo movimiento.
3148 En el próximo loop, el bucle levantará un nuevo gap, y utilizando el gap
3149 anterior (En esta caso el Gap anterior será
3153 ) como referencia, realizará los mismos cálculos, desde donde transferir
3154 y cuantos bytes mover.
3155 (El destino es solo establecido inicialmente por código, y para el resto
3156 del algoritmo es el lugar donde quedo el puntero destination luego de la
3160 Una vez que se salga del bucle while, se realizará un último movimiento
3161 preprogramado, donde la fuente (
3165 ) será el final del ultimo gap, y la cantidad de bytes a mover será lo que
3166 se encuentre luego del mismo hasta el fin de archivo.
3169 Source = StartLastGap + SizeLastGap = EndLastGap
3172 Mustmove_bytes = Datsize - Source
3175 Damos por terminada así, la explicación del algoritmo de compresión el cual
3176 para el caso del tipo 2, es realmente bastante sencillo.
3181 emufs_tipo2_compactar()
3184 Consideraciones y Políticas de Diseño
3187 Se han tomado ciertas consideraciones para algunos casos particulares que
3188 se pueden presentar durante el uso/ejecución de la aplicación, así como
3189 tambien politicas respecto del diseño e implementación del sistema:
3192 En la organización física tipo 2 para los registros que se graban en disco
3193 hemos decidido utilizar como encabezado de cada uno de ellos, los datos
3194 [ID_REG][REG_SIZE], los cuales fueron detallados previamente.
3195 Si bien se podría haber descartado el grabado del ID del registro en el
3196 archivo de datos y puede parecer redundante, dado que poseemos el archivo
3197 índice con el offset directo, el mismo se lo graba por distintos motivos:
3201 A) En caso de la corrupción del archivo índice (.idx), podremos gracias a
3202 que poseemos en el archivo de datos, el ID de cada registro, recrear dicho
3203 índice, ayudándonos del archivo de espacios libres (
3207 ), para poder saltear los espacios libres y e ir recorriendo secuencialmente
3208 los registros, reconstruyendo así el índice en cuestión.
3209 (esta función de reconstrucción no pudo ser implementada para esta entrega,
3210 pero es una posibilidad real).
3214 B) Luego de un proceso de recompactación, los espacios libres que pudieron
3215 haber existido en el archivo de datos (
3219 ), son eliminados y los registros han cambiado de posición.
3220 Por ello, recorriendo secuencialmente por única vez el archivo de datos,
3221 se procede a la actualización / reconstrucción del índice de direcciones
3229 Si se desea insertar un registro y no se puede hayar un gap o espacio libre
3230 donde quepa, se los inserta al final del archivo.
3233 Ante una operación de baja de un registro, el mismo no es físicamente borrado
3234 del archivo de datos (
3238 ), simplemente los bytes que ocupa son llenados con hexa (00).
3239 Paralelamente, se procede a actualiza el archivo índice, insertando como
3240 valor de OFFSET para el registro eliminado, el valor ¨-1¨, indicando así
3241 la inexistencia del registro para el futuro, y por otro lado se genera
3242 la entrada de espacio libre en el archivo de gaps (
3249 La reutilización de ID's liberados por previas operaciones de baja de registros,
3250 se ve implementada por el archivo de ID liberados (.did), y su comportamiento
3251 es el de una pila por lo que el último ID liberado, sera el próximo a ser
3255 Como fue explicado en la implementación del archivo índice, existe una correspon
3256 dencia 1 a 1 entre los registros allí presentes (en el .idx) y los ID's de
3257 los registros, por lo cual el registro N-ésimo del archivo índice, será
3258 el correspondiente al registro de datos cuyo ID es igual a N.
3261 El proceso de compactación de archivos, realiza los movimientos de información
3262 requeridos para dicho propósito de a chunks de 25 bytes por vez.
3263 Este valor es fijo, pero se lo podría hacer parametrizable mediante la
3264 GUI en próximas entregas.
3268 \begin_inset LatexCommand \label{cha:tipo3}
3272 Archivo con bloques parametrizados y registros de longitud constante
3275 Las distintas organizaciones de archivos buscan aprovechar al máximo el
3276 espacio del archivo.
3279 En este caso veremos que sucede luego de agregar y borrar una gran cantidad
3280 de registros del archivo, lo que provoca como consecuencia directa la fragmenta
3281 ción del archivo, es decir, quedan huecos entre un registro y otro, lo que
3282 produce un desperdicio de espacio.
3285 La implementación de este tipo de archivo puede ser encontrada en
3289 mientras que su interfaz pública está disponible en
3299 Esta organización guarda los registros pertenecientes al archivo en bloques
3300 de tamaño parametrizado, de modo que intentará guardar la mayor cantidad
3301 de registros que quepan en un bloque.
3305 Así como los graba, también tendrá la posibilidad de leer registros y borrarlos
3309 El archivo estara compuesto por una cabecera que da información sobre el
3310 tipo de organización, el tamaño de los bloques y el tamaño de los registros.
3313 Organización Física de un Bloque
3316 Cada bloque será capaz de contener la cantidad de registros enteros que
3318 De esta manera un registro que no entre completamente en el bloque deberá
3319 almacenarce en un bloque diferente.
3322 Los bloques no contienen ninguna información adicional, solo se conoce su
3323 tamaño y se usa para delimitar
3324 \begin_inset Quotes eld
3328 \begin_inset Quotes erd
3331 zonas en el archivo.
3334 Organizacion Física de Registros
3337 Cada registro se almacena en un bloque, y contiene una cabecera que indica
3342 por este motivo al realizar la busqueda de espacio en un bloque se lo hará
3343 preguntando por el tamaño del registro más
3345 sizeof(EMUFS_REG_ID).
3349 Organización Física de Registros Multibloque
3352 Al ser los registros de longitud constante, se ha adoptado que un registro
3353 multibloque nunca podra estar almacenado en algún lugar que no sea el comienzo
3355 De esta manera se puede calcular cuantos bloques ocupará un registro y
3356 se podrá solicitar lugar para almacenarlo con la ayuda de la función
3358 emufs_fsc_buscar_n_lugares(),
3360 que es muy importante para evitar el solapamiento de registros.
3361 Esta consideración acarrea como consecuencia directa un alto costo en términos
3362 del espacio desperdiciado.
3365 Funciones Principales
3376 se encuentran las cabeceras y la implementación de las funciones principales
3377 respectivamente, las cuales dan funcionalidad a esta organización.
3380 A continuación se comentará la descripción de algunas acciones importantes.
3386 La lectura de un registro se realiza con la ayuda del archivo .
3390 el cual contiene la información de la posición del registro dentro del
3392 Una vez leida esta información, se recupera el bloque (en su totalidad)
3393 del archivo y se busca secuencialmente el registro con el
3402 emufs_tipo3_leer_registro()
3408 Graba un registro en un bloque donde haya espacio suficiente, y si no crea
3409 un nuevo bloque y lo agrega al final del archivo.
3412 Luego de grabar un registro, actualiza los archivos de índice .idx y .fsc
3413 para mantener la coherencia.
3418 emufs_tipo3_grabar_registro()
3424 Borra un registro del archivo de datos, para esto levanta el bloque al que
3425 pertenece el archivo y ajusta los demás registros justificandolos hacia
3429 Cabe destacar que para dar de baja un registro no hace falta borrarlo del
3430 archivo de datos, solo es necesario borrar las entradas en los archivos
3431 de índice, pero cuando se realiza el ajuste el algoritmo toma porciones
3432 del bloque del tamaño de un registro mas su encabezado - comenzando desde
3433 el siguiente al que fue borrado - y copia (sobreescribe) sobre el anterior.
3434 De esta manera, la información correspondiente al registro borrado no estará
3435 presente en el archivo de datos.
3436 Esto es una consecuencia del ajuste al borrar un registro, pudiendo no
3437 ser así, si no se realizara el mismo.
3442 emufs_tipo3_borrar_registro()
3448 Se puede tener acceso a las estadísticas generales del archivo, por ejemplo,
3449 cantidad de bloques, cantidad de registros, espacio libre total, espacio
3450 libre promedio, espacio libre máximo y mínimo, etc.
3453 Esta información es el resultado de ciertos cálculos realizados tanto en
3454 el archivo de datos como en los archivos índice.
3457 Completa una estructura del tipo EMUFS_Estadisticas con las estadísticas
3458 del archivo de datos, espacio libre total, cantidad de registros, cantidad
3459 de bloques, tamaño del archivo en bytes, relaciones entre tamaños y espacios
3465 emufs_tipo3_leer_estadisticas()
3468 Compactar el Archivo
3471 Esta función intenta reorganizar el archivo de manera que el espacio libre
3472 sea lo menor posible, recordando siempre que un registro no puede ser almacenad
3473 o en mas de un bloque excepto que el tamaño del registro sea mayor que el
3477 Para realizar esto, se aprovecha la funcionalidad de
3479 emufs_tipo3_grabar_registro()
3481 ya que esta tiene la capacidad de determinar una posición mas eficiente
3482 en el archivo para un registro.
3483 Por esto lo que se hace es levantar uno por uno los registros y volverlos
3484 a grabar, de ese modo todos los
3488 que pudieron haberse formado por la eliminación de registros serán cubiertos
3492 Al estar utilizando recuperación de
3496 borrados, esto me asegura que el registro borrado-guardado conservará el
3500 Al finalizar este proceso se verifica si existen bloques vacios para truncar
3502 Lo mismo se debe hacer con el archivo de espacios libres .
3506 el cual disminuye su tamaño también.
3511 void emufs_tipo3_compactar()
3514 Consideraciones y Políticas de Diseño
3517 Se han tomado ciertas consideraciones para algunos casos particulares que
3518 se pueden presentar durante el uso/ejecución de la aplicación.
3521 Cada registro tiene un encabezado que indica el
3528 Si el tamaño del registro es mayor que el tamaño del bloque el registro
3529 se particionará en la cantidad de bloques que sea necesario, pero siempre
3530 se guardará desde el comienzo de un bloque, esto quiere decir que nunca
3531 se podrá encontrar un comienzo de registro en algún lugar de un bloque
3532 que no sea el comienzo del mismo.
3535 Si el registro se divide en mas de un bloque, se le coloca el id como encabezado
3536 igualmente, pero en el archivo .
3540 solo se guarda el primer bloque.
3545 se actualizan todos los bloques con el espacio libre que realmente tienen.
3551 Las comparaciones, pruebas, etc...