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
199 EMUFS *emufs_crear(const char *filename, EMUFS_Tipo tipo,EMUFS_BLOCK_SIZE
200 tam_bloque, EMUFS_REG_SIZE tam_reg),
206 es el nombre que tendrán los archivos de datos e índice,
210 es el tipo de organización - bloques parametrizados y registros constantes
215 es el tamaño del bloque, y
219 es el tamaño del registro.
222 Para las diferentes organizaciones puede ser que alguno de estos 2 últimos
223 valores no tengan sentido almacenarlas y tomaran un valor por defecto igual
227 Según el tipo de organización, se inicializan los punteros a las funciones.
234 emufs_tipo3_leer_bloque()
236 , y lo mismo sucede con los demás.
246 es un tipo de dato enum, el cual será utilizado en la cabecera de todo
251 ), para indicar los distintos tipos de organización física.
252 Su declaración puede verse en el archivo
257 A saberse los valores y significado correspondiente que puede tomar este
261 Archivos con registros de longitud variable y bloques parametrizables.
264 Archivos con registros de longitud variable sin bloques.
267 Archivos con registros de longitud fija y bloques parametrizables.
277 es una estructura que almacenará los datos pertinentes a las estadísticas
278 de un archivo dado, y será utilizada para visualizar dichas observaciones
282 Su declaración puede ser observada en el archivo
286 y la misma cuenta con los siguiente campos:
293 tam_archivo: indica el tamaño del archivo de datos (.dat) en bytes.
300 tam_archivos_aux: indica el tamaño de los archivos auxiliares sumados en
308 tam_info_control_dat: indica la cantidad de bytes en información de control
309 utilizados para el archivo.
316 media_fs: promedio de espacio libre en el archivo de datos (por bloque
317 o gap promedio segun la org)
324 total_fs: total de espacio libre en el archivo de datos.
331 max_fs: máximo espacio libre en el archivo de datos (en un bloque o máximo
339 min_fs: idem pero mínimo.
346 cant_bloques: cantidad de bloques en el archivo de datos (.
357 cant_registros: cantidad de registros en el archivo de datos (
364 En base a la estructura descripta anteriormente y mediante la utilización
367 emufs_leer_estadisticas()
369 disponible en la estructura común
373 handler de cualquier tipo de archivo, podremos obtener una serie de estadística
374 s que pasamos a detallar (más alla de los datos básicos como cant registros,
375 cant bloques, tam archivo, etc):
378 Relación entre espacio libre y el tamaño del archivo de datos (
385 Relación entre el espacio ocupado por información de control y el tamaño
386 del archivo de datos (
393 Cantidad promedio de espacio libre (en bloque o gap promedio)
396 Desviaciones extremas de espacio libre (máximo/mínimo espacio libre en bloque
403 En la implementación de cada tipo de organización física, así como tambien
404 en las API de los archivos auxiliares comunes a ellas, se da la utilización
405 de tipo definidos para una clara interfaz entre las mismas, los cuales
406 son brevemente descriptos a continuación y pueden ser hayados en el archivo
416 unsigned long EMUFS_REG_ID
418 : usado para representar un
427 unsigned long EMUFS_REG_SIZE
429 : usado para representar el tamaño en bytes de un registro.
434 unsigned long EMUFS_BLOCK_ID
436 : usado para representar un número de bloque.
441 unsigned long EMUFS_BLOCK_SIZE
443 : usado para representar el tamaño en bytes de un bloque.
448 unsigned long EMUFS_FREE
450 : usado para representar espacio libre en bytes.
455 unsigned long EMUFS_OFFSET
457 : usado para representar un offset.
461 \begin_inset LatexCommand \label{sec:cabecera_gral}
465 Organización física general de un archivo E
466 \begin_inset Formula $\mu$
473 \begin_inset Formula $\mu$
476 FS está compuesto por 4 archivos a nivel de sistema operativo: archivo de
477 datos (con 3 formatos posibles, ver páginas
478 \begin_inset LatexCommand \pageref{cha:tipo1}
483 \begin_inset LatexCommand \pageref{cha:tipo2}
488 \begin_inset LatexCommand \pageref{cha:tipo3}
492 ), archivo de índice (ver página
493 \begin_inset LatexCommand \pageref{sec:idx}
497 ), archivo de control de espacio libre (ver página
498 \begin_inset LatexCommand \pageref{sec:fsc}
502 ) y archivo de índices recuperables (ver página
503 \begin_inset LatexCommand \pageref{sec:did}
510 El archivo de datos está compuesto por:
521 (4 bytes en plataformas Linux de 32 bits) que representa el tipo de archivo.
524 Datos dependientes del tipo de archivo.
531 es utilizada para poder detectar el formato de un archivo al abrirlo.
532 Los datos dependientes del tipo de archivo serán explicados en sus secciones
539 +-----------+--------------------------------------------//-+
542 | tipo | Datos dependientes del tipo de archivo ...
550 +-----------+--------------------------------------------//-+
559 Acompañando al archivo de datos (
563 ) el cual es responsable de la contención de los registros, tendremos tres
564 archivos auxiliares (
576 ) cuya funcionalidad y propósito pasamos a describir a continuación, sin
577 antes remarcar que los tres archivos poseen una sola implementación para
578 las distintas formas de organización física que hemos implementado (tres
579 para ser mas exactos).
582 Entre las ventajas de poseer la misma implementación se encuentra el tener
583 un API común entre los tres tipos para el manejo de la localización de
584 sus registros, administración de espacio libre e Id's liberados, sin necesidad
585 de realizar n-implementaciones para un mismo objetivo final.
588 Además, la obtención de ciertos datos estadísticos como espacio libre, o
589 cantidad de registros, se realiza a través de la misma interfaz, y también
590 se ha facilitado en cierto grado la re-organización física de un archivo
591 (pasar de un tipo a otro), dado el uso de estos tres archivos auxiliares
592 en común para funciones tan predominantes como índexación, administración
593 de espacio libre y recuperación de Id's.
597 \begin_inset LatexCommand \label{sec:idx}
604 El archivo índice (.idx), permite la localización de los registros en el
605 .DAT de forma directa, mediante la obtención de su offset respecto del inicio
606 del .dat, o nro bloque (segun el tipo de organización física) en donde se
607 encuentra un registro dado, indicado por su
612 Los registros de este archivo se encuentran representados una estructura
613 que indica un número de registro y el bloque u offset en donde se encuentra
617 Es necesario que este archivo esté ordenado por
621 , ya que esto permitirá el acceso directo al mismo, para la rápida obtención
622 del nro de bloque u offset y posterior búsqueda de un registro en el archivo
629 Los registros de este archivo se encuentran representados a nivel codigo
630 por el siguiente tipo de dato interno (
637 typedef unsigned long EMUFS_REG_ID;
640 typedef unsigned long EMUFS_OFFSET;
643 typedef struct emufs_idx_t {
649 EMUFS_OFFSET location;
656 \begin_inset Float table
663 Ejemplo de registro en archivo índice (.idx), para un archivo de organizacion
669 <lyxtabular version="3" rows="2" columns="3">
671 <column alignment="center" valignment="top" leftline="true" width="0">
672 <column alignment="center" valignment="top" leftline="true" width="0">
673 <column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
674 <row topline="true" bottomline="true">
675 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
683 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
691 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
699 <row topline="true" bottomline="true">
700 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
708 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
716 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
721 Indica que el registro de id_reg = 5, se encuentra en el bloque 54
733 \begin_inset Float table
740 Ejemplo de registro en archivo índice (.idx), para un archivo de organizacion
746 <lyxtabular version="3" rows="2" columns="3">
748 <column alignment="center" valignment="top" leftline="true" width="0">
749 <column alignment="center" valignment="top" leftline="true" width="0">
750 <column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
751 <row topline="true" bottomline="true">
752 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
760 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
768 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
776 <row topline="true" bottomline="true">
777 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
785 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
793 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
798 Indica que el registro de id_reg = 5, se encuentra en el bloque 54
818 Como se puede observar, para distintas organizaciones el significado de
819 los registros en este archivo es diferente y se utilizará de distinta manera
826 Las declaraciones e implementación se pueden encontrar en
840 \labelwidthstring 00.00.0000
848 Los registros del archivo indice (
852 ), poseen una correspondencia 1 a 1, con los Id's de los registros en el
858 Con esto, queremos decir que el N-ésimo registro del archivo índice, será
859 aquél que posea la información para localizar al registro cuyo
863 es N, dentro del archivo de datos (
873 Cabe aclarar que por si bien el indice se encuentra ordenado por
877 , los registros en el archivo de datos, por lo general no lo estarán.
883 emufs_idx_buscar_registro()
885 \labelwidthstring 00.00.0000
891 Ante la alta de un registro en el archivo de datos, se insetará un nuevo
892 registro en el archivo índice, con el id_reg del registro en cuestion,
893 y el offset u bloque donde se lo haya grabado en disco.
899 \labelwidthstring 00.00.0000
905 Ante el borrado de un registro del archivo de datos, se accederá el registro
906 correspondiente en el índice, y se actualizara su LOCATION, estableciendolo
907 en el valor -1 UL, el cual indica que ese registro ha sido eliminado y
908 por ende no se lo podrá localizar en el futuro.
909 Como se verá mas adelante, según el tipo de organización física, el registro
910 puede ser borrado concretamente del .
921 \labelwidthstring 00.00.0000
927 Ante la modificación en la posición física de un registro dentro del archivo
928 de datos (por ejemplo luego del proceso de recompactación, se realizará
929 la modificación respectiva del campo
937 emufs_idx_actualizar()
941 \begin_inset LatexCommand \label{sec:fsc}
945 Archivo de control de espacio libre
948 El archivo de espacio libre (
952 ) (espacio por bloque o gaps en archivo, según el tipo de organización física),
953 tiene como función la administración del espacio libre, generado por previas
954 eliminaciones de registros en el archivo de datos.
955 El mismo, nos indicará donde hay lugar para insertar un nuevo registro.
958 Para el caso de una organización por bloque, nos dirá en que bloque o si
959 se debe generar un nuevo bloque.
960 En el caso de la organización sin bloques, nos indicará en que gap o si
961 al final del archivo.
964 Los registros de este archivo se encuentran representados una estructura
965 que indica un número de bloque u offset y el espacio libre disponible en
966 el mismo (o apartir del mismo en el caso del offset).
973 : Por requerimiento del algoritmo de compactación el tipo de organización
974 física con reg long var, sin bloques, los gaps se graban en forma ordenada
976 (El orden se corresponde con lo que hay en el .dat).
982 Los registros de este archivo se encuentran representados a nivel codigo
983 por el siguiente tipo de dato interno (
990 typedef struct emufs_fsc_t {
993 unsigned long int marker;
996 unsigned long int freespace;
1006 \begin_inset Float table
1013 Ejemplo de registro en archivo de control de espacio libre para un archivo
1018 \begin_inset Tabular
1019 <lyxtabular version="3" rows="2" columns="3">
1021 <column alignment="center" valignment="top" leftline="true" width="0">
1022 <column alignment="center" valignment="top" leftline="true" width="0">
1023 <column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
1024 <row topline="true" bottomline="true">
1025 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
1033 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
1041 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
1049 <row topline="true" bottomline="true">
1050 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
1058 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
1066 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
1071 Indica que en el bloque 12, hay 120 bytes libres al final del mismo.
1083 \begin_inset Float table
1090 Ejemplo de registro en archivo de
1094 para un archivo sin bloques
1098 \begin_inset Tabular
1099 <lyxtabular version="3" rows="2" columns="3">
1101 <column alignment="center" valignment="top" leftline="true" width="0">
1102 <column alignment="center" valignment="top" leftline="true" width="0">
1103 <column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
1104 <row topline="true" bottomline="true">
1105 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
1113 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
1121 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
1129 <row topline="true" bottomline="true">
1130 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
1138 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
1146 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
1151 Indica que a partir del byte 12 del archivo de datos, hay 120 bytes libres.
1171 Como se puede observar, para distintas organizaciones el significado de
1172 los registros en este archivo es diferente y se utilizará de distinta manera
1176 Funciones principales
1179 Las declaraciones e implementación se pueden encontrar en
1193 \labelwidthstring 00.00.0000
1199 Ante la operación de alta de un registro en el archivo de datos, se realizará
1200 la búsqueda de espacio libre donde este podrá ser insertado.
1201 En el caso de organizaciones con bloques, se buscará en que
1205 se posee espacio suficiente para albergar el nuevo registro.
1206 En el caso de organizacion sin bloque, se buscará un gap o espacio libre
1207 en el archivo, obteniéndose en consecuencia, el
1215 emufs_fsc_buscar_lugar()
1217 \labelwidthstring 00.00.0000
1223 Luego de una operación de baja o alta de un registro en el archivo de datos
1228 ), incrementará o decrementará respectivamente el espacio libre en el archivo
1229 de datos, y esto deberá ser registrado, agregando un nuevo registro en
1230 el archivo de espacios libres (
1234 ) o bien modificandoló.
1238 En el caso de organizaciónes con bloques, se actualizará el valor del espacio
1243 en el bloque (ya sea incrementandoló o decrementandoló) o bien se insertará
1244 un nuevo registro en caso de que se esté creando un nuevo bloque en el
1245 archivo de datos (en este caso no será debido a un alta o baja de registro
1246 como se mencionó al principio).
1250 Para el caso de organización sin bloques, en el caso de baja de un registro
1255 ) se insertará un nuevo registro en el
1259 dando cuenta de la aparición de un nuevo gap en el archivo de datos (
1263 ), y en caso de estar este lindante con otro gap, se realizará el merge
1265 (esto esta explicado más en profundidad en los casos particulares de organizaci
1266 ón fisica, registros variables sin bloques).
1267 Para el caso de una alta en el archivo de datos (
1271 ), el valor del gap donde se haya insertado se actualizará.
1276 emufs_fsc_agregar(), emufs_fsc_agregar_gap(), emufs_fsc_actualizar(), emufs_fsc_
1279 \labelwidthstring 00.00.0000
1285 : Unicamente para el caso de una organización que presente gaps en el archivo,
1286 se podrá dar a lugar la eliminación de un registro del archivo de espacios
1292 Esta situación tendrá efecto cuando se inserte un registro que entre perfecto
1293 en un gap disponible, y por ende el gap desaparecerá.
1297 emufs_fsc_borrar_gap()
1301 \begin_inset LatexCommand \label{sec:did}
1305 Archivo de id's recuperables
1308 El archivo de Id's liberado (
1312 ) llevará cuenta de aquellos Id's de registros (
1316 ) que ya no se encuentran siendo utilizados y fueron liberados por registros
1317 eliminados previamente.
1318 A través del mismo, se podrá realizar la reutilización de Id's ante la
1319 alta de nuevos registros.
1322 A nivel físico, este archivo poseerá una secuencia de datos del tipo EMUFS_REG_I
1323 D, y el comportamiento del sistema de recuperación de Id's será el de una
1325 Es decir, ante el requerimiento de un
1329 libre por una función del sistema como por ejemplo la alta de un nuevo
1330 registro, el API del archivo (
1334 ), obtendrá el último dato del mismo (el
1338 que fue liberado mas recientemente), y truncará el archivo eliminando el
1343 recuperado de la tabla.
1344 (LIFO, Last in First Out).
1350 Este archivo tiene registros de un solo campo,
1354 el cual simboliza al id que fue liberado en un proceso de baja de registros.
1357 Funciones principales
1360 Las declaraciones e implementación se pueden encontrar en
1374 \labelwidthstring 00.00.0000
1380 Ante la eliminación de un registro del archivo de datos (
1384 ) se procederá al agregado del correspondiente
1388 que fue liberado por dicha operación, al archivo
1402 \labelwidthstring 00.00.0000
1408 Cuando el sistema desee grabar un nuevo registro en el archivo de datos,
1413 disponible para el mismo.
1414 El sistema de administración de Id's libres, obtendrá el último
1418 que se guardó en el archivo (o se eliminó del archivo de datos), y truncará
1419 el archivo eliminandolo.
1427 emufs_did_get_last()
1431 \begin_inset LatexCommand \label{cha:tipo1}
1435 Archivo con bloques parametrizados y registros de longitud variable
1438 Este tipo de archivo tiene varias complicaciones, al tratarse de un punto
1440 \begin_inset LatexCommand \ref{cha:tipo2}
1445 \begin_inset LatexCommand \ref{cha:tipo3}
1449 (cuenta tanto con bloques como con registros variables), hereda los inconvenien
1450 tes (y ventajas) de ambos, más los propios.
1451 Al implementar este tipo de archivo se puso enfásis en la eficiencia mientras
1452 esta no comprometa la mantenibilidad del código, es por esto que en algunas
1453 circunstancias no se hace un uso óptimo del espacio.
1456 La implementación de este tipo de archivo puede ser encontrada en
1460 mientras que su interfaz pública está disponible en
1470 El archivo está compuesto por la
1475 \begin_inset LatexCommand \pageref{sec:cabecera_gral}
1480 El valor que toma en este tipo de archivo es 0 (o el valor simbólico
1489 Luego le sigue una cabecera propia del archivo (un
1493 , 4 bytes) que almacena el tamaño del bloque que usa el archivo.
1494 De esta menera, al abrir un archivo de este tipo no se necesita tener ninguna
1495 información sobre él.
1496 A esta cabecera le siguen cero o más bloques del tamaño fijo especificado
1497 en la cabecera antes mencionada.
1503 +-----------+-----------+------------------------//-+
1506 | tipo | tam bloque| Cero o más bloques ...
1514 +-----------+-----------+------------------------//-+
1517 /- 4 bytes -/- 4 bytes -/
1520 Organización física de un bloque
1523 Cada bloque no guarda información en sí, sólo se comporta como un contenedor
1525 Esto no significa que un bloque no tenga utilidad, el bloque es utilizado
1526 para proveer un acceso semi-aleatorio a los registros.
1527 Para esto se utiliza el archivo de índice (ver página
1528 \begin_inset LatexCommand \ref{sec:idx}
1532 ), que almacena pares [identificador de registro, número de bloque].
1533 Para que sea suficiente este único índice para hallar un registro (siendo
1534 que puede haber más de un registro por bloque), es necesario
1536 alinear los registros a izquierda
1539 Esto significa que hay que asegurar que siempre los registros en un bloque
1540 se presenten de forma consecutiva, jamás permitiendo que haya un espacio
1541 libre entre registros (en un mismo bloque).
1544 Podemos ver un ejemplo de esto en forma gráfica:
1547 bloque N-1 | bloque N | bloque N+1
1550 /----------+------------+------------+---------------+-----------/
1555 | registro 1 | registro 2 | espacio libre |
1560 /----------+------------+------------+---------------+-----------/
1563 /------------- tamaño del bloque ---------/
1566 De esta forma, una vez obtenido el número de bloque, se pueda recorrer secuencia
1567 lmente hasta encontrar el registro deseado.
1568 A fin de llevar el conteo de espacio libre se utiliza el archivo de control
1569 de espacio libre (ver página
1570 \begin_inset LatexCommand \ref{sec:fsc}
1574 ), de forma tal que no sea necesario recorrer secuencialmente en busca de
1575 espacio libre al hacer una inserción.
1578 Puede darse un caso excepcional en el que un registro sea más grande que
1579 un bloque, en este caso el registro se almacenará en N bloques consecutivos
1580 (siendo N la cantidad de bloques que necesita el registro), ocupando completos
1581 los todos los bloques a excepción del último, en el que posteriormente
1582 se pueden agregar más registros.
1583 \layout Subsubsection
1586 \begin_inset LatexCommand \label{sub:tipo1_reg}
1590 Organización física de un registro.
1593 El registro es el que representa al dato realmente que se quiere almacenar.
1594 Para representar ese dato se necesita una determinada información de control,
1595 tanto para poder identificar el registro en un bloque (en búsquedas secuenciale
1596 s dentro del bloque) como para saber su longitud (dado que este tipo de
1597 archivo utiliza registros de tamaño variable).
1600 Siguiendo la metodología general de E
1601 \begin_inset Formula $\mu$
1604 FS, se optó por incluir esta información de control como una cabecera al
1605 comienzo del registro, siguiendo a esta los datos en sí.
1606 La cabecera está compuesta por un identificador (
1610 ) de registro (EMUFS_REG_ID, 4 bytes) seguido por el tamaño (
1614 ) del registros (EMUFS_REG_SIZE, 4 bytes).
1615 Podemos ver gráficamente como se se compone un registro:
1621 +-----------+-----------+------------------+
1624 | id | tamaño | datos ...
1628 +-----------+-----------+------------------+
1631 /- 4 bytes -/- 4 bytes -/- [tamaño] bytes -/
1632 \layout Subsubsection
1635 \begin_inset LatexCommand \label{sub:tipo1_reg_multi}
1639 Organización física de un registro más grande que un bloque (registro
1646 Puede darse el caso excepcional en que un registro sea de mayor longitud
1648 Al ser una situación excepcional, no siempre se resuelve de la forma más
1649 eficiente ni se mínimiza el espacio ocupado por datos de control (como
1650 se dijo anteriormente, se prefirió conservar la simpleza del código, adoptando
1651 algoritmos generales aunque no sea de la forma más eficiente o maximizando
1652 el uso del espacio para no perjudicar la mantenibilidad).
1655 Para menejar un registro
1659 se optó por limitarlo a la siguiente estructura (suponiendo que el registro
1660 ocupa N bloques, con N > 1 y que un
1664 es una porción del registro que entra en un bloque):
1671 se almacenan en bloques completos consecutivos.
1674 El último fragmento se almacena al comienzo del bloque inmediatamente posterior
1678 Cada framento posee las cabeceras mencionadas en la sección
1679 \begin_inset LatexCommand \ref{sub:tipo1_reg}
1683 , cuyo contenido es el siguiente:
1691 se almacena el identificador único obtenido al hacer el alta.
1698 se almacena el tamaño del
1702 actual más los tamaños de los
1706 posteriores, quedando en el primer
1710 el tamaño completo del registro y en el último sólo el tamaño del
1718 Como puede observarse, la información de control en los
1722 intermedios puede ser redundante, pero se conserva para poder realizar
1723 algoritmos genéricos (que se basan en que al principio de un bloque, si
1724 no está vacío, hay una cabecera de un registro) y para facilitar chequeos
1725 de integridad del archivo.
1728 A continuación se presenta un ejemplo gráfico de un registro multibloque
1729 de 10 bytes (de contenido
1730 \begin_inset Quotes eld
1734 \begin_inset Quotes erd
1737 ) almacenado en un archivo con bloques de 4 bytes:
1740 | bloque 0 | bloque 1 | bloque 2
1743 +-------------------+-------------------+-------------------+-//-+
1746 | registro 0 - 1/3 | registro 0 - 2/3 | registro 0 - 3/3..|
1753 |+----+-----+------+|+----+-----+------+|+----+-----+----+..| // |
1756 || id | tam | datos||| id | tam | datos||| id | tam |dato|..|
1763 ||----+-----+------+||----+-----+------+||----+-----+----+..| // |
1766 || 0 | 10 | 1234 ||| 0 | 6 | 5678 ||| 0 | 2 | 90 |..|
1773 |+----+-----+------+|+----+-----+------+|+----+-----+----+..| // |
1776 +-------------------+-------------------+-------------------+-
1783 Funciones principales
1786 Las funciones principales son las necesarias para completar la estructura
1788 \begin_inset LatexCommand \pageref{sub:EMUFS}
1795 Lectura de registros
1798 Para leer un registro se hace uso del archivo de índice (ver página
1799 \begin_inset LatexCommand \pageref{sec:idx}
1803 ), obteniéndose el número de bloque en donde está almacenado el registro
1805 Una vez obtenido, se carga en memoria el bloque entero y se busca secuencialmen
1806 te en él (leyendo la cabecera de cada registro y salteando los datos) hasta
1807 encontrar el registro pedido.
1808 Una vez encontrado se lo copia y devuelve.
1811 Si se tratara de un registro
1816 \begin_inset LatexCommand \ref{sub:tipo1_reg_multi}
1820 ), se procede forma similar, sólo que se cargan en memoria uno a uno los
1821 bloques que componen el registro y se van copiando (y uniendo) los
1830 emufs_tipo1_leer_registro()
1836 Para realizar el alta de un registro, lo primero que se obtiene es un identifica
1837 dor, buscando primero en el archivo de identificadores recuperables (pág.
1839 \begin_inset LatexCommand \ref{sec:did}
1843 ) y de no haber ninguno, buscando el mayor identificador presente en el
1844 archivo de índice (pág.
1846 \begin_inset LatexCommand \ref{sec:idx}
1851 El paso siguiente es buscar un bloque con espacio libre suficiente como
1852 para almacenar el registro (y su cabecera) en el archivo de control de
1855 \begin_inset LatexCommand \ref{sec:fsc}
1859 ) y cargarlo completo en memoria.
1860 De no encontrarse, se crea un bloque nuevo al final de archivo.
1861 En el bloque cargado en memoria, se agrega el registro nuevo (con su cabecera)
1862 al comienzo del espacio libre (calculado a partir del tamaño del bloque
1863 y el espacio libre en bloque) y se lo graba en disco.
1864 Finalmente se agrega (o actualiza) el identificador al archivo índice y
1865 el espacio libre en el bloque.
1868 Si el registro ocupara más de un bloque (ver sección
1869 \begin_inset LatexCommand \ref{sub:tipo1_reg_multi}
1873 ), se buscan N bloques consecutivos (todos los que necesite el registro)
1874 absolutamente libres
1880 Incluso el último bloque debe estar absolutamente libre para cumplir con
1881 las condiciones presentadas en la sección
1882 \begin_inset LatexCommand \ref{sub:tipo1_reg_multi}
1889 y graba bloque a bloque cada
1893 del registro (con sus cabeceras intermedias), al último
1897 se lo trata de forma análoga a un registro
1902 Por cada bloque utilizado se actualiza el archivo de control de espacio
1908 emufs_tipo1_agregar_registro()
1916 emufs_tipo1_borrar_registro()
1919 Modificación de registros
1924 emufs_tipo1_modificar_registro()
1927 Obtención de estadísticas
1932 emufs_tipo1_leer_estadisticas()
1935 Compactación del archivo de datos
1940 emufs_tipo1_compactar()
1943 Detalles de implementación (funciones internas, ver si lo ponemos o no)
1947 \begin_inset LatexCommand \label{cha:tipo2}
1951 Archivo sin bloques y registros de longitud variable
1954 Este tipo de archivo nos traerá a la mesa la particularidad de grabar registros
1955 de longitud variable sin realizar su agrupación en bloques, y como veremos
1956 en la siguiente sección, tambien permitirá la administración de gaps que
1957 queden en el archivo luego de operaciones de baja de registros.
1963 Este tipo de archivo realizará el almacenamiento de registros de longitud
1964 variable en disco, su borrado y modificación sin la utilización de bloques
1966 Su implementación se encuentra en los archivos fuente (
1977 Los archivos del tipo 2, presentarán al comienzo del mismo un header compuesto
1978 simplemente por un dato del tipo EMUFS_Tipo (int) el cual indicará el tipo
1979 de archivo en cuestión.
1982 Para poder entender mejor la organización fisica de este tipo de archivo,
1983 tomemos el caso hipotético en el que se encuentran grabados
1987 (comenzando desde registro 0) de
1996 Supongamos también que entre el registro 0 y 1 se encontraba un
1998 registro de 10 bytes
2013 Si miramos al archivo de datos (.dat) en el disco nos encontraremos con
2015 \begin_inset Float figure
2022 Organización física de los registros en disco
2026 \begin_inset Graphics
2027 filename graphics/Example1.png
2038 Como se puede observar, a nivel físico cada registro grabado esta compuesto
2039 por un Header cuyo tamaño total es de 8 bytes (
2047 ), y posteriormente el registro (bloque de datos) en sí.
2048 Luego se encuentra el espacio libre de 18 bytes dejado por el registro
2049 de 10 bytes eliminado (10 bytes de datos + header de 8 bytes) y finalmente
2050 el segundo registro mencionado.dsds
2053 Comportamiento Particular de los Archivos Auxiliares
2056 Como fue explicado al inicio de la documentación, la implementación de cualquier
2057 a de las tres organizaciones físicas de archivos presenta la necesidad de
2058 poseer tres archivos auxiliares que actuarán como índice de direcciones
2063 ), administrador de espacio libre (
2067 ) y administrador de Id's liberados (
2074 No obstante, cada tipo de organización presentara sus particularidades respecto
2075 de estos tres archivos, las cuales describiremos a continuación en caso
2077 \layout Subsubsection
2079 Archivo índice o de posiciones relativas (.idx)
2086 ), permite la localización de los registros en el .DAT de forma directa,
2087 mediante la obtención de su offset o posición relativa respecto del inicio
2092 en donde se encuentra un registro dado, indicado por su ID.
2095 Así pues, si tomamos el ejemplo descripto al inicio de este capítulo, tendremos
2096 las siguientes entradas en el archivo índice
2101 \begin_inset Float table
2108 Organización física del archivo de índice o posiciones relativas.
2112 \begin_inset Tabular
2113 <lyxtabular version="3" rows="3" columns="3">
2115 <column alignment="center" valignment="top" leftline="true" width="0">
2116 <column alignment="center" valignment="top" leftline="true" width="0">
2117 <column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
2118 <row topline="true" bottomline="true">
2119 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2129 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2139 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
2147 <row topline="true">
2148 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2158 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2168 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
2173 El primer registro (reg0) comienza en el byte 4
2177 <row topline="true" bottomline="true">
2178 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2186 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2196 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
2201 El segundo registro (reg1) comienza en el byte 60
2221 LOCATION indica donde comienza el header del registro buscado, y por consiguien
2222 te luego del header tendremos el registro en sí (los datos).
2223 \layout Subsubsection
2225 Achivo de Gaps / Espacios Libres (.fsc)
2228 El archivo de espacios libres o gaps (.fsc), tiene como función la administración
2229 del espacio libre o gaps (agujeros), generados por previas eliminaciones
2230 de registros en el archivo de datos.
2231 El mismo, nos indicará donde hay lugar para insertar un nuevo registro
2232 (se podrán insertar en algún gap acorde, o bien al final del archivo).
2233 Este archivo será utilizado tambien para el proceso de compactación de
2234 un archivo, explicado luego.
2237 Así pues, si tomamos el ejemplo descripto al inicio del documento, tendremos
2238 las siguientes entradas en el archivo índice
2243 \begin_inset Float table
2250 Organización física del archivo de
2254 o control de espacio libre.
2258 \begin_inset Tabular
2259 <lyxtabular version="3" rows="2" columns="3">
2261 <column alignment="center" valignment="top" leftline="true" width="0">
2262 <column alignment="center" valignment="top" leftline="true" width="0">
2263 <column alignment="center" valignment="top" leftline="true" rightline="true" width="0">
2264 <row topline="true" bottomline="true">
2265 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2275 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2285 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
2293 <row topline="true" bottomline="true">
2294 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2304 <cell alignment="center" valignment="top" topline="true" leftline="true" usebox="none">
2314 <cell alignment="center" valignment="top" topline="true" leftline="true" rightline="true" usebox="none">
2319 18 bytes libres a partir del byte 42 del .dat
2339 Por requerimiento del algoritmo de compactación, los gaps se graban en
2340 forma ordenada en el (.fsc).
2341 (El orden se corresponde con lo que hay en el
2346 \layout Subsubsection*
2351 Si bien la utilización concreta de los GAPS será explicada posteriormente
2352 en la ALTA y BAJA de registros, debemos remarcar la funcionalidad de MERGING
2353 que posee nuestro sistema FSC.
2356 Ante la eliminación de un registro del archivo de datos, se generara por
2357 consiguiente un gap o espacio libre en alguna posición del archivo.
2358 Ese gap deberá ser registrado en el archivo de gaps (.fsc).
2359 Ahora bien, nuestro sistema de gaps, contemplará como es debido, la posibilidad
2360 de que se haya eliminado un registro que posee un GAP por delante, un GAP
2361 por detrás, o bien un GAP por delante y por detrás del mismo.
2364 Nuestro sistema actuará en consecuencia, realizando un merge de los espacios
2365 libres, y unificándolos en una UNICA entrada en el archivo .fsc, que contendrá
2366 como dato de freespace, la suma correspondiente de los espacios libres
2368 \layout Subsubsection
2370 Archivo de ID's liberados (.did)
2373 El archivo de ID's liberados no presenta ningún aspecto particular en este
2374 tipo de organización.
2375 Remitirse al capítulo correspondiente a los archivos auxiliares para consultar
2376 su estructura y funcionamiento.
2379 Funciones Principales
2394 se encuentran las cabeceras y la implementación de las funciones principales
2395 respectivamente, las cuales dan funcionalidad a esta organización.
2399 A continuación se comentará el funcionamiento algunas de las mas importantes.
2402 Lectura de registros
2405 Como se vió al comienzo, los registros en este tipo de archivo no se encuentran
2406 agrupados en bloques de ninguna índole y estan dispersos a lo largo del
2407 archivo, con la particularidad de que pueden existir gaps o espacio libre,
2408 entre dos registros dados.
2411 Por ende la lectura de registros en este tipo de organización es muy simple
2412 y dada la inexistencia de bloques, el procedimiento será el siguiente:
2415 Se determina el offset en bytes, donde comienza el registro deseado, a través
2416 de su ID, buscando la misma en el archivo índice (
2423 Ya determinada la posición física del registro dentro del archivo de datos
2428 ), nos posicionamos en la misma, y leemos el header del registro (
2437 Contando así con el tamaño del registro, procedemos a leer el mismo (los
2438 datos), dando por finalizada la lectura.
2443 emufs_tipo2_leer_registro()
2449 En el proceso de alta de registros entrarán en juego dos archivos descriptos
2452 sección de archivos auxiliares
2454 , siendo estos el archivo índice (
2458 ), y el archivo de gaps / espacios libres (
2465 Así pues, a la hora de realizar una inserción de un registro en el archivo
2466 de datos, el procedimiento será el siguiente:
2469 Calculamos el espacio que necesitaremos para el registro: sizeof(
2477 ) + sizeof(registro).
2480 Determinamos donde debemos insertar el registro, ya sea un gap donde entre,
2481 o bien al final del archivo.
2484 Insertamos el registro e información de control (
2492 ), en la posición indicada en el paso 2.
2495 En caso de haber utilizado un GAP, actualizamos el espacio libre restante
2496 en el mismo y en caso de que se haya utilizado al totalidad del GAP, se
2497 lo elimina del archivo (
2504 Actualizamos la entrada correspondiente al registro ingresado (determinada
2505 por su RegID), en el archivo índice (
2509 ), indicando su offset donde podrá ser accedido luego.
2514 emufs_tipo2_agregar_registro()
2520 En el proceso de baja de registros entrarán en juego los tres archivos descripto
2523 sección de archivos auxiliares
2525 , siendo estos el archivo índice (
2529 ), el archivo de gaps / espacios libres (
2533 ) y el archivo de ID's liberados (
2540 Dado que en la implementación de este tipo de organización física contamos
2541 con los gaps o espacios libres entre registros, no se eliminará fisicamente
2542 el registro del archivo de datos (
2546 ), pues entonces carecería de sentido el archivo anteriormente mencionado
2552 En cambio, se agrega el gap dejado por la eliminación a dicho archivo,
2553 y se marca fisicamente en el archivo de datos la eliminación mediante un
2554 fill de los bytes correspondientes con un caracter nulo.
2555 (hexa 00 y con el propósito de probar fehacientemente que el sistema funciona).
2558 El proceso de baja o eliminación de un registro constará luego de los siguientes
2562 Se obtiene el offset o posición relativa en donde se encuentra grabado el
2563 registro dentro del archivo de datos.
2566 Se obtiene el tamaño del registro y se realiza un dummyfill del sector del
2567 archivo correspondiente al registro que se está dando de baja.
2568 (Se rellena la zona correspondiente a su header+data).
2571 Se agrega el GAP generado al archivo de gaps o espacios libres, y en caso
2572 de haberse generado un GAP lindante con otro GAP, se realizará un merge
2573 de los mismos y se los registrará bajo una única entrada en el archivo
2574 de espacios libres (.fsc).
2577 Se agrega el ID que fue liberado, al archivo de ID's liberados (
2581 ), al final del mismo (
2588 Se marca en el archivo índice (
2592 ) la eliminación, mediante el valor ¨-1¨ en el registro correspondiente
2593 al registro recién eliminado (se le cambia el valor al n-esimo registro,
2594 donde N = IDReg del reg eliminado).
2599 emufs_tipo2_borrar_registro()
2602 Modificación de registros
2605 Dada la naturaleza del archivo de ID's liberados, y el manejo de espacio
2606 libre del que consta esta organización de archivo, el proceso de modificación
2607 de un registro se limita a los siguientes pasos:
2610 Se realiza la lectura del registro, mediante el respectivo procedimiento
2611 ya desarollado anteriormente.
2614 Una vez que se cuenta con los nuevos datos modificados, se procede a dar
2615 de baja el registro que ha sido modificado, e inmediatamente después se
2616 realiza una inserción con los nuevos datos.
2625 Como fue indicado, dada la naturaleza de PILA del subsistema de administración
2626 de ID liberados, es asegurado que la nueva inserción del registro modificado
2627 se realizará con el mismo RegID.
2632 emufs_tipo2_modificar_registro()
2635 Obtención de estadísticas
2638 Se puede tener acceso a las estadísticas generales del archivo, por ejemplo,
2639 cantidad de bloques, cantidad de registros, espacio libre total, espacio
2640 libre promedio, espacio libre máximo y mínimo, etc.
2643 Esta información es el resultado de ciertos cálculos realizados tanto en
2644 el archivo de datos como en los archivos índice.
2647 Completa una estructura del tipo EMUFS_Estadisticas con las estadísticas
2648 del archivo de datos, espacio libre total, cantidad de registros, cantidad
2649 de bloques, tamaño del archivo en bytes, relaciones entre tamaños y espacios
2655 emufs_tipo2_leer_estadisticas()
2658 Compactación del archivo de datos
2661 Asi como los otros dos tipos de datos, el que nos compete también cuenta
2662 con la posibilidad de realizar la compactación de datos cuando el usuario
2663 lo desee, justificando todos los registros a izquierda, eliminando así
2664 los gaps existentes y decrementando el tamaño del archivo en disco (truncandolo
2668 Para poder comprender como hemos implementado el proceso de recompactación
2669 en nuestro tipo de archivo 2, nos ayudaremos de esquemas a través de los
2670 cuales iremos describiendo el proceso.
2671 Notemos antes, que el proceso de compactación esta directamente ligado
2672 con el archivo de gaps o espacios libres (
2679 Comenzemos con el siguiente cuadro situacional:
2680 \begin_inset Float figure
2687 Archivo con gaps entre registros previo a compactación
2691 \begin_inset Graphics
2692 filename graphics/Compact1.png
2704 Partiendo de esta base, el algoritmo de compactación tomará en su inicio
2705 al primer gap existente dentro del archivo de datos, en este caso llamado
2711 Luego, establecerá que el
2715 a partir de donde se quieren mover datos, sera:
2718 StartGap0 + SizeGap0 = EndGap0 = Source
2721 Lo cual no es nada más y nada menos que lo obvio, la fuente a partir de
2722 donde se mueven los datos, sera el fin del primer gap, donde comienzan
2728 ) del movimiento, se establece inicialmente, el inicio del gap, o sea
2730 StartGap0 = Destination
2735 Luego, el algoritmo entrara en un bucle while (mientras haya bucles por
2736 levantar), el cual trabajara hasta el final de la compactación de la siguiente
2747 Se levanta el proximo gap al levantado en una instancia previa.
2748 En este ejemplo, durante el primer loop del while, se levantará
2753 Luego, se calcula cuantos bytes hay que mover hacia el Destination de la
2777 Lo cual nuevamente es lógico pues querremos mover lo que se encuentra entre
2778 el final del primer gap levantado y el inicio del siguiente).
2781 Se realiza el movimiento de los datos, utilizando las direcciones
2789 , así como la variable
2793 que nos indica cuantos bytes transferir.
2799 La transferencia se hace de a chunks de 25 bytes + un resto segun el valor
2803 Se establece como gap de referencia, al ultimo gap leido (En este caso se
2816 ) y termina el código de repetición del bucle, dando lugar a la carga del
2817 siguiente gap en el inicio del mismo.
2825 Luego del primer bucle, el archivo se vera de la siguiente forma:
2826 \begin_inset Float figure
2833 Archivo con gaps en disco luego del primer bucle de compactación
2837 \begin_inset Graphics
2838 filename graphics/Compact2.png
2849 Notemos que al final de la porción de datos de los bytes movidos (donde
2854 ), hay basura que será pisada por el próximo movimiento.
2857 En el próximo loop, el bucle levantará un nuevo gap, y utilizando el gap
2858 anterior (En esta caso el Gap anterior será
2862 ) como referencia, realizará los mismos cálculos, desde donde transferir
2863 y cuantos bytes mover.
2864 (El destino es solo establecido inicialmente por código, y para el resto
2865 del algoritmo es el lugar donde quedo el puntero destination luego de la
2869 Una vez que se salga del bucle while, se realizará un último movimiento
2870 preprogramado, donde la fuente (
2874 ) será el final del ultimo gap, y la cantidad de bytes a mover será lo que
2875 se encuentre luego del mismo hasta el fin de archivo.
2878 Source = StartLastGap + SizeLastGap = EndLastGap
2881 Mustmove_bytes = Datsize - Source
2884 Damos por terminada así, la explicación del algoritmo de compresión el cual
2885 para el caso del tipo 2, es realmente bastante sencillo.
2890 emufs_tipo2_compactar()
2893 Consideraciones y Políticas de Diseño
2896 Se han tomado ciertas consideraciones para algunos casos particulares que
2897 se pueden presentar durante el uso/ejecución de la aplicación, así como
2898 tambien politicas respecto del diseño e implementación del sistema:
2901 En la organización física tipo 2 para los registros que se graban en disco
2902 hemos decidido utilizar como encabezado de cada uno de ellos, los datos
2903 [ID_REG][REG_SIZE], los cuales fueron detallados previamente.
2904 Si bien se podría haber descartado el grabado del ID del registro en el
2905 archivo de datos y puede parecer redundante, dado que poseemos el archivo
2906 índice con el offset directo, el mismo se lo graba por distintos motivos:
2910 A) En caso de la corrupción del archivo índice (.idx), podremos gracias a
2911 que poseemos en el archivo de datos, el ID de cada registro, recrear dicho
2912 índice, ayudándonos del archivo de espacios libres (
2916 ), para poder saltear los espacios libres y e ir recorriendo secuencialmente
2917 los registros, reconstruyendo así el índice en cuestión.
2918 (esta función de reconstrucción no pudo ser implementada para esta entrega,
2919 pero es una posibilidad real).
2923 B) Luego de un proceso de recompactación, los espacios libres que pudieron
2924 haber existido en el archivo de datos (
2928 ), son eliminados y los registros han cambiado de posición.
2929 Por ello, recorriendo secuencialmente por única vez el archivo de datos,
2930 se procede a la actualización / reconstrucción del índice de direcciones
2938 Si se desea insertar un registro y no se puede hayar un gap o espacio libre
2939 donde quepa, se los inserta al final del archivo.
2942 Ante una operación de baja de un registro, el mismo no es físicamente borrado
2943 del archivo de datos (
2947 ), simplemente los bytes que ocupa son llenados con hexa (00).
2948 Paralelamente, se procede a actualiza el archivo índice, insertando como
2949 valor de OFFSET para el registro eliminado, el valor ¨-1¨, indicando así
2950 la inexistencia del registro para el futuro, y por otro lado se genera
2951 la entrada de espacio libre en el archivo de gaps (
2958 La reutilización de ID's liberados por previas operaciones de baja de registros,
2959 se ve implementada por el archivo de ID liberados (.did), y su comportamiento
2960 es el de una pila por lo que el último ID liberado, sera el próximo a ser
2964 Como fue explicado en la implementación del archivo índice, existe una correspon
2965 dencia 1 a 1 entre los registros allí presentes (en el .idx) y los ID's de
2966 los registros, por lo cual el registro N-ésimo del archivo índice, será
2967 el correspondiente al registro de datos cuyo ID es igual a N.
2970 El proceso de compactación de archivos, realiza los movimientos de información
2971 requeridos para dicho propósito de a chunks de 25 bytes por vez.
2972 Este valor es fijo, pero se lo podría hacer parametrizable mediante la
2973 GUI en próximas entregas.
2977 \begin_inset LatexCommand \label{cha:tipo3}
2981 Archivo con bloques parametrizados y registros de longitud constante
2984 Las distintas organizaciones de archivos buscan aprovechar al máximo el
2985 espacio del archivo.
2988 En este caso veremos que sucede luego de agregar y borrar una gran cantidad
2989 de registros del archivo, lo que provoca como consecuencia directa la fragmenta
2990 ción del archivo, es decir, quedan huecos entre un registro y otro, lo que
2991 produce un desperdicio de espacio.
2994 La implementación de este tipo de archivo puede ser encontrada en
2998 mientras que su interfaz pública está disponible en
3008 Esta organización guarda los registros pertenecientes al archivo en bloques
3009 de tamaño parametrizado, de modo que intentará guardar la mayor cantidad
3010 de registros que quepan en un bloque.
3014 Así como los graba, también tendrá la posibilidad de leer registros y borrarlos
3018 El archivo estara compuesto por una cabecera que da información sobre el
3019 tipo de organización, el tamaño de los bloques y el tamaño de los registros.
3022 Organización Física de un Bloque
3025 Cada bloque será capaz de contener la cantidad de registros enteros que
3027 De esta manera un registro que no entre completamente en el bloque deberá
3028 almacenarce en un bloque diferente.
3031 Los bloques no contienen ninguna información adicional, solo se conoce su
3032 tamaño y se usa para delimitar
3033 \begin_inset Quotes eld
3037 \begin_inset Quotes erd
3040 zonas en el archivo.
3043 Organizacion Física de Registros
3046 Cada registro se almacena en un bloque, y contiene una cabecera que indica
3051 por este motivo al realizar la busqueda de espacio en un bloque se lo hará
3052 preguntando por el tamaño del registro más
3054 sizeof(EMUFS_REG_ID).
3058 Organización Física de Registros Multibloque
3061 Al ser los registros de longitud constante, se ha adoptado que un registro
3062 multibloque nunca podra estar almacenado en algún lugar que no sea el comienzo
3064 De esta manera se puede calcular cuantos bloques ocupará un registro y
3065 se podrá solicitar lugar para almacenarlo con la ayuda de la función
3067 emufs_fsc_buscar_n_lugares(),
3069 que es muy importante para evitar el solapamiento de registros.
3070 Esta consideración acarrea como consecuencia directa un alto costo en términos
3071 del espacio desperdiciado.
3074 Funciones Principales
3085 se encuentran las cabeceras y la implementación de las funciones principales
3086 respectivamente, las cuales dan funcionalidad a esta organización.
3089 A continuación se comentará la descripción de algunas acciones importantes.
3095 La lectura de un registro se realiza con la ayuda del archivo .
3099 el cual contiene la información de la posición del registro dentro del
3101 Una vez leida esta información, se recupera el bloque (en su totalidad)
3102 del archivo y se busca secuencialmente el registro con el
3111 emufs_tipo3_leer_registro()
3117 Graba un registro en un bloque donde haya espacio suficiente, y si no crea
3118 un nuevo bloque y lo agrega al final del archivo.
3121 Luego de grabar un registro, actualiza los archivos de índice .idx y .fsc
3122 para mantener la coherencia.
3127 emufs_tipo3_grabar_registro()
3133 Borra un registro del archivo de datos, para esto levanta el bloque al que
3134 pertenece el archivo y ajusta los demás registros justificandolos hacia
3138 Cabe destacar que para dar de baja un registro no hace falta borrarlo del
3139 archivo de datos, solo es necesario borrar las entradas en los archivos
3140 de índice, pero cuando se realiza el ajuste el algoritmo toma porciones
3141 del bloque del tamaño de un registro mas su encabezado - comenzando desde
3142 el siguiente al que fue borrado - y copia (sobreescribe) sobre el anterior.
3143 De esta manera, la información correspondiente al registro borrado no estará
3144 presente en el archivo de datos.
3145 Esto es una consecuencia del ajuste al borrar un registro, pudiendo no
3146 ser así, si no se realizara el mismo.
3151 emufs_tipo3_borrar_registro()
3157 Se puede tener acceso a las estadísticas generales del archivo, por ejemplo,
3158 cantidad de bloques, cantidad de registros, espacio libre total, espacio
3159 libre promedio, espacio libre máximo y mínimo, etc.
3162 Esta información es el resultado de ciertos cálculos realizados tanto en
3163 el archivo de datos como en los archivos índice.
3166 Completa una estructura del tipo EMUFS_Estadisticas con las estadísticas
3167 del archivo de datos, espacio libre total, cantidad de registros, cantidad
3168 de bloques, tamaño del archivo en bytes, relaciones entre tamaños y espacios
3174 emufs_tipo3_leer_estadisticas()
3177 Compactar el Archivo
3180 Esta función intenta reorganizar el archivo de manera que el espacio libre
3181 sea lo menor posible, recordando siempre que un registro no puede ser almacenad
3182 o en mas de un bloque excepto que el tamaño del registro sea mayor que el
3186 Para realizar esto, se aprovecha la funcionalidad de
3188 emufs_tipo3_grabar_registro()
3190 ya que esta tiene la capacidad de determinar una posición mas eficiente
3191 en el archivo para un registro.
3192 Por esto lo que se hace es levantar uno por uno los registros y volverlos
3193 a grabar, de ese modo todos los
3197 que pudieron haberse formado por la eliminación de registros serán cubiertos
3201 Al estar utilizando recuperación de
3205 borrados, esto me asegura que el registro borrado-guardado conservará el
3209 Al finalizar este proceso se verifica si existen bloques vacios para truncar
3211 Lo mismo se debe hacer con el archivo de espacios libres .
3215 el cual disminuye su tamaño también.
3220 void emufs_tipo3_compactar()
3223 Consideraciones y Políticas de Diseño
3226 Se han tomado ciertas consideraciones para algunos casos particulares que
3227 se pueden presentar durante el uso/ejecución de la aplicación.
3230 Cada registro tiene un encabezado que indica el
3237 Si el tamaño del registro es mayor que el tamaño del bloque el registro
3238 se particionará en la cantidad de bloques que sea necesario, pero siempre
3239 se guardará desde el comienzo de un bloque, esto quiere decir que nunca
3240 se podrá encontrar un comienzo de registro en algún lugar de un bloque
3241 que no sea el comienzo del mismo.
3244 Si el registro se divide en mas de un bloque, se le coloca el id como encabezado
3245 igualmente, pero en el archivo .
3249 solo se guarda el primer bloque.
3254 se actualizan todos los bloques con el espacio libre que realmente tienen.
3260 Las comparaciones, pruebas, etc...