Laboratorio de Sistemas de Bases de Datos II

Laboratorio 0009: Aplicaciones con modelos semiestructurados XML

publicado a la‎(s)‎ 14 ago. 2012 12:16 por Hernan Nina Hanco   [ actualizado el 4 jun. 2013 10:56 ]

I) OBJETIVOS
  • Utilizar un SGBD comercial u OpenSource escribir aplicaciones con modelos Semiestructurados.

II) MARCO CONCEPTUAL

Ver guía o presentaciones de la asignatura

III) PRÁCTICAS DE LABORATORIO

Ejemplos del uso de las Clausula FOR XML en SQL Server.
CREATE DATABASE TEST1
GO
USE TEST1
GO
-- CREATE TABLAS
CREATE TABLE cliente(
id_cliente int not null primary key,
nombres varchar(20),
)

CREATE TABLE venta (
id_venta int not null primary key,
fecha datetime,
id_cliente int not null foreign key references cliente(id_cliente)
)
CREATE TABLE detalle_venta (
id_detalle int not null primary key,
producto varchar(20),
cantidad int,
precio smallmoney,
id_venta int not null foreign key references venta(id_venta)
)
GO
-- Agregar datos
-- Clientes
INSERT INTO cliente(id_cliente, nombres) VALUES (1,'hernan');
INSERT INTO cliente(id_cliente, nombres) VALUES (2,'sonia');
-- Ventas
INSERT INTO venta(id_venta,fecha,id_cliente) VALUES (1,getdate(),1);
INSERT INTO venta(id_venta,fecha,id_cliente) VALUES (2,getdate(),1);
INSERT INTO venta(id_venta,fecha,id_cliente) VALUES (3,getdate(),1);
INSERT INTO venta(id_venta,fecha,id_cliente) VALUES (4,getdate(),2);

--Detalle Venta
INSERT INTO detalle_venta(id_detalle,producto,cantidad,precio,id_venta) VALUES (1,'p1',5,5,1);
INSERT INTO detalle_venta(id_detalle,producto,cantidad,precio,id_venta) VALUES (2,'p2',12,4,1);
INSERT INTO detalle_venta(id_detalle,producto,cantidad,precio,id_venta) VALUES (3,'p3',7,8,1);
INSERT INTO detalle_venta(id_detalle,producto,cantidad,precio,id_venta) VALUES (4,'p1',4,5,2);
INSERT INTO detalle_venta(id_detalle,producto,cantidad,precio,id_venta) VALUES (5,'p2',3,4,2);
INSERT INTO detalle_venta(id_detalle,producto,cantidad,precio,id_venta) VALUES (6,'p1',2,5,3);
INSERT INTO detalle_venta(id_detalle,producto,cantidad,precio,id_venta) VALUES (7,'p2',10,4,3);
INSERT INTO detalle_venta(id_detalle,producto,cantidad,precio,id_venta) VALUES (8,'p1',12,5,4);
INSERT INTO detalle_venta(id_detalle,producto,cantidad,precio,id_venta) VALUES (9,'p2',1,4,4);
INSERT INTO detalle_venta(id_detalle,producto,cantidad,precio,id_venta) VALUES (10,'p3',3,8,4);


/*Modo RAW: Cada fila de la consulta es un elemento XML*/
SELECT id_cliente, nombres 
FROM cliente
FOR XML RAW

GO
-- Resultado:
--<row id_cliente="1" nombres="hernan"/>
--<row id_cliente="2" nombres="sonia"/>

/*Modo RAW: cada columna de la consulta es un elemento XML*/
SELECT id_cliente, nombres 
FROM cliente
FOR XML RAW, ELEMENTS
GO
-- Resultado:
--<row>
-- <id_cliente>1</id_cliente>
-- <nombres>hernan</nombres>
--</row>
--<row><id_cliente>2</id_cliente>
-- <nombres>sonia</nombres>
--</row>

/*Modo RAW: Coloca etiquetas personalizadas en los elementos XML*/
SELECT id_cliente, nombres 
FROM cliente
FOR XML RAW('USUARIO'), root('DEUDORES'), elements
GO
-- Resultado:
--<DEUDORES>
-- <USUARIO id_cliente="1" nombres="hernan"/>
-- <USUARIO id_cliente="2" nombres="sonia"/>
--</DEUDORES>

/*Modo AUTO: Identico a RAW para una sola tabla*/
SELECT id_cliente, nombres 
FROM cliente
FOR XML AUTO
GO
-- Resultado:

--<cliente id_cliente="1" nombres="hernan"/>
--<cliente id_cliente="2" nombres="sonia"/>


/*Modo AUTO: Crea elementos XML anidados cuando hay un JOIN*/
-- Creacion de tablas para JOIN
-- Escribir la consulta para mostrar documentos XML
SELECT v.id_venta, v.fecha, d.id_detalle, d.producto, d.cantidad, d.precio
FROM venta v inner join detalle_venta d ON v.id_venta = d.id_venta
FOR XML AUTO
GO
-- Resultado:
--<v id_venta="1" fecha="2009-05-04T17:06:15.250">
-- <d id_detalle="1" producto="p1" cantidad="5" precio="5.0000"/>
-- <d id_detalle="2" producto="p2" cantidad="12" precio="4.0000"/>
-- <d id_detalle="3" producto="p3" cantidad="7" precio="8.0000"/>
--</v>
--<v id_venta="2" fecha="2009-05-04T17:06:15.250">
-- <d id_detalle="4" producto="p1" cantidad="4" precio="5.0000"/>
-- <d id_detalle="5" producto="p2" cantidad="3" precio="4.0000"/>
--</v>
--<v id_venta="3" fecha="2009-05-04T17:06:15.250">
-- <d id_detalle="6" producto="p1" cantidad="2" precio="5.0000"/>
-- <d id_detalle="7" producto="p2" cantidad="10" precio="4.0000"/>
--</v>
--<v id_venta="4" fecha="2009-05-04T17:06:15.250">
-- <d id_detalle="8" producto="p1" cantidad="12" precio="5.0000"/>
-- <d id_detalle="9" producto="p2" cantidad="1" precio="4.0000"/>
-- <d id_detalle="10" producto="p3" cantidad="3" precio="8.0000"/>
--</v>

/*Modo AUTO: Muestra cada columna como un elemento XML*/
SELECT v.id_venta, v.fecha, d.id_detalle, d.producto, d.cantidad, d.precio
FROM venta v inner join detalle_venta d ON v.id_venta = d.id_venta
FOR XML AUTO, ELEMENTS
GO
-- Resultado:
--<v><id_venta>1</id_venta><fecha>2009-05-04T17:06:15.250</fecha>
-- <d><id_detalle>1</id_detalle><producto>p1</producto><cantidad>5</cantidad><precio>5.0000</precio></d>
-- <d><id_detalle>2</id_detalle><producto>p2</producto><cantidad>12</cantidad><precio>4.0000</precio></d>
-- <d><id_detalle>3</id_detalle><producto>p3</producto><cantidad>7</cantidad><precio>8.0000</precio></d>
--</v>
--<v><id_venta>2</id_venta><fecha>2009-05-04T17:06:15.250</fecha>
-- <d><id_detalle>4</id_detalle><producto>p1</producto><cantidad>4</cantidad><precio>5.0000</precio></d>
-- <d><id_detalle>5</id_detalle><producto>p2</producto><cantidad>3</cantidad><precio>4.0000</precio></d>
--</v>
--<v><id_venta>3</id_venta><fecha>2009-05-04T17:06:15.250</fecha>
-- <d><id_detalle>6</id_detalle><producto>p1</producto><cantidad>2</cantidad><precio>5.0000</precio></d>
-- <d><id_detalle>7</id_detalle><producto>p2</producto><cantidad>10</cantidad><precio>4.0000</precio></d>
--</v>
--<v><id_venta>4</id_venta><fecha>2009-05-04T17:06:15.250</fecha>
-- <d><id_detalle>8</id_detalle><producto>p1</producto><cantidad>12</cantidad><precio>5.0000</precio></d>
-- <d><id_detalle>9</id_detalle><producto>p2</producto><cantidad>1</cantidad><precio>4.0000</precio></d>
-- <d><id_detalle>10</id_detalle><producto>p3</producto><cantidad>3</cantidad><precio>8.0000</precio></d>
--</v>

/*Modo AUTO: Muestra cada columna como un elemento XML*/
SELECT v.id_venta, v.fecha, d.id_detalle, d.producto, d.cantidad, d.precio
FROM venta v inner join detalle_venta d ON v.id_venta = d.id_venta
FOR XML AUTO, ELEMENTS, ROOT('Factura')
GO
--Resultado:
--<Factura>
-- <v><id_venta>1</id_venta><fecha>2009-05-04T17:06:15.250</fecha>
-- <d><id_detalle>1</id_detalle><producto>p1</producto><cantidad>5</cantidad><precio>5.0000</precio></d>
-- <d><id_detalle>2</id_detalle><producto>p2</producto><cantidad>12</cantidad><precio>4.0000</precio></d>
-- <d><id_detalle>3</id_detalle><producto>p3</producto><cantidad>7</cantidad><precio>8.0000</precio></d>
-- </v>
-- <v><id_venta>2</id_venta><fecha>2009-05-04T17:06:15.250</fecha>
-- <d><id_detalle>4</id_detalle><producto>p1</producto><cantidad>4</cantidad><precio>5.0000</precio></d>
-- <d><id_detalle>5</id_detalle><producto>p2</producto><cantidad>3</cantidad><precio>4.0000</precio></d>
-- </v>
-- <v><id_venta>3</id_venta><fecha>2009-05-04T17:06:15.250</fecha>
-- <d><id_detalle>6</id_detalle><producto>p1</producto><cantidad>2</cantidad><precio>5.0000</precio></d>
-- <d><id_detalle>7</id_detalle><producto>p2</producto><cantidad>10</cantidad><precio>4.0000</precio></d>
-- </v>
-- <v><id_venta>4</id_venta><fecha>2009-05-04T17:06:15.250</fecha>
-- <d><id_detalle>8</id_detalle><producto>p1</producto><cantidad>12</cantidad><precio>5.0000</precio></d>
-- <d><id_detalle>9</id_detalle><producto>p2</producto><cantidad>1</cantidad><precio>4.0000</precio></d>
-- <d><id_detalle>10</id_detalle><producto>p3</producto><cantidad>3</cantidad><precio>8.0000</precio></d>
-- </v>
--</Factura>

/*Modo EXPLICIT: Define el XML a traves de una tabla universal*/
SELECT 1 AS TAG, 
  null AS PARENT, 
  v.id_cliente [venta!1!IdVenta], 
       v.fecha [venta!1!Fecha!Element]
FROM venta v
FOR XML EXPLICIT
GO

-- Otro ejemplo
select 1 AS tag,
null AS PARENT,
cliente.id_cliente [cliente!1!Codigo!Element],
cliente.nombres [cliente!1!personal!Element],
null as [venta!2!NroVenta],
null as [venta!2!FechaVenta]
from cliente 
for XML EXPLICIT

select * from venta



USE AdventureWorks
/*Modo EXPLICIT: Define el XML a traves de una tabla universal*/
select 1 as Tag, null as Parent, 
     C.ContactID [Clientes!1!IdContacto], 
     C.ModifiedDate [Clientes!1!FechaModificacion], 
     C.FirstName [Clientes!1!Nombre!Element],
     C.LastName [Clientes!1!Apellidos!Element],
     C.EmailAddress [Clientes!1!Email!Element]
  from Person.Contact C
 for xml explicit

go
--Resultado:
--<venta IdVenta="1">
-- <Fecha>2009-05-04T17:06:15.250</Fecha>
--</venta>
--<venta IdVenta="1">
-- <Fecha>2009-05-04T17:06:15.250</Fecha>
--</venta>
--<venta IdVenta="1">
-- <Fecha>2009-05-04T17:06:15.250</Fecha>
--</venta>
--<venta IdVenta="2">
-- <Fecha>2009-05-04T17:06:15.250</Fecha>
--</venta>

/*Modo PATH: Define el formato XML a traves de XPATH*/
use TEST1
SELECT  v.id_venta "@IDVenta",
v.fecha "Categoria/fecha_ingreso"
FROM venta v
FOR XML PATH
GO
--Resultado:
--<row IDVenta="1">
-- <Categoria>
-- <fecha_ingreso>2009-05-04T17:06:15.250</fecha_ingreso>
-- </Categoria>
--</row>
--<row IDVenta="2">
-- <Categoria>
-- <fecha_ingreso>2009-05-04T17:06:15.250</fecha_ingreso>
-- </Categoria>
--</row>
--<row IDVenta="3">
-- <Categoria>
-- <fecha_ingreso>2009-05-04T17:06:15.250</fecha_ingreso>
-- </Categoria>
--</row>
--<row IDVenta="4">
-- <Categoria>
-- <fecha_ingreso>2009-05-04T17:06:15.250</fecha_ingreso>
-- </Categoria>
--</row>
/*Modo PATH: Define el formato XML dentro de un elemento*/
SELECT  v.id_cliente "@IDVenta",
v.fecha "Categoria/Fecha_ingreso"
FROM venta v
FOR XML PATH('Tienda'), ROOT('FACTURAS')
GO

-- Resultado:
--<FACTURAS>
-- <Tienda IDVenta="1">
-- <Categoria>
-- <Fecha_ingreso>2009-05-04T17:06:15.250</Fecha_ingreso>
-- </Categoria>
-- </Tienda>
-- <Tienda IDVenta="1">
-- <Categoria>
-- <Fecha_ingreso>2009-05-04T17:06:15.250</Fecha_ingreso>
-- </Categoria>
-- </Tienda>
-- <Tienda IDVenta="1">
-- <Categoria>
-- <Fecha_ingreso>2009-05-04T17:06:15.250</Fecha_ingreso>
-- </Categoria>
-- </Tienda>
-- <Tienda IDVenta="2">
-- <Categoria>
-- <Fecha_ingreso>2009-05-04T17:06:15.250</Fecha_ingreso>
-- </Categoria>
-- </Tienda>
--</FACTURAS>

SELECT c.id_cliente "@codigo", 
c.nombres "datospersonales", 
v.id_venta "venta/@numero_venta", 
v.fecha "venta/@fecha",
d.producto "producto", 
d.cantidad "cantidad", 
d.precio "precio"
FROM (cliente c inner join venta v ON (c.id_cliente = v.id_cliente))
inner join detalle_venta d ON (v.id_venta = d.id_venta)
order by c.id_cliente, v.id_venta

FOR XML PATH
GO

SELECT c.id_cliente "@codigo",
c.nombres "datos_personales", 
(SELECT v.id_venta "@nro_venta", 
v.fecha "@fecha_venta"
FROM venta v
WHERE v.id_cliente = c.id_cliente
FOR XML Path('venta'), TYPE
) "ventas"
FROM cliente c
FOR XML path('cliente')
GO

Esquemas de documentos XML en SQL Server

create database banco
go

-- 
use banco
go


-- crear un esquema de sql
-- drop xml schema collection esquema_banco2 as 
create xml schema collection esquema_banco3 as
'<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="banco" type="TipoBanco"/>
<xsd:element name="cuenta">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="nombre_sucursal" type="xsd:string"/>
<xsd:element name="saldo" type="xsd:decimal"/>
</xsd:sequence>
<xsd:attribute name="numero_cuenta" type="xsd:string"/>
<xsd:attribute name="titulares" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="cliente">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="nombre_cliente" type="xsd:string"/>
<xsd:element name="ciudad_cliente" type="xsd:string"/>
<xsd:element name="calle_cliente" type="xsd:string"/>
</xsd:sequence>
<xsd:attribute name="id_cliente" type="xsd:integer"/>
<xsd:attribute name="cuentas" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="TipoBanco">
<xsd:sequence>
<xsd:element ref="cuenta"   minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="cliente"   minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>'

select * from sys.xml_schema_collections
-- crear una tabla en base al esquema
-- drop table bancos1

create table bancos3
(
id_banco int identity(1,1),
data_banco xml (esquema_banco3) null -- se almacena documentos xml con restricción del shema
)
go

insert into bancos3(data_banco) values (
'<banco>
<cuenta numero_cuenta="C-401" titulares="101 102">
<nombre_sucursal>Cusco</nombre_sucursal>
<saldo>459.80</saldo>
</cuenta>
<cuenta numero_cuenta="C-402" titulares="101 102">
<nombre_sucursal>Puno</nombre_sucursal>
<saldo>560.89</saldo>
</cuenta>
<cuenta numero_cuenta="C-403" titulares="101 102">
<nombre_sucursal>Cusco</nombre_sucursal>
<saldo>25900.89</saldo>
</cuenta>
<cliente id_cliente="101" cuentas="C-401 C-301">
<nombre_cliente>juan</nombre_cliente>
<ciudad_cliente>Cusco</ciudad_cliente>
<calle_cliente>alamos </calle_cliente>
</cliente>
<cliente id_cliente="102" cuentas="C-401 C-301">
<nombre_cliente>ana</nombre_cliente>
<ciudad_cliente>Cusco</ciudad_cliente>
<calle_cliente>Jose Olaya</calle_cliente>
</cliente>
<cliente id_cliente="103" cuentas="C-401 C-301">
<nombre_cliente>pedro</nombre_cliente>
<ciudad_cliente>Puno</ciudad_cliente>
<calle_cliente>San Jose</calle_cliente>
</cliente>
</banco>'
)
go
select * from bancos3

IV) Tarea
  1. Personalizar entre elementos y atributos el resultado de una consulta con la clausula FOR XML y modo PATH.
  2. Crear un esquema para el siguiente documento XML.
<part>
 <producto>
  <nombre> bicicleta </nombre>
   <infocomponente>
    <producto>
     <nombre> rueda </nombre>
     <infocomponente>
      <producto>
       <nombre> borde </nombre>
      </producto>
      <cantidad> 1 </cantidad>
     </infocomponente>
     <infocomponente>
      <producto>
       <nombre> rayos </nombre>
      </producto>
      <cantidad> 40 </cantidad>
     </infocomponente>
    <infocomponente>
     <producto>
      <nombre> neumático </nombre>
     </producto>
     <cantidad> 1 </cantidad>
    </infocomponente>
   </producto>
   <cantidad> 2 </cantidad>
  </infocomponente>
  <infocomponente>
   <producto>
    <nombre> freno </nombre>
   </producto>
   <cantidad> 2 </cantidad>
  </infocomponente>
  <infocomponente>
   <producto>
    <nombre> equipo </nombre>
   </producto>
   <cantidad> 3 </cantidad>
  </infocomponente>
  <infocomponente>
   <producto>
    <nombre> marco </nombre>
   </producto>
   <cantidad> 1 </cantidad>
  </infocomponente>
 </producto>

</part>



Laboratorio 0008: Aplicaciones con transacciones

publicado a la‎(s)‎ 14 ago. 2012 12:14 por Hernan Nina Hanco   [ actualizado el 4 jun. 2013 10:56 ]

I) OBJETIVOS
  • Utilizando un SGBD comercial u OpenSource escribir aplicaciones de Transacciones

II) MARCO CONCEPTUAL

Ver Guía de la Asignatura

III) PRÁCTICAS DE LABORATORIO

Trabajo con transacciones en SQL Server.

/*Trabajo con transacciones*/

-- Iniciar una Transaccion
BEGIN TRANSACTION

-- Iniciamos una tracsaccion de actualizacion
UPDATE HumanResources.Employee
SET Title = 'TestTitle'
WHERE EmployeeID = 150

-- Para verificar la modificacion realizamos una consulta

SELECT Title
FROM HumanResources.Employee
WHERE EmployeeID = 150

-- Debera mostrar la modificacion en el registro

----------------
-- Inicie una nueva consulta y luego escriba
---------------
SELECT Title
FROM HumanResources.Employee
WHERE EmployeeID = 150

----------------
-- Vuelva a la consulta anterior y revierta la transaccion
---------------

ROLLBACK TRANSACTION

-- Se revierte y la consulta realizada en la nueva ventana muestra que el dato del registro se ha modificado

Aplicaciones de la propiedad de aislamiento de transacciones en SQL Server.

Ejecutar en una conexión lo siguiente:
USE AdventureWorks
GO

-- Iniciar la transaccion ...
BEGIN TRAN

   -- Modificaciones en los datos ...
   UPDATE Production.Product
   SET Name = 'Adjustable Race 2009-Cusco'
   WHERE ProductID = 1

   -- Ver los datos cambiados ...
   SELECT * FROM Production.Product
   WHERE name LIKE 'A%'

-- Cancelar la transaccion ...
-- ROLLBACK TRAN

En otra conexión ejecuta lo siguiente, no debe culminar la transacción de la conexión anterior.
USE Adventureworks
GO
-------------------------------------------------------------------------------------------------------------
-- En la otra conexion ejecutamos este codigo mientras al transaccion anterior este abierta
-------------------------------------------------------------------------------------------------------------

-- SCRIPT #A.1
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT * FROM Production.Product
WHERE name LIKE 'A%'

SET TRANSACTION ISOLATION LEVEL READ COMMITTED


-- SCRIPT #A.2
SELECT * FROM Production.Product WITH ( NOLOCK )
WHERE name LIKE 'A%'


-- SCRIPT #B
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
SELECT * FROM Production.Product
WHERE name LIKE 'A%'

Debe disponer de la base de datos ejemplo o demo de SQL Server Adeventureworks

III) TAREA
  1. Verifique que podemos crear un tercer aislamiento y comprobar como quedan los datos después de finalizar la transacción de la primera conexión. Ejecute instrucciones de Inserción, Modificación y Eliminado en las transacciones.

Laboratorio 0007: Aplicaciones de Índices

publicado a la‎(s)‎ 14 ago. 2012 12:07 por Hernan Nina Hanco   [ actualizado el 4 jun. 2013 10:54 ]

I) OBJETIVOS
  • Utilizar un Sistema de Gestión de Bases de Datos Comercial u OpenSource y realizar aplicaciones sobre Índices

II) MARCO CONCEPTUAL


Guía de la Asignatura.

III) PRÁCTICAS DE LABORATORIO

/*Indices en SQL Server */
-- Los indices al igual que los indices de los libros ofrecen una forma rapida de 
-- acceder a los datos que se esta buscando aun en tablas grandes

CREATE DATABASE BD_PRUEBA2
GO

use bd_prueba2
go

CREATE TABLE AlumnoInfo (
id_alumno int identity(1,1),
nombres varchar(30),
ap varchar(20),
am varchar(20),
ciudad varchar(30),
fecha_nac datetime,
obs varchar(1000)
)
GO
--DROP TABLE AlumnoInfo
/* Opciones de Indices */
/* Opcion online*/
-- Si esta en ON indica que las tablas e indices asociados estan 
-- disponibles para consultas y modificacion de datos durante la 
-- operacion de indexado. La opcion predeterminada es OFF

CREATE INDEX idx_nombres
ON AlumnoInfo (nombres)
WITH (ONLINE = ON)

-- Modificar la opcion de un indice
ALTER INDEX idx_nombres
ON AlumnoInfo
REBUILD
WITH (ONLINE=OFF)

-- Eliminar un indice de la tabla
DROP INDEX idx_nombres ON dbo.AlumnoInfo

/* Crear un indice con la opcion ALLOW_ROW_LOCKS */
-- Si la opcion esta activada es ON(Opcion Predeterminada) 
-- se permite los Bloqueos de fila
CREATE INDEX idx_nombres2
ON AlumnoInfo (nombres)
WITH (ALLOW_ROW_LOCKS = OFF)
/*Crear un indice con la opcion ALLOW_PAGE_LOCKS*/
-- Si la opcion esta activada es ON(Opcion Predeterminada) se permite los 
-- Bloqueos de pagina
CREATE INDEX idx_nombre3
ON AlumnoInfo (nombres)
WITH (ALLOW_PAGE_LOCKS = OFF)

/*Crear un indice con la opcion ONLINE, ALLOW_ROW_LOCKS, ALLOW_PAGE_LOCKS*/
CREATE INDEX idx_nombres4
ON AlumnoInfo (nombres)
WITH (ONLINE = ON, ALLOW_ROW_LOCKS = OFF, ALLOW_PAGE_LOCKS = OFF)

/*Crear un Indice Agrupado*/
-- Los Indices agrupados ordenan las filas segun la 
-- clave de agrupamiento. En general
--, toda tabla deberia tener un solo indice agrupago;
-- generalmento sobre la clave primaria

CREATE CLUSTERED INDEX ci_fecha_nac
ON dbo.AlumnoInfo(fecha_nac);
-- Consultamos para verificar si pueden ser extraidos de la tabla
SELECT * FROM dbo.ALumnoInfo;
/*Deshabilitar el indice ejecutando la siguiente Instruccion*/
ALTER INDEX ci_fecha_nac ON dbo.AlumnoInfo DISABLE;
-- Consultamos para verificar que no se pueden extraer datos de la tabla
SELECT * FROM dbo.ALumnoInfo;
/*Habilitar un indice agrupado*/
ALTER INDEX ci_fecha_nac ON dbo.AlumnoInfo REBUILD;
GO
-- Consultamos para verificar que se pueden extraer datos de la tabla
SELECT * FROM dbo.ALumnoInfo;

/* Crear un indice no agrupado */
-- Los Indices no agrupados no ordenan las filas de la tablas. 
-- Puede crear Hasta 249 indices no agrupados 
-- por tabla para satisfacer la mayor parte de sus consultas

CREATE NONCLUSTERED INDEX idx_ap ON
dbo.AlumnoInfo(ap);
/*Indices cubiertos COVERED*/
-- Mediante los indices cuviertos, 
-- podemos ejecutar consultas sin necesidad de acceder a la tabla
CREATE NONCLUSTERED INDEX idx_ap_am_nombres
ON AlumnoInfo(ap,am,nombres)
/*Indices Incluidos */
-- los indices de columnas incluidas permiten añadir 
-- valores al nivel de hoja del indice de forma que pueda 
-- crear implementaciones de indices complejas
-- Solución para el límite de los 900 bytes en la creación de un Indice
CREATE NONCLUSTERED INDEX idx_id_obs ON
dbo.AlumnoInfo(id_alumno)
INCLUDE(obs); -- Este campo excede el limite de 900 bytes puesto que lo definimos con varchar(1000)

/* Buscar indices fragmentados*/
-- La siguiente consulta identifica el porcentaje de fragmentacion de los Indices de la BD
USE AdventureWorks
GO

SELECT
  OBJECT_NAME(i.object_id) AS TableName, 
  i.name AS IndexName,
  ips.avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED') ips
JOIN sys.indexes i ON 
  i.object_id = ips.object_id 
  AND i.index_id = ips.index_id
WHERE ips.avg_fragmentation_in_percent > 90
-- Resultado:
-- TableName IndexName Promedio del porcentaje de Fragmentación
---------------------------------------------------------------------------------
--vProductAndDescription IX_vProductAndDescription 98.5714285714286
--SalesOrderDetail AK_SalesOrderDetail_rowguid 100
--Individual XMLVALUE_Individual_Demographics 100
--Store PXML_Store_Demographics 98.4375


/* Defragmentación de un index*/

ALTER INDEX AK_SalesOrderDetail_rowguid
ON Sales.SalesOrderDetail
REORGANIZE

IV) Tareas
  1. Verificar y comparar los costos de procesamiento para una búsqueda con y sin Índices primario.
  2. Crear una tabla con una clave primaria, la tabla debe tener mas de dos campos. crea un Índice primario para la tabla donde su clave de búsqueda no sea la clave primaria.

Laboratorio 0006: Indices de Árboles B+

publicado a la‎(s)‎ 17 jul. 2012 0:27 por Hernan Nina Hanco   [ actualizado el 6 ago. 2013 13:42 ]

I) OBJETIVOS
  • Implementar archivos de Índices de Árboles B+.

II) MARCO CONCEPTUAL

Ver la sección
3.3.1. Algoritmos en Árboles B+ de la Guía de Sistemas de Bases de Datos II


III) PRÁCTICAS DE LABORATORIO
1) Implementación básica de un árbol B+

Clase que representa un Nodo de Árbol B+
package org.taqque.indice.arbolbmas;

/**
 *
 * @author hernan
 */
public class Nodo {

    private int n;
    private int m = -1; //último puntero
    private int nK = -1; // última clave
    private Object[] punteros;
    private int[] claves;

    public Nodo(int n) {
        this.n = n;
        punteros = new Object[n];
        for (int i = 0; i < n; i++) {
            punteros[i] = null;
        }
        claves = new int[n - 1];
        for (int j = 0; j < n - 1; j++) {
            claves[j] = -1;
        }
    }
    /*
     * ki minimo valor de la clave de busqueda, si lo hay, mayor que Valor clave buscado
     */

    public int posClave(int valor) {
        int pos = -1;
        for (int i = 0; i <= nK; i++) {
            if (claves[i] != -1) {
                if (claves[i] < valor) {
                    pos = i;
                } else {
                    break;
                }
            }
        }
        return pos;
    }

    public boolean existeClave(int valor) {
        for (int i = 0; i < nK; i++) {
            if (claves[i] == valor) {
                return true;
            }
        }
        return false;
    }

    public void insertarClave(Object p, int k, int pos) {
        desplazarEntradas(pos);
        punteros[pos] = p;
        m++;
        claves[pos] = k;
        nK++;
    }

    private void desplazarEntradas(int pos) {
        for (int i = nK; i >= pos; i--) {
            int k = claves[i];
            claves[i + 1] = k;
        }
        for (int i = m; i >= pos; i--) {
            Object p = punteros[i];
            punteros[i + 1] = p;
        }
    }

    public void copiarEntradasPunteros(Nodo t, int ini, int fin) {
        int j=0;
        for (int i = ini; i <= fin; i++) {
            t.getPunteros()[j++] = punteros[i];
            t.setM(t.getM() + 1);
        }
    }

    public void copiarEntradasClaves(Nodo t, int ini, int fin) {
        int j=0;
        for (int i = ini; i <= fin; i++) {
            t.getClaves()[j++] = claves[i];
            t.setnK(t.getnK() + 1);
        }
    }

    public void borrarEntradas() {
        for (int i = 0; i <= m; i++) {
            punteros[i] = null;
        }
        for (int i = 0; i <= nK; i++) {
            claves[i] = -1;
        }


    }

    public int[] getClaves() {
        return claves;
    }

    public void setClaves(int[] claves) {
        this.claves = claves;
    }

    public Object[] getPunteros() {
        return punteros;
    }

    public void setPunteros(Object[] punteros) {
        this.punteros = punteros;
    }

    public int getM() {
        return m;
    }

    public void setM(int m) {
        this.m = m;
    }

    public int getN() {
        return n;
    }

    public void setN(int n) {
        this.n = n;
    }

    public int getnK() {
        return nK;
    }

    public void setnK(int nK) {
        this.nK = nK;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (int i = 0; i < n; i++) {
            sb.append("(");
            sb.append(punteros[i] != null ? punteros[i] : "null");
            if (n > i + 1) {
                sb.append("|");
                sb.append(claves[i] != -1 ? claves[i] : "null");
                sb.append(")");
            }
        }
        sb.append(")");
        sb.append("]");
        return sb.toString();
    }
}

Clase que representa un árbol B+
package org.taqque.indice.arbolbmas;

/**
 *
 * @author hernan
 */
public class ArbolBMas {

    private int n;
    private Nodo raiz;

    public ArbolBMas(int n) {
        this.n = n;
        raiz = new Nodo(n);
    }

    public Nodo buscar(int valor) {
        Nodo c = buscarNodo(valor);
        // si hay un valor de de la clave ki en C tal que ki=V
        // entonces el puntero Pi conduce al registro o cajon deseado.
        if (c.existeClave(valor)) {
            return c;
        } else // no existe ningun registro con el valor de la clave k
        {
            return null;
        }
    }

    public Nodo buscarNodo(int valor) {
        Nodo c = raiz;
        while (!esHoja(c)) {
            // ki minimo valor de la clave de busqueda, si lo hay, mayor que Valor buscado
            int i = c.posClave(valor);

            if (i == -1) // no hay tal valor ki 
            {
                // buscar en el nodo señalado por el último puntero
                // m - último puntero
                int m = c.getM();
                // hacer que ahora C sea el puntero que se apunta desde pm
                c = (Nodo) c.getPunteros()[m];
            } else // existe el ki
            {
                c = (Nodo) c.getPunteros()[i];
            }
        }
        return c;
    }

    public boolean esHoja(Nodo nodo) {
        Object[] punteros = nodo.getPunteros();
        if (punteros[0] instanceof Nodo) {
            return false;
        }
        return true;
    }

    public void insertar(int k, Object p) {
        // Hallar el nodo hoja L que debe contener el valor de la clave k
        Nodo l = buscarNodo(k);
        // Si L tiene menos de n-1 valores de clave
        if (l.getnK() + 1 < n - 1) {
            insertarEnHoja(l, k, p);
        } else // L ya tiene n-1 valores de la clave, debemos dividirlo
        {
            // Crear un nodo L'
            Nodo lPrima = new Nodo(n);
            // Copiar L.P1 .... L.Kn-1 a un bloque de memoria T que pueda almacenar n pares (puntero y valor clave)
            Nodo t = new Nodo(n + 1);
            l.copiarEntradasPunteros(t, 0, l.getM());
            l.copiarEntradasClaves(t, 0, l.getnK());
            insertarEnHoja(t, k, p);
            lPrima.getPunteros()[n-1] = l.getPunteros()[n-1];
            l.getPunteros()[n-1] = lPrima;
            l.borrarEntradas();
            int ini = 0;
            int fin = Math.round((t.getN()) / 2);
            t.copiarEntradasPunteros(l, ini, fin-1);
            t.copiarEntradasClaves(l, ini, fin-1);
            
            t.copiarEntradasPunteros(lPrima, fin, t.getM());
            t.copiarEntradasClaves(lPrima, fin, t.getnK());
                    
            int kPrima = lPrima.getClaves()[0];
            insertarEnPadre(l, kPrima, lPrima);
        }
    }

    public void insertarEnHoja(Nodo l, int k, Object p) {
        int k0 = l.getClaves()[0];
        // Si k < L.K1 la primera clave de L, insertar p,k antes de L.P1
        if (k < k0 || k0 == -1) {
            l.insertarClave(p, k, 0);
        } else {
            int pos = l.posClave(k);
            System.out.println("Pos: "+pos);
            l.insertarClave(p, k, pos+1);
        }

    }
    public void insertarEnPadre(Nodo N, int k, Nodo nPrima) {
        if (N == raiz) // si n es la raíz
        {
            Nodo r = new Nodo(n);
            r.getPunteros()[0] = N;
            r.getClaves()[0] = k;
            r.getPunteros()[1] = nPrima;
            r.setM(2);
            raiz = r;
            return;
        }
    }
    

    public static void main(String[] args) {
        ArbolBMas arbol = new ArbolBMas(4);
        arbol.insertar(2, null);
        arbol.insertar(3, null);
        arbol.insertar(5, null);
        arbol.insertar(7, null);
        System.out.println(arbol.raiz);
    }
}

Tarea
  1. Implementar un archivo de Indice con estructura de árbol B+ para una determinada relación.

Laboratorio 0005: Gestión de Almacenamiento y de Relación

publicado a la‎(s)‎ 10 jul. 2012 19:11 por Hernan Nina Hanco   [ actualizado el 6 ago. 2013 13:47 ]

I) OBJETIVOS
  • Implementar un gestor de almacenamiento y de relación.

II) MARCO CONCEPTUAL

El gestor de almacenamiento esta encargado del servicio de transferencias de unidades de datos que son los bloques o páginas a quienes lo solicitan. Entonces se implementa una clase que se encargue de la entrada y salida de las páginas tomando en cuenta que algunos bloques o páginas se encuentran en la memoria intermedia, evitando así el acceso a disco.
El gestor de relación utiliza el gestor de almacenamiento para cuando exista la necesidad de insertar una nueva tupla en la relación, el gestor de almacenamiento se encargue de buscar la página y la ubicación dentro de la página de la nueva tupla a insertar.

III) PRÁCTICAS DE LABORATORIO

1) Modificación del gestor de memoria intermedia
Clase GestorMemoriaIntermedia
/*
 * Creado el 28 de mayo, 2012 por Hernán Nina Hanco
 *
 * Este trabajo es parte del proyecto Taqque, que corresponde a la 
 * implementación de un Sistema de Gestión de Base de Datos. Cualquier
 * cambio es necesario declararlo en este apartado.
 * 
 * Universidad Nacional de San Antonio Abad del Cusco
 * Carrera Profesional de Ingeniería Informática y de Sistemas
 * Asignatura: Sistemas de Bases de Datos II
 */
package org.taqque.memoriaintermedia;

import java.util.LinkedList;
import java.util.Queue;
import java.util.logging.Logger;
import org.taqque.almacenamiento.IdentificadorPagina;
import org.taqque.almacenamiento.Pagina;
import org.taqque.almacenamiento.Relacion;
/**
 * Representa una abstracción de un 
 * Gestor de la Memoria Intermedia
 * 
 * @author hernan
 */
public class GestorMemoriaIntermedia {

    static final Logger logger = 
            Logger.getLogger("Gestion de Buffer");
    /** Representa a los bloques de la 
     * memoria intermedia o buffer. */
    private ContenedorPagina[] buffer;
    /** Numero de paginas en total en el buffer. */
    private int numeroPaginas;
    /** Posición en el buffer de la ultima pagina colocada. */
    private int posicionUltimaPagina = -1;
    /** cola para el control de sustitución basada en LRU. */
    private Queue colaLRU;

    /**
     * Crea un nuevo Gestor de memoria intermedia.
     * 
     * @param numeroPaginas cantidad de paginas en total en el buffer.
     */
    public GestorMemoriaIntermedia(int numeroPaginas) {
        this.numeroPaginas = numeroPaginas;
        // Crear el buffer con paginas vacias
        buffer = new ContenedorPagina[numeroPaginas];
        // Crear una cola FIFO
        colaLRU = new LinkedList<Integer>();
    }

    /**
     * Devuelve una pagina conociendo el numero de la página.
     * 
     * @param numeroPagina el id de la pagina que queremos devolver
     * @return la página del id de pagina proporcionado.
     */
    public Pagina recuperarPaginaDelBuffer(IdentificadorPagina idPagina) {
        // Verificar si la pagina esta en el buffer
        int posicion = posicionDePaginaEnBuffer(idPagina.getNumero());
        if (posicion >= 0) // la pagina esta en el buffer
        {
            // Marcar Pagina o bloque como recientemente referenciado
            colaLRU.remove(buffer[posicion].pagina.getIdentificadorPagina().getNumero());
            colaLRU.add(buffer[posicion].pagina.getIdentificadorPagina().getNumero());
            // devolver la pagina del buffer al solicitante
            return buffer[posicion].pagina;
        }
        return null;
    }

    /**
     * Poner una pagina en el buffer de la memoria intermedia.
     * 
     * @param pagina la pagina a ser insertado en el buffer.
     * @return la pagina que sera descartada del buffer si es necesario.
     */
    public Pagina ponerPaginaEnBuffer(Pagina pagina, boolean modificadoEnBuffer) {
        // Si la pagina esta en el buffer
        if (estaPaginaEnBuffer(pagina.getIdentificadorPagina())) {
            // no descartar ninguna pagina o bloque 
            int index = this.posicionDePaginaEnBuffer(
                    pagina.getIdentificadorPagina().getNumero());
            buffer[index].pagina = pagina;
            buffer[index].modificadorEnBuffer = modificadoEnBuffer;
            colaLRU.remove(pagina.getIdentificadorPagina().getNumero());
            colaLRU.add(pagina.getIdentificadorPagina().getNumero());
            
            return null;
        } // Si la pagina no esta en el buffer, pero con espacio en el buffer
        else if (!bufferLLeno()) {
            // Asignar la nueva pagina al bloque o pagina libre del buffer 
            posicionUltimaPagina++;
            buffer[posicionUltimaPagina] = new ContenedorPagina(pagina);
            buffer[posicionUltimaPagina].modificadorEnBuffer = modificadoEnBuffer;
            // Actualizar la LRU
            colaLRU.add(pagina.getIdentificadorPagina().getNumero());
            return null;
        } // Si la pagina no esta en el buffer, pero sin espacio en el buffer
        else {
            // recuperar la pagina a descartar
            // Identificar el ID Pagina a descartar de la cola LRU
            int numeroPaginaDescartada = (Integer) 
                    colaLRU.remove();
            // conociendo el ID de pagina ubicar la posición de 
            // la pagina en el buffer.
            int posicion = posicionDePaginaEnBuffer
                    (numeroPaginaDescartada);
            // Extraer la pagina a descartar del buffer
            Pagina paginaDescartada = buffer[posicion].pagina;
            buffer[posicion].modificadorEnBuffer = modificadoEnBuffer;
            // Actualizar la nueva pagina en la posición de la 
            // pagina descartada
            buffer[posicion].pagina = pagina;
            // hacer que el ID de la Nueva pagina sea el 
            // mas recientemente referenciado.
            colaLRU.add(pagina.getIdentificadorPagina().getNumero());
            
            return paginaDescartada;
        }

    }

    private int posicionDePaginaEnBuffer(int numeroPagina) {
        int posicion = -1;
        for (int i = 0; i < buffer.length; i++) {
            if ((buffer[i] != null)   && 
             (numeroPagina == buffer[i].pagina.getIdentificadorPagina().getNumero())) {
                posicion = i;           break;
            }
        } return posicion;
    }

    public boolean estaPaginaEnBuffer(IdentificadorPagina idPagina) {
        return (posicionDePaginaEnBuffer
                (idPagina.getNumero()) != -1);
    }

    private boolean bufferLLeno() {
        return numeroPaginas - 1 == posicionUltimaPagina;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Buffer: ").append("Paginas: {\n");
        int tid = 0;
        for (ContenedorPagina cpg : buffer) {
            if (cpg!=null)
                sb.append("\t").append(tid++).append(": ").append(cpg.pagina.toString()).append("\n");
        }
        sb.append("}").append("\n");
        sb.append("LRU: {").append(colaLRU).append("}");
        return sb.toString();
    }

    public static void main(String[] args) {
        // Crear un gestor de memoria
        GestorMemoriaIntermedia gestorBuffer = 
                new GestorMemoriaIntermedia(2);
        // Paginas del Disco
        System.out.println("Creando Paginas...");
        Pagina[] paginas = new Pagina[2];
        for (int i = 0; i < paginas.length; i++) {
            Pagina pagina = new Pagina(new Relacion(),new IdentificadorPagina("relacion",i));
            paginas[i] = pagina;
        }
        System.out.println("Contenido del Gestor: ");
        System.out.println(gestorBuffer);
       
        gestorBuffer.ponerPaginaEnBuffer(new Pagina(new Relacion(),
                new IdentificadorPagina("relacion",9)),false);

        gestorBuffer.ponerPaginaEnBuffer(new Pagina(new Relacion(),
                new IdentificadorPagina("relacion",5)),false);
        
       
        System.out.println("Contenido del Gestor despues de poner bloques: ");
        System.out.println(gestorBuffer);
        
        gestorBuffer.ponerPaginaEnBuffer(new Pagina(new Relacion(),
                new IdentificadorPagina("relacion",3)),false);
        
        System.out.println("Contenido del Gestor despues de poner bloques 3: ");
        System.out.println(gestorBuffer);

        gestorBuffer.ponerPaginaEnBuffer(new Pagina(new Relacion(),
                new IdentificadorPagina("relacion",12)),false);
        
        System.out.println("Contenido del Gestor despues de poner bloques 12: ");
        System.out.println(gestorBuffer); 
        
        System.out.println("despues de recuperar 3: ");
        Pagina pagina2 = gestorBuffer.recuperarPaginaDelBuffer(new IdentificadorPagina("relacion",3));
        System.out.println(gestorBuffer);
        System.out.println(pagina2);

        System.out.println("despues de recuperar 12: ");
        Pagina pagina12 = gestorBuffer.recuperarPaginaDelBuffer(new IdentificadorPagina("relacion",12));
        System.out.println(gestorBuffer);
        System.out.println(pagina12);
        
        gestorBuffer.ponerPaginaEnBuffer(new Pagina(new Relacion(),
                new IdentificadorPagina("relacion",15)),false);
        
        System.out.println("Contenido del Gestor despues de poner bloques 15: ");
        System.out.println(gestorBuffer); 
    }
}

Clase ContenedorPagina

/*
 * Creado el 28 de mayo, 2012 por Hernán Nina Hanco
 *
 * Este trabajo es parte del proyecto Taqque, que corresponde a la 
 * implementación de un Sistema de Gestión de Base de Datos. Cualquier
 * cambio es necesario declararlo en este apartado.
 * 
 * Universidad Nacional de San Antonio Abad del Cusco
 * Carrera Profesional de Ingeniería Informática y de Sistemas
 * Asignatura: Sistemas de Bases de Datos II
 */

package org.taqque.memoriaintermedia;

import org.taqque.almacenamiento.Pagina;

/**
 * ContenedorPagina: Contenedor de una página en el buffer de la memoria intermedia
 * con seguimiento de versión de página o modificación de la página en buffer. 
 * 
 * @author hernan
 */

public class ContenedorPagina {

    public Pagina pagina;
    public boolean modificadorEnBuffer;

    public ContenedorPagina(Pagina pagina) {
        this.pagina = pagina;
        modificadorEnBuffer = false;
    } // ContenedorPagina
} // ContenedorPagina

2) Implementar el gestor de almacenamiento
Clase GestorAlmacenamiento
package org.taqque.almacenamiento;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import org.taqque.memoriaintermedia.GestorMemoriaIntermedia;

/**
 * GestorAlmacenamiento: Provee un manejo a bajo nivel de la 
 * entrada y salida de paginas en un nivel inferior como servicio para el resto
 * del sistema.
 *
 * @author hernan
 */
public class GestorAlmacenamiento {

    /** Catalogo del gestor de almacenamiento. */
    private Catalogo catalogo;
    /** El gestor de memoria intermedio del gestor de almacenamiento. */
    private GestorMemoriaIntermedia buffer;

    /**
     * Inicializa un nuevo gestor de almacenamiento, dado un catalogo y 
     * un buffer de memoria inteermedia.
     * 
     */
    public GestorAlmacenamiento(Catalogo catalogo, GestorMemoriaIntermedia buffer) {
        this.catalogo = catalogo;
        this.buffer = buffer;
    } // GestorAlmacenamiento()

    /**
     * Registrar una pagina considerando la existencia de memoria intermedia.
     *
     */
    public void registrarPagina(Pagina pagina) {
        escribirPagina(pagina);
    }

    /**
     * Escribir una pagina en disco.
     * 
     */
    public synchronized void escribirPagina(Pagina pagina) {
        try {
            // Colocar la página en la memoria intermedia y verificar si una 
            // pagina será desechada -- si es así, extraer la página desechada            
            Pagina paginaDesechada = buffer.ponerPaginaEnBuffer(pagina, false);
            
            if (paginaDesechada != null) {
                String nombreArchivo = paginaDesechada.getIdentificadorPagina().getNombreArchivo();
                RandomAccessFile archivoDB = new RandomAccessFile(nombreArchivo,
                        "rw");
                GestorIOPagina.escribirPagina(archivoDB, paginaDesechada);
                archivoDB.close();
            }
        } catch (IOException e) {
            System.out.println("Error escribiendo página a disco. " + e);
        }
    }

    /**
     * Leer una página de la bd conociendo el identificador de la página.
     * 
     * @param idPagina el identificador de la página a leer.
     * @return la pagina leida.
     */
    public synchronized Pagina leerPagina(Relacion relacion,
            IdentificadorPagina idPagina) {
        try {
            // Si la página esta en el buffer, entonces leer del mismo
            if (buffer.estaPaginaEnBuffer(idPagina)) {
                return buffer.recuperarPaginaDelBuffer(idPagina);
            } // caso contrario leer del archivo y colocarlo en la memoria intermedia.
            else {
                String nombreArchivo = idPagina.getNombreArchivo();
                RandomAccessFile archivoBD = 
                        new RandomAccessFile(nombreArchivo, "rw");
                Pagina pagina = GestorIOPagina.leerPagina(relacion, idPagina, archivoBD);
                archivoBD.close();
                Pagina paginaDesechada = buffer.ponerPaginaEnBuffer(pagina, true);
                if (paginaDesechada != null) {
                    nombreArchivo = paginaDesechada.getIdentificadorPagina().getNombreArchivo();
                    archivoBD = new RandomAccessFile(nombreArchivo, "rw");
                    GestorIOPagina.escribirPagina(archivoBD, paginaDesechada);
                    archivoBD.close();
                }
                return pagina;
            }
        } catch (IOException e) {
            System.out.println("Error leyendo la página del disco. "+ e);
            return null;
        }
    }
    
    /**
     * Crear unn nuevo archivo en disco.
     * 
     */
    public void crearArchivo(String nombreArchivo){
        try {
            File file = new File(nombreArchivo);
            if (!file.createNewFile()) {
                file.delete();
                file.createNewFile();
            }
        } catch (Exception e) {
            System.err.println("No se puede crear el archivo "
                    + nombreArchivo + ". "+ e);
        }
    }
}

3) Implementar el gestor de relación

Clase GestorIORelacion

package org.taqque.almacenamiento;

import java.io.FileNotFoundException;
import java.io.IOException;

import java.io.RandomAccessFile;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.taqque.memoriaintermedia.GestorMemoriaIntermedia;

/**
 * GestorIORelacion: clase que representa de forma básica las funciones 
 * de I/O en una relación.
 *
 * @author hernan
 */
public class GestorIORelacion {

    /** El esquema de relación a ser gestionada. */
    private Relacion relacion;
    /** El gestor de almacenamiento para este gestor. */
    private GestorAlmacenamiento ga;
    /** El nombre de archivo de la relación. */
    private String nombreArchivo;

    /**
     * Constructor de un nuevo gestor I/O de relación.
     * 
     */
    public GestorIORelacion(GestorAlmacenamiento ga,
            Relacion relacion,
            String nombreArchivo) {
        this.ga = ga;
        this.relacion = relacion;
        this.nombreArchivo = nombreArchivo;
    }

    /**
     * Insertar una nueva tupla en la relación.
     * 
     * @param lista de valores.
     */
    public void insertarTupla(List<Comparable> valores) {
        try {
            // leer la última página del archivo
            int numPagina = recuperarNumeroDePaginas(getNombreArchivo());
            numPagina = (numPagina == 0) ? 0 : numPagina - 1;
            IdentificadorPagina idPagina =
                    new IdentificadorPagina(getNombreArchivo(), numPagina);
            Pagina pagina = ga.leerPagina(relacion, idPagina);
            int num = 0;
            if (pagina.getNumeroDeTuplas() != 0) {
                Tupla t = pagina.recuperarTupla(pagina.getNumeroDeTuplas() - 1);
                num = t.getIdTupla().getNumero() + 1;
            }
            Tupla nuevaTupla = new Tupla(
                    new IdentificadorTupla(getNombreArchivo(), num), valores);
            if (!pagina.hayEspacio(nuevaTupla)) {
                pagina = new Pagina(relacion, 
                        new IdentificadorPagina(getNombreArchivo(),
                        numPagina + 1));
                cambiarNumeroDePaginas(getNombreArchivo(), numPagina + 2);
            }
            pagina.adicionarTupla(nuevaTupla);

            ga.escribirPagina(pagina);
        } catch (Exception e) {
            e.printStackTrace(System.err);
            System.err.println("Error de I/O mientras se insertaba la tupla "
                    + "al archivo: " + getNombreArchivo()
                    + " (" + e.getMessage() + ")");
        }
    }

    /**
     * Recuperar el numero de paginas en el archivo de la relación.
     * 
     */
    public int recuperarNumeroDePaginas(String nombreArchivo)
            throws IOException, FileNotFoundException {

        RandomAccessFile archivoDB = new RandomAccessFile(getNombreArchivo(), "r");
        int paginas = (int) ((archivoDB.length() / 4096) + 0.5);
        archivoDB.close();
        return paginas;
    }

    public void cambiarNumeroDePaginas(String nombreArchivo, int np)
            throws IOException, FileNotFoundException {

        RandomAccessFile archivoBD = new RandomAccessFile(getNombreArchivo(), "rw");
        int paginas = (int) ((archivoBD.length() / 4096) + 0.5);
        if (paginas < np) {
            archivoBD.setLength(np * 4096);
        }
        archivoBD.close();
    }

    public String getNombreArchivo() {
        return nombreArchivo;
    }

    /**
     * Abrir un iterador de pagina sobre la relación.
     *
     */
    public Iterable<Pagina> paginas() throws IOException {
        return new PaginaIterator();
    }

    /**
     * Abrir un iterador de tuplas sobre la relación.
     *
     */
    public Iterable<Tupla> tuplas() throws IOException {
        return new TuplaIterator();
    }

    /**
     * Un iterador basico para paginas de la relación.
     */
    class PaginaIterator implements Iterable<Pagina> {

        /** La pagina actual en la iteración. */
        private Pagina paginaActual;
        /** Numero de páginas en la relación. */
        private int numPaginas;
        /** El desplazamiento de la actual pagina. */
        private int desplazamientoPagina;

        /**
         * Construir un nuevo iterador de pagina.
         */
        public PaginaIterator() throws IOException {

            desplazamientoPagina = 0;
            numPaginas = recuperarNumeroDePaginas(getNombreArchivo());
        }

        /**
         * devolver un iterador de paginas.
         */
        @Override
        public Iterator<Pagina> iterator() {
            return new Iterator<Pagina>() {

                @Override
                public boolean hasNext() {
                    return desplazamientoPagina < numPaginas;
                }

                @Override
                public Pagina next() throws NoSuchElementException {
                    try {
                        paginaActual =
                                ga.leerPagina(relacion,
                                new IdentificadorPagina(getNombreArchivo(),
                                desplazamientoPagina++));
                        return paginaActual;
                    } catch (Exception sme) {
                        throw new NoSuchElementException("No se puede leer la "
                                + "paina por el iterador." + sme.getMessage());

                    }
                } 

                @Override
                public void remove() throws UnsupportedOperationException {
                    throw new UnsupportedOperationException("no se puede eliminar "
                            + "paginas en un iterador");
                }
            }; 
        } 
    } // Fin de clase

    /**
     * UN iterador básico para tuplas de la relación.
     */
    class TuplaIterator implements Iterable<Tupla> {

        /** La página a iterar. */
        private Iterator<Pagina> paginas;
        /** un simple iterador de tuplas. */
        private Iterator<Tupla> tuplas;
        /** Registrar la pista si hay mas tuplas que devolver. */
        private boolean masElementos;

        /**
         * Construir el iterador de tuplas.
         */
        public TuplaIterator() throws IOException {

            paginas = paginas().iterator();
            masElementos = paginas.hasNext();
            tuplas = null;
        } 

        /**
         * Verificar si hay mas tuplas que iterar
         */
        @Override
        public Iterator<Tupla> iterator() {
            return new Iterator<Tupla>() {

                public boolean hasNext() {
                    return masElementos;
                } // hasNext()

                public Tupla next() throws NoSuchElementException {
                    if (tuplas == null && masElementos) {
                        tuplas = paginas.next().iterator();
                    }

                    Tupla tupla = tuplas.next();
                    if (tuplas.hasNext()) {
                        masElementos = true;
                    } else if (paginas.hasNext()) {
                        tuplas = paginas.next().iterator();
                        masElementos = true;
                    } else {
                        masElementos = false;
                    }
                    return tupla;
                } 

                @Override
                public void remove() throws UnsupportedOperationException {
                    throw new UnsupportedOperationException("no se puede eliminar "
                            + "tuplas al "
                            + "iterar.");
                }
            }; 
        } 
    } // Fin de clase

    /**
     * test de las clases.
     */
    public static void main(String[] args) {
        try {
            GestorMemoriaIntermedia gmi = new GestorMemoriaIntermedia(2);
            GestorAlmacenamiento ga = new GestorAlmacenamiento(null, gmi);

            List<Atributo> atributos = new ArrayList<Atributo>();
            atributos.add(new Atributo("integer", Integer.class));
            atributos.add(new Atributo("string", String.class));
            
            Relacion relacion = new Relacion(atributos);
            
            String nombreArchivo = "d:/prueba/relacionprueba.db";
            ga.crearArchivo(nombreArchivo);

            GestorIORelacion gestor =
                    new GestorIORelacion(ga, relacion, nombreArchivo);

            for (int i = 0; i < 100; i++) {
                List<Comparable> v = new ArrayList<Comparable>();
                v.add(new Integer(i));
                v.add(new String("12345678901234567890123456789012345678901234567890"));
                // System.out.println("insertando: " + v);
                gestor.insertarTupla(v);
            }

            System.out.println("Tuplas insertadas correctamente.");
            System.out.println("Abriendo un cursos de tuplas...");



            for (Tupla tuple : gestor.tuplas()) {
                System.out.println("read tupla: " + tuple);
            }

            for (Pagina pagina : gestor.paginas()) {
                System.out.println("read page: " + pagina);
            }

            System.out.println("buffer: " + gmi);

        } catch (Exception e) {
            System.err.println("Exception: " + e.getMessage());
            e.printStackTrace(System.err);
        }
    } 
}

4) Implementar un programa para insertar varias tuplas 

El método main de la clase GestorIORelacion inserta 100 tuplas las cuales el gestor de almacenamiento las registra en 3 paginas, de las cuales 2 paginas están localizadas en memoria intermedia y la otra al ser desechada de la memoria intermedia se escribió en el disco. Para el ejemplo de utiliza la memoria intermedia con capacidad de almacenamiento de 2 páginas.

Resultado: Solo se muestra las lineas mas representativas.

Tuplas insertadas correctamente.
Abriendo un cursos de tuplas...
Leer todas las tuplas de la relación ubicados ya sea en disco o en el buffer de la memoria intermedia:
read tupla: [d:/prueba/relacionprueba.db - 0] : [0, 12345678901234567890123456789012345678901234567890]
read tupla: [d:/prueba/relacionprueba.db - 1] : [1, 12345678901234567890123456789012345678901234567890]
read tupla: [d:/prueba/relacionprueba.db - 2] : [2, 12345678901234567890123456789012345678901234567890]
read tupla: [d:/prueba/relacionprueba.db - 3] : [3, 12345678901234567890123456789012345678901234567890]
..................................................
read tupla: [d:/prueba/relacionprueba.db - 98] : [98, 12345678901234567890123456789012345678901234567890]
read tupla: [d:/prueba/relacionprueba.db - 99] : [99, 12345678901234567890123456789012345678901234567890]

Leer todas las paginas mas contenido de la relación ubicados ya sea en disco o en el buffer de la memoria intermedia:
read page: pagina: [pagina d:/prueba/relacionprueba.db:0], tuplas: {
            0: [d:/prueba/relacionprueba.db - 0] : [0, 12345678901234567890123456789012345678901234567890]
            1: [d:/prueba/relacionprueba.db - 1] : [1, 12345678901234567890123456789012345678901234567890]
            2: [d:/prueba/relacionprueba.db - 2] : [2, 12345678901234567890123456789012345678901234567890]
    .............................
            34: [d:/prueba/relacionprueba.db - 34] : [34, 12345678901234567890123456789012345678901234567890]
            35: [d:/prueba/relacionprueba.db - 35] : [35, 12345678901234567890123456789012345678901234567890]
}

read page: pagina: [pagina d:/prueba/relacionprueba.db:1], tuplas: {
            0: [d:/prueba/relacionprueba.db - 36] : [36, 12345678901234567890123456789012345678901234567890]
            1: [d:/prueba/relacionprueba.db - 37] : [37, 12345678901234567890123456789012345678901234567890]
            2: [d:/prueba/relacionprueba.db - 38] : [38, 12345678901234567890123456789012345678901234567890]
    ...........................................................
            34: [d:/prueba/relacionprueba.db - 70] : [70, 12345678901234567890123456789012345678901234567890]
            35: [d:/prueba/relacionprueba.db - 71] : [71, 12345678901234567890123456789012345678901234567890]
}

read page: pagina: [pagina d:/prueba/relacionprueba.db:2], tuplas: {
            0: [d:/prueba/relacionprueba.db - 72] : [72, 12345678901234567890123456789012345678901234567890]
            1: [d:/prueba/relacionprueba.db - 73] : [73, 12345678901234567890123456789012345678901234567890]
            2: [d:/prueba/relacionprueba.db - 74] : [74, 12345678901234567890123456789012345678901234567890]
    .............................................
            25: [d:/prueba/relacionprueba.db - 97] : [97, 12345678901234567890123456789012345678901234567890]
            26: [d:/prueba/relacionprueba.db - 98] : [98, 12345678901234567890123456789012345678901234567890]
            27: [d:/prueba/relacionprueba.db - 99] : [99, 12345678901234567890123456789012345678901234567890]
}

buffer: Buffer: Paginas: {
            0: pagina: [pagina d:/prueba/relacionprueba.db:2], tuplas: {
            0: [d:/prueba/relacionprueba.db - 72] : [72, 12345678901234567890123456789012345678901234567890]
            1: [d:/prueba/relacionprueba.db - 73] : [73, 12345678901234567890123456789012345678901234567890]
            25: [d:/prueba/relacionprueba.db - 97] : [97, 12345678901234567890123456789012345678901234567890]
    ........................................
            26: [d:/prueba/relacionprueba.db - 98] : [98, 12345678901234567890123456789012345678901234567890]
            27: [d:/prueba/relacionprueba.db - 99] : [99, 12345678901234567890123456789012345678901234567890]
}

1: pagina: [pagina d:/prueba/relacionprueba.db:1], tuplas: {
            0: [d:/prueba/relacionprueba.db - 36] : [36, 12345678901234567890123456789012345678901234567890]
            26: [d:/prueba/relacionprueba.db - 62] : [62, 12345678901234567890123456789012345678901234567890]
    ...............................................................................
            34: [d:/prueba/relacionprueba.db - 70] : [70, 12345678901234567890123456789012345678901234567890]
            35: [d:/prueba/relacionprueba.db - 71] : [71, 12345678901234567890123456789012345678901234567890]
}
}

LRU: {[1, 2]}

En la última parte del resultado se puede apreciar que la página 0 no se encuentra en el buffer, esto porque fue desechada para la entrada de la pagina 2.

IV) Tarea

  • El programa del método main de la clase GestorIORelacion no permite volcar todas las páginas que están en la memoria intermedia al disco cuando el programa se cierra o deja de funcionar. Entonces modifique este programa para que pueda guardar todas las páginas en el disco cuando este termine su funcionamiento.
  • Implementar las clases necesarias para construir un Archivo Secuencial Indexado para una determinada relación.

Laboratorio 0001: Almacenamiento con diccionario de datos o Catalogo del sistema

publicado a la‎(s)‎ 10 jul. 2012 19:09 por Hernan Nina Hanco   [ actualizado el 4 jun. 2013 13:50 ]

I) OBJETIVOS
  • Implementar el catalogo del sistema de gestión de bases de datos.

II) MARCO CONCEPTUAL

El catalogo del sistema almacena información del esquema de la base de datos registrada en el sistema de gestión de bases de datos, almacena nombres de tablas, columnas, indices, información de usuarios, claves y demás meta-datos. 

En la presente práctica se implementa un catalogo básico, que solo registra información de las tablas y sus correspondientes atributos. Cada información de tabla se almacena en una entrada de catalogo. El catalogo utiliza una tabla hash para registrar las entradas de catalogo y también las puede localizar en base a las operaciones de la tabla hash.

III) PRÁCTICAS DE LABORATORIO

1) Implementación de una entrada de catalogo
Clase EntradaCatalogo
package org.taqque.almacenamiento;
/**
 * EntradaCatalogo: Almacena toda la informacion referente a una 
 * tabla en el catalogo.
 * 
 * @author hernan
 */
public class EntradaCatalogo implements java.io.Serializable {
    /** Directory of the server. */
    public static String TAQQUE_DIR="d:/prueba";
    /** Tabla para este entrada a catalogo. */
    private Tabla tabla;
    /** El nombre de archvio para la tabla. */
    private String nombreArchivo;
    public EntradaCatalogo(Tabla tabla) {
        this.tabla = tabla;
        crearNombreArchivo();
    } 
    public String getNombreTabla() {
        return tabla.getNombre();
    } 
    public Tabla getTabla() {
        return tabla;
    } 
    public String getNombreArchivo() {
        return nombreArchivo;
    } 
    @Override
    public String toString() {
        return "Tabla: " + getNombreTabla() + ", nombre de Archivo: "
            + nombreArchivo + ", definición: " + tabla+"\n";
    }
    protected void crearNombreArchivo() {
        String nombreTabla = tabla.getNombre();
        nombreArchivo = new String(TAQQUE_DIR
                              + System.getProperty("file.separator")
                              + nombreTabla + "_" + nombreTabla.hashCode());
    } 
}
2) Implementar el catalogo del sistema
Clase Catalogo
package org.taqque.almacenamiento;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Map;
import java.util.NoSuchElementException;

/**
 * Diccionario de Datos - Meta datos
 * @author hernan
 */
public class Catalogo {
    /** Nombre de archivo del catalogo. */
    private String archivoCatalogo;
    /** Entradas del catalogo, mapean nombres de tabla a entradas. */
    private java.util.Map<String, EntradaCatalogo> entradas;
    /** Numero de tablas actualmente almacenadas en el catalogo. */
    private int numeroDeTablas;
    public Catalogo(String archivoCatalogo) {
        this.archivoCatalogo = archivoCatalogo;
        entradas = new java.util.Hashtable<String, EntradaCatalogo>();
    }
    public void crearNuevaEntrada(EntradaCatalogo entrada)
            throws IllegalArgumentException {
        if (!existeTabla(entrada.getNombreTabla())) {
            entradas.put(entrada.getNombreTabla(), entrada);
            numeroDeTablas++;
        } else {
            throw new IllegalArgumentException("Tabla: "
                    + entrada.getNombreTabla()
                    + " ya existe.");
        }
    }
    protected boolean existeTabla(String nombreTabla) {
        return (entradas.get(nombreTabla) != null);
    }
    @Override
    public String toString() {
        return "Catalogo: " + numeroDeTablas + " tablas.  Entradas: \n"
                + "\t" + entradas.toString();
    }
    // Leer un archivo de catalogo del Disco
    public void leerCatalogo() throws Exception {
        try {
            // Objeto que representa al archivo
            FileInputStream fstream = new FileInputStream(archivoCatalogo);
            // tarea de lectura utilizamos este objeto
            ObjectInputStream istream = new ObjectInputStream(fstream);

            // leer en del número de tablas
            numeroDeTablas = istream.readInt();
            // leer en las entradas del catálogo

            entradas = (Map<String, EntradaCatalogo>) istream.readObject();

            istream.close();
        } catch (Exception ex) {
            System.out.println("Problemas al abrir el archivo: " + ex.getMessage());
        }
    }
    // Metodo para almacenar el catalogo en disco

    public void escribirCatalogo() throws Exception {

        try {
            // Crear un nuevo archivo en disco - Interface acceso de archivo
            FileOutputStream fstream = new FileOutputStream(archivoCatalogo);
            // realizar operaciones de escritura en el archivo
            ObjectOutputStream ostream = new ObjectOutputStream(fstream);

            // write out the number of tables
            ostream.writeInt(numeroDeTablas);
            // write out the entries of the catalog
            ostream.writeObject(entradas);
            // ejecutar el almacenamiento
            ostream.flush();
            ostream.close(); // si no realiza cerrar no almacena 
        } catch (IOException ioe) {
            System.out.println("I/O Exception mientras se almacenaba el archvio del catalogo "
                    + archivoCatalogo + ioe.getMessage());
        }
    }
    
    public void eliminarTabla(String nombreTabla)
        throws NoSuchElementException {
        
        if (! existeTabla(nombreTabla))
            throw new NoSuchElementException("Tabla " + nombreTabla + " no esta "
                                             + "en el catalogo de la BD.");
        entradas.remove(nombreTabla);
        numeroDeTablas--;
    } // deleteTable()

    public static void main(String args[]) {
        try {
            // crear tres nuevas entradas de tabla
            EntradaCatalogo ce1 = new EntradaCatalogo(
                    new Tabla("alumno", new ArrayList<Atributo>()));
            EntradaCatalogo ce2 =
                    new EntradaCatalogo(new Tabla("docente",
                    new ArrayList<Atributo>()));
            EntradaCatalogo ce3 =
                    new EntradaCatalogo(new Tabla("curso",
                    new ArrayList<Atributo>()));

            // crear el catalogo

            Catalogo catalogo = new Catalogo(EntradaCatalogo.TAQQUE_DIR+
                    System.getProperty("file.separator") + "catalogoprueba.dat");
            // añdir informacion a catalogo
            
            catalogo.crearNuevaEntrada(ce1);
            catalogo.crearNuevaEntrada(ce2);
            catalogo.crearNuevaEntrada(ce3);

            // imprimir en patalla el catalogo
            System.out.println(catalogo);
            Thread.sleep(1000);

            // escribir el catalogo en archivo
            System.out.println("Creando catalogo catalog.");
            catalogo.escribirCatalogo();
            Thread.sleep(1000);

            // Leer el catalogo almacenado recientemente
            System.out.println("Leyendo catalogo.");
            catalogo.leerCatalogo();

             // Imprimir nuevamente el catalogo
            System.out.println(catalogo);
            Thread.sleep(1000);
            // Eliminar una Tabla
            System.out.println("Eliminado una tabla.");
            catalogo.eliminarTabla("docente");
             // Imprimir nuevamente el catalogo
            System.err.println(catalogo);
            Thread.sleep(1000);
        } catch (Exception e) {
            System.err.println("Exception " + e.getMessage());
            e.printStackTrace(System.err);
        }
    } // main()
}

3) Implementar una representación básica de una tabla
Clase Tabla
package org.taqque.almacenamiento;
/**
 *
 * @author hernan
 */
public class Tabla extends Relacion implements java.io.Serializable{
      private String nombre;
    
    public Tabla(String nombre) {
        super();
        this.nombre = nombre;
    } 
    public Tabla(String nombre, java.util.List<Atributo> atributos) {
        super(atributos);
        this.nombre = nombre;
    }
    public String getNombre() {
        return nombre;
    }
}

4) Demostración de la utilización del catalogo.
La demostración podemos apreciarla en el método main de la clase Catalogo, puede identificarlo porque tiene el color azul.
El resultado de ejecutar el método main es el siguiente:

run:
Catalogo: 3 tablas.  Entradas: 
{docente=Tabla: docente, nombre de Archivo: d:/prueba\docente_1828437522, definición: {}
, curso=Tabla: curso, nombre de Archivo: d:/prueba\curso_95027356, definición: {}
, alumno=Tabla: alumno, nombre de Archivo: d:/prueba\alumno_-1414605564, definición: {}
}
Creando catalogo catalog.
Leyendo catalogo.
Catalogo: 3 tablas.  Entradas: 
{alumno=Tabla: alumno, nombre de Archivo: d:/prueba\alumno_-1414605564, definición: {}
, docente=Tabla: docente, nombre de Archivo: d:/prueba\docente_1828437522, definición: {}
, curso=Tabla: curso, nombre de Archivo: d:/prueba\curso_95027356, definición: {}
}
Eliminado una tabla.
Catalogo: 2 tablas.  Entradas: 
{alumno=Tabla: alumno, nombre de Archivo: d:/prueba\alumno_-1414605564, definición: {}
, curso=Tabla: curso, nombre de Archivo: d:/prueba\curso_95027356, definición: {}
}
BUILD SUCCESSFUL (total time: 6 seconds)
El resultado indica que se han registrado tres tablas en el catalogo, luego se han escrito en el disco y seguidamente se han leído del disco y se han mostrado en pantalla. Finalmente muestra una entrada eliminada. 
IV) Tarea
  • Modificar el programa anterior, para que muestre información de los atributos de tabla (Campos)
  • Implemente un programa que permita registrar la información de tablas, especificando sus nombres y atributos correspondientes, el programa debe permitir la opción de eliminar entradas y actualizar las mismas sobre cualquier cambio.
V) Refeerencias
  • Se adjunta el código de las clases implementadas hasta la fecha del SGBD.

Laboratorio 0003: Gestión de páginas

publicado a la‎(s)‎ 25 jun. 2012 18:08 por Hernan Nina Hanco   [ actualizado el 4 jun. 2013 14:20 ]

I) OBJETIVOS
  • Implementar la gestión de páginas.

II) MARCO CONCEPTUAL


En el presente laboratorio, se implementa la gestión de paginas o bloques de disco que almacenan las tuplas de una relación. Para este fin se ha creado la clase IdentificadorPagina  que permite la identificación de una Página o Bloque en el archivo de una determinada relación. Tambiés es necesario la creación de la clase Pagina que representa un abstracción básica de una Pagina de disco, cumple con las operaciones de registrar tuplas en el espacio libre que tiene. Para las operaciones de acceder a una página en un archivo se ha creado la clase estática GestionIOPagina encargada de escribir y recuperar una página del archivo de la relación. 

Para las implementaciones se han tomado en cuenta la organización de registros en archivos por montículos y archivos con registros de longitud fija.

III) PRÁCTICAS DE LABORATORIO

1) Implementación de la Clase IdentificadorPágina.

package org.taqque.almacenamiento;

/**
 * IdentificadorPagina: Identifica una página en disco.
 *
 * @author hernan
 */
public class IdentificadorPagina {
    /** Nombre del archivo al que pertenece la página. */
    private String nombreArchivo;
    /** numero de la página. */
    private int numero;

    
    /**
     * Crear un nuevo identificador.
     * 
     * @param nombreArchivo el archivo al que la página pertenece.
     * @param numero el numero de la página en el archivo.
     */
    public IdentificadorPagina(String nombreArchivo, int numero) {
        
        this.nombreArchivo = nombreArchivo;
        this.numero = numero;
    } // PageIdentifier()

    
    /**
     * Recupera el nombre de archivo al que pertenece la página.
     * 
     * @return nombre de archivo.
     */
    public String getNombreArchivo() {
        
        return nombreArchivo;
    }

    
    /**
     * Recupera el número de la página.
     * 
     * @return numero de página.
     */
    public int getNumero () {
        return numero;
    }
    
    /**
     * Retorna una representación textual del identificador de página.
     * 
     * @return representación textual del identificador.
     */
    @Override
    public String toString() {
        
        return "[pagina " + getNombreArchivo() + ":" + getNumero() + "]";
    }
}
 
2) Implementar la clase Pagina.

package org.taqque.almacenamiento;

import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;

/**
 * Pagina: Representación básica de una página de disco.
 *
 * @author hernan
 */
public class Pagina implements Iterable<Tupla> {

    /** Las tuplas de la página. */
    private List<Tupla> tuplas;
    /** El ID de la página. */
    private IdentificadorPagina idPagina;
    /** El esquema de la relación al que pertenece la página. */
    private Relacion relacion;
    /** El espacio libre en la página. */
    private int espacioLibre;

    /**
     * Crear una nueva página dado el esquema de la relación y el IdPagina.
     * 
     * @param relacion la relación al que pertenece la página.
     * @param idPagina el ID de la página.
     */
    public Pagina(Relacion relacion, IdentificadorPagina idPagina) {
        this.relacion = relacion;
        this.idPagina = idPagina;
        this.tuplas = new ArrayList<Tupla>();
        // tamaño de página 4k
        espacioLibre = 4096 - Convert.INT_SIZE;
    }

    /**
     * Devolver la relación a la que pertenece la página.
     * 
     * @return relación a la que pertenece la página.
     */
    public Relacion getRelacion() {
        return relacion;
    }

    /**
     * Verificar si la página tiene espacio para mas tuplas.
     *
     * @return <pre>true</pre> si hay espacio para mas tuplas
     * en la página, <pre>false</pre> en caso contrario.
     */
    public boolean hayEspacio(Tupla t) {
        return espacioLibre >= GestorIOTupla.byteSize(getRelacion(), t);
    }

    /**
     * Devolver el número de tuplas almacendas en la página.
     *
     * @return numero de tuplas almacenadas en la página.
     */
    public int getNumeroDeTuplas() {
        return tuplas.size();
    }

    /**
     * Almacenar una nueva tupla en la página.
     * 
     * @param tupla la nueva tupla.
     * @throws ArrayIndexOutOfBoundsException lanzar si el límite del tamaño de la
     * página no es suficiente para almacenar la tupla.
     */
    public void adicionarTupla(Tupla tupla)
            throws ArrayIndexOutOfBoundsException {

        if (hayEspacio(tupla)) {
            tuplas.add(tupla);
            espacioLibre -= GestorIOTupla.byteSize(getRelacion(), tupla);
        } else {
            throw new ArrayIndexOutOfBoundsException("no hay espacio en la página.");
        }
    }

    /**
     * Cambiar una tupla.
     * 
     * @param indice el indice de la tupla a ser cambiada.
     * @param tupla la nueva tupla.
     * @throws ArrayIndexOutOfBoundsException lanzar si el límite del tamaño de la
     * página no es suficiente para almacenar la nueva tupla.
     */
    public void setTupla(int index, Tupla tupla)
            throws ArrayIndexOutOfBoundsException {

        if (!puedeCambiar(index, tupla)) {
            throw new ArrayIndexOutOfBoundsException("no hay espacio en la página.");
        }
        tuplas.set(index, tupla);
    }

    /**
     * Verificar si un especifico indice de una tupla puede ser reemplazado 
     * por una nueva tupla.
     *
     * @param index indice de la tupla a ser reemplado.
     * @param nt la nueva tupla.
     */
    public boolean puedeCambiar(int index, Tupla nt) {

        return (espacioLibre
                + GestorIOTupla.byteSize(getRelacion(), tuplas.get(index))
                - GestorIOTupla.byteSize(getRelacion(), nt)) >= 0;
    }

    /**
     * Intercambiar dos tuplas en base a sus indices.
     *
     * @param x el indice de la primera tupla.
     * @param y el índice de la segunda tupla.
     */
    public void intercambiar(int x, int y) {
        Tupla t = tuplas.get(x);
        tuplas.set(x, tuplas.get(y));
        tuplas.set(y, t);
    }

    /**
     * Recuperar una determinada tupla de la página.
     * 
     * @param index el indice de la tupla a ser recuperada.
     * @return una tupla en la posición de index.
     */
    public Tupla recuperarTupla(int index) {

        return tuplas.get(index);
    }

    /**
     * Recuperar el ID de la pagina
     * 
     * @return ID de la página
     */
    public IdentificadorPagina getIdentificadorPagina() {
        return idPagina;
    }

    /**
     * Devolver un iterator de tuplas de la página.
     *
     * @return an iterator .
     */
    @Override
    public Iterator<Tupla> iterator() {
        return new IteradorDePagina();
    }

    /**
     * Clase interna que implementa un iterator de tupla
     * DIGA 18 de Junio - 022600
     */
    private class IteradorDePagina implements Iterator<Tupla> {

        /** El actual indice del iterator. */
        private int indiceActual;

        /**
         * Constructor de un nuevo iterator para el contenido de la página.
         */
        public IteradorDePagina() {
            indiceActual = 0;
        }

        /**
         * Verificar si hay mas tuplas en la página.
         *
         * @return <code>true</code> si hay mas tuplas
         * en la página, <code>false</code> en caso contrario.
         */
        @Override
        public boolean hasNext() {
            return indiceActual < tuplas.size();
        }

        /**
         * Devuelve la siguiente tupla del iterator.
         *
         * @return la siguiente tupla del iterator.
         */
        @Override
        public Tupla next() {
            return tuplas.get(indiceActual++);
        }

        /**
         * Elimina la última tupla devuelta por el iterador.
         */
        @Override
        public void remove() {
            int size = GestorIOTupla.byteSize(getRelacion(),
                    tuplas.get(indiceActual));
            espacioLibre += size;
            tuplas.remove(indiceActual);
        }
    }

    /**
     * Devolver un representación textual de la página.
     * 
     * @return representación textual de la página.
     */
    @Override
    public String toString() {

        StringBuilder sb = new StringBuilder();
        sb.append("pagina: ").append(getIdentificadorPagina()).append(", tuplas: {\n");
        int tid = 0;
        for (Tupla it : this) {
            sb.append("\t").append(tid++).append(": ").append(it.toString()).append("\n");
        }
        sb.append("}");
        return sb.toString();
    }
}

3) Implementar la clase GestorIOPagina

package org.taqque.almacenamiento;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;

/**
 * GestorIOPagina: Implementa un gestor de pagina de I/O sobre archivos.
 *
 * @author hernan
 */
public class GestorIOPagina {

    /**
     * Construir una nuevo gestor de página de I/O.
     */
    public GestorIOPagina() {
    }

    /**
     * Escribe una página en un archivo de salida
     * 
     * @param raf archivo de salida.
     * @param pagina la página a ser escrita.
     * @throws StorageManagerException thrown whenever there is an
     * output error.
     */
    public static void escribirPagina(RandomAccessFile raf, Pagina pagina) {

        try {
            // buscar el lugar correcto en el archivo
            long seek = pagina.getIdentificadorPagina().getNumero() * 4096;
            raf.seek(seek);
            byte[] bytes = new byte[4096];
            volcarNumero(pagina, bytes);
            volcarTuplas(pagina, bytes);
            raf.write(bytes);
        } catch (IOException ioe) {
            System.out.println("Exception mientras se escribe la página "
                    + pagina.getIdentificadorPagina()
                    + " a disco: " + ioe);
        }
    }

    /**
     * Leer una página del disco.
     * 
     * @param relacion la relación a la que la página pertenece.
     * @param pid Identificador de la página.
     * @param raf el archivo de la salida.
     * @return la página leida.
     */
    public static Pagina leerPagina(Relacion relacion, IdentificadorPagina pid, RandomAccessFile raf) {
        try {
            // seek to the appropriate place
            long seek = pid.getNumero() * 4096;
            raf.seek(seek);
            byte[] bytes = new byte[4096];
            int leerBytes = raf.read(bytes);
            if (leerBytes == -1) {
                // hemos llegado al final del archivo, 
                // así que tenemos que asignar una página
                raf.setLength(seek + 4096);
                return new Pagina(relacion, pid);
            }
            if (leerBytes != 4096) {
                System.out.println("Pagina: " + pid.toString()
                        + "no fue leido completamente.");
            }
            return extraerTuplas(relacion, pid, bytes);
        } catch (IOException ioe) {
            System.out.println("Exception mientras se lee la página "
                    + pid.toString()
                    + " de disco. " + ioe);
            return null;
        }
    }

    /**
     * Volcar al arreglo de bytes el número de tuplas en la página.
     *
     * @param pagina la página a ser escrita.
     * @param bytes un arreglo de salida de bytes.     
     */
    protected static void volcarNumero(Pagina pagina, byte[] bytes) {

        byte[] b = Convert.toByte(pagina.getNumeroDeTuplas());
        System.arraycopy(b, 0, bytes, 0, b.length);
    }

    /**
     * Volcar a arreglo de bytes una página de tuplas a disco.
     * 
     * @param pagina la página a ser escrito en el disco.
     * @param bytes el arreglo de bytes de salida para las tuplas.
     */
    protected static void volcarTuplas(Pagina pagina, byte[] bytes) {

        // crear un nuevo gestor IO de tuplas
        GestorIOTupla gestor =
                new GestorIOTupla(pagina.getRelacion(),
                pagina.getIdentificadorPagina().getNombreArchivo());
        // Un numero entero se utiliza para el numero de tuplas
        int desplazamiento = Convert.INT_SIZE;
        // iterate sobre todas las tuplas de la página, y localizarlo en el arreglo
        for (Tupla tupla : pagina) {
            desplazamiento = gestor.escribirTupla(tupla, bytes, desplazamiento);
        }
        rellenar(bytes, desplazamiento);
    }

    /**
     * Leer las tuplas del disco y los coloca en una página.
     * 
     * @param relacion la relacion a la que pertenece la página.
     * @param pid el identificador de la nueva página.
     * @param bytes el arreglo de bytes donde las tuplas se encuentran.
     * @return la pagina leida del disco.
     */
    protected static Pagina extraerTuplas(Relacion relacion, IdentificadorPagina pid,
            byte[] bytes) {

        // crear un gestor IO de tupla
        GestorIOTupla gestor = new GestorIOTupla(relacion,
                pid.getNombreArchivo());
        // iniciar la lectura de tuplas
        int numeroDeTuplas = extraerNumero(bytes);
        Pagina pagina = new Pagina(relacion, pid);
        // Un numero entero se utiliza para el numero de tuplas
        int desplazamiento = Convert.INT_SIZE;
        for (int i = 0; i < numeroDeTuplas; i++) {
            Par par = gestor.leerTupla(bytes, desplazamiento);
            Tupla tupla = (Tupla) par.primero;
            desplazamiento = ((Integer) par.segundo).intValue();
            pagina.adicionarTupla(tupla);
        }

        return pagina;
    }

    /**
     * Extraer numero de tuplas del arreglo de byte.
     *
     * @param bytes el arreglo de bytes.
     * @return el numero de tuplas.
     */
    public static int extraerNumero(byte[] bytes) {

        byte[] b = new byte[Convert.INT_SIZE];
        System.arraycopy(bytes, 0, b, 0, b.length);
        return Convert.toInt(b);
    }

    /**
     * Rellena una matriz de bytes con ceros para alcanzar 
     * el tamaño de página de disco.  
     * 
     * @param bytes el arreglo de bytes de entrada a ser rellenado.
     * @param inicio el inicio del desplazamiento en el arreglo de bytes.
     */
    protected static void rellenar(byte[] bytes, int inicio) {
        for (int i = inicio; i < bytes.length; i++) {
            bytes[i] = (byte) 0;
        }
    }
    
    /*
     * Probar las clases implementadas.
     */

    public static void main(String[] args) {
        try {
            // Crear el archivo de la relación
            String nombreArchivo = "D:/prueba/relacion.dat";
            // Crear un esquema de relación.    
            List<Atributo> attrs = new ArrayList<Atributo>();
            attrs.add(new Atributo("character", Character.class));
            attrs.add(new Atributo("byte", Byte.class));
            attrs.add(new Atributo("short", Short.class));
            attrs.add(new Atributo("integer", Integer.class));
            attrs.add(new Atributo("long", Long.class));
            attrs.add(new Atributo("float", Float.class));
            attrs.add(new Atributo("double", Double.class));
            attrs.add(new Atributo("string", String.class));
            // Esquema de relación
            Relacion esquema_relacion = new Relacion(attrs);
            // Crear una lista de valores de tupla
            List<Comparable> v = new ArrayList<Comparable>();
            v.add(new Character('a'));
            v.add(new Byte((byte) 26));
            v.add(new Short((short) 312));
            v.add(new Integer(2048));
            v.add(new Long(34567));
            v.add(new Float(12.3));
            v.add(new Double(25.6));
            v.add(new String("bla bla"));
            // crear tuplas de la relación
            Tupla t1 = new Tupla(new IdentificadorTupla(nombreArchivo, 0), v);
            Tupla t2 = new Tupla(new IdentificadorTupla(nombreArchivo, 1), v);
            
            // Crear 2 páginas de disco
            // Crear un id de página
            IdentificadorPagina pid1 = new IdentificadorPagina(nombreArchivo, 0);
            Pagina p1 = new Pagina(esquema_relacion, pid1);
            IdentificadorPagina pid2 = new IdentificadorPagina(nombreArchivo, 1);
            Pagina p2 = new Pagina(esquema_relacion, pid2);
            
            // añadir tuplas a las páginas
            p1.adicionarTupla(t1);
            p2.adicionarTupla(t2);
            // Mostrar las páginas creadas en pantalla
            System.out.println(p1);
            System.out.println(p2);
            // Almacenar en disco las páginas
            // Abrir en modo de lectura y escritura el archivo de la relación
            java.io.RandomAccessFile raf = 
                    new java.io.RandomAccessFile(nombreArchivo, "rw");
            // Escribir las páginas en el archivo de la relación
            System.out.println("Escribiendo paginas ...");
            GestorIOPagina.escribirPagina(raf, p1);
            GestorIOPagina.escribirPagina(raf, p2);
            // cerrar archivo
            raf.close();

            // Leer la página del disco
            // Abrir el archivo de la relacion en modo de lectura
            raf = new java.io.RandomAccessFile(nombreArchivo, "r");
            System.out.println("leyendo paginas...");

            Pagina pagina1 = 
                    GestorIOPagina.leerPagina(esquema_relacion, 
                    new IdentificadorPagina(nombreArchivo, 0), raf);
            Pagina pagina2 = 
                    GestorIOPagina.leerPagina(esquema_relacion, 
                    new IdentificadorPagina(nombreArchivo, 1), raf);
            // Mostrar las páginas leidas
            System.out.println(pagina1);
            System.out.println(pagina2);
            // cerrar archivo
            raf.close();
        } catch (Exception e) {
            System.err.println("Exception: " + e.getMessage());
            e.printStackTrace(System.err);
        }
    }
}

Resultado: 

run:
pagina: [pagina D:/prueba/relacion.dat:0], tuplas: {
0: [D:/prueba/relacion.dat - 0] : [a, 26, 312, 2048, 34567, 12.3, 25.6, bla bla]
}
pagina: [pagina D:/prueba/relacion.dat:1], tuplas: {
0: [D:/prueba/relacion.dat - 1] : [a, 26, 312, 2048, 34567, 12.3, 25.6, bla bla]
}
Escribiendo paginas ...
leyendo paginas...
pagina: [pagina D:/prueba/relacion.dat:0], tuplas: {
0: [D:/prueba/relacion.dat - 0] : [a, 26, 312, 2048, 34567, 12.3, 25.6, bla bla]
}
pagina: [pagina D:/prueba/relacion.dat:1], tuplas: {
0: [D:/prueba/relacion.dat - 1] : [a, 26, 312, 2048, 34567, 12.3, 25.6, bla bla]
}
BUILD SUCCESSFUL (total time: 2 seconds)

IV) Tarea:

1) Crear un programa, que permita registrar varias tuplas en las páginas correspondientes, El programa debe controlar el hecho de que una página que no tenga espacio suficiente para una nueva tupla, pueda crear de manera automática una nueva página y seguir agregando tuplas, Controlar el eliminado de tuplas.
2) Implementar la Gestión de una Página utilizando Estructuras de Páginas con Ranuras

Plazo de entrega: Lunes 02 de Julio del 2012.

Referencia de código:


Clase:

  • Pagina.java
  • GestorIOPagina.java
  • IdentificadorPagina.java

Laboratorio 0002: Gestión de Tuplas

publicado a la‎(s)‎ 6 jun. 2012 18:06 por Hernan Nina Hanco   [ actualizado el 7 may. 2013 13:08 ]

I) OBJETIVOS
  • Implementar la gestión de tuplas.

II) MARCO CONCEPTUAL


En la presente práctica, se implementa la gestión de tuplas como base para la gestión de páginas que contienen a una o varias tuplas en bloques de disco de tamaño fijo.
Dentro de la práctica, se implementa una clase Relación que es una abstracción básica de un Esquema de Relación que proporciona información de los atributos de la relación. También se implementa una Clase Atributo como parte del esquema de relación, la información que mantiene la clase Atributo, es el nombre de los atributos y los tipos de cada atributo.

Por lo tanto, podemos ahora definir las Tuplas y la Gestión de las mismas en base a la información del esquema de relación. Para este propósito, se implementa una Clase Tupla que permite representar cualquier tupla que esta compuesto por un identificador de tupla y los valores de la tupla, una tupla es un conjunto de celdas, para asegurar que esta clase Tupla represente a cualquier posibilidad de generar tuplas se implementa métodos que pueden identificar el tipo de una determinada celda de tupla. También se implementa una clase GestorIOTupla que permite escribir una tupla cualquiera en un arreglo de bytes y representar una tupla desde un arreglo de Bytes. La finalidad de trabajar las tuplas en bytes será necesario para trabajar con la gestión de paginas.   

III) PRÁCTICAS DE LABORATORIO

1) Implementar las siguientes clases, para la gestión de tuplas.
Clase Atributo
/*
 * Creado el 30 de Noviembre, 2011 por Hernán Nina Hanco
 *
 * Modificado el 11 de Diciembre, 2011 por Hernán Nina Hanco
 *
 * Esto es parte del proyecto Taqque.  
 * Código exclusivamente para fines académicos.
 * 
 * 
 * Universidad Nacional de San Antonio Abad del Cusco
 * Carrera de Ingeniería Informática y de Sistemas
 * 
 */
package org.taqque.almacenamiento;

/**
 * Atributo: Abstracción básica de un atributo como parte del 
 * modelo de datos del SGBD.
 *
 * @author hanconina
 */
public class Atributo implements java.io.Serializable {

    /** Nombre del atributo */
    private String nombre;
    /** Tipo de datos del atributo. */
    private Class<? extends Comparable> tipo;

    /**
     * Crear un nuevo atributo por su nombre y clase.
     * 
     * @param nombre, representa el nombre del atributo.
     * @param tipo, representa la clase del atributo.
     */
    public Atributo(String nombre, Class<? extends Comparable> tipo) {
        this.nombre = nombre;
        this.tipo = tipo;
    } // Atributo()
    
    /**
     * Devuelve el nombre del atributo.
     * 
     * @return nombre del atributo.
     */    
    public String getNombre() {
        return nombre;
    }
    
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    /**
     * Devuelve la clase o tipo del atributo.
     * 
     * @return tipo del atributo.
     */

    public Class<? extends Comparable> getTipo() {
        return tipo;
    }

    public void setTipo(Class<? extends Comparable> tipo) {
        this.tipo = tipo;
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (! (o instanceof Atributo)) return false;
        Atributo a = (Atributo) o;
        return getNombre().equals(a.getNombre()) && 
                getTipo().equals(a.getTipo());
    }

    @Override
    public int hashCode() {
        int hash = 17;
        hash = hash*31 + getNombre().hashCode();
        return hash*31 + getTipo().hashCode();
    }
    
    /**
     * Representación Textual.
     */
    @Override
    public String toString() {
        return getNombre() + ":" + getTipo();
    } // toString()    
}


Clase Relacion 
package org.taqque.almacenamiento; import java.util.Iterator; import java.util.List; import java.util.ArrayList; /** * * @author hernan */ public class Relacion implements java.io.Serializable, Iterable<Atributo> { /** lista de atributos de la relación. */ private List<Atributo> atributos; /** Constructor por Default de una relación. */ public Relacion() { atributos = new ArrayList<Atributo>(); } /** * Constructor de relación dado una <code>Lista</code> de atributos. * * @param atributos, atributos de la relacion. */ public Relacion(List<Atributo> atributos) { this.atributos = new ArrayList<Atributo>(atributos); } /** * Añadir un atributo a la relación. * * @param atributo, atributo a ser añadido. */ protected void adicionarAtributo(Atributo atributo) { atributos.add(atributo); } /** * Devuelve el numero de atributos de la relación. * * @return numero de atributos de una <code>Relación</code> */ public int getNumeroDeAtributos() { return atributos.size(); } /** * Devuelve un <code>Iterator</code> sobre los atributos de la * relación. * * @return <code>Iterator</code> de Atributos de la <code>Relación</code>. * */ @Override public Iterator<Atributo> iterator() { return atributos.iterator(); } /** * Devuelve un atributo especifico de la relación. * * @param i el indice del atributo que será devuelto. * @return el atributo especificaco. */ public Atributo getAtributo(int i) { return atributos.get(i); } /** * Dado el nombre de un atributo, se devuelve el índice de este atributo * en el esquema de la relación. Se devuelve <code>-1</code> si el atributo * no aparece en el esquema de la relación. * * @param atr el nombre del atributo * @return el indice del atributo en el esquema de la relación, * <code>-1</code> si el atributo no aparece en el esquema de la relación. */ public int getIndiceAtributo(String atr) { int i = 0; for (Atributo atributo : atributos) { if (atributo.getNombre().equals(atr)) { return i; } } return -1; } // getIndiceAtributo() /** * Representación textual de una relación. */ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("{"); for (int i = 0; i < getNumeroDeAtributos() - 1; i++) { sb.append(getAtributo(i)).append(", "); } sb.append(getAtributo(getNumeroDeAtributos() - 1)).append("}"); return sb.toString(); } // toString() }

Clase IdentificadorTupla
package org.taqque.almacenamiento;

/**
 * Un Identificador para una Tupla
 * 
 * @author hernan
 */
public class IdentificadorTupla {

    /** Nombre de archivo al que pertenece la tupla. */
    private String nombreArchivo;
    /** Numero de la tupla. */
    private int numero;

    /**
     * Construye un nuevo identificador de tupla cuando se conoce el nombre del
     * archivo al que pertence la tupla. El numero de tupla se cambia luego
     * 
     * @param Nombre del archivo al que pertenece la tupla.
     */
    public IdentificadorTupla(String nombreArchivo) {
        this(nombreArchivo, -1);
    } 

    /**
     * Construye una nueva tupla conociendo el nombre de archivo y el numero de tupla
     * 
     * @param nombreArchivo Nombre de archivo al que pertenece la tupla.
     * @param numero Numero de la tupla.
     */
    public IdentificadorTupla(String nombreArchivo, int numero) {
        this.nombreArchivo = nombreArchivo;
        this.numero = numero;
    }

    /**
     * Devuelve el nombre del archivo al que pertenece la tupla.
     * 
     * @return nombre del archivo al que pertenece la tupla.
     */
    public String getNombreArchivo() {
        return nombreArchivo;
    } 
    

    /**
     * Devuelve el numero de la tupla.
     * 
     * @return the number of this tuple in the file.
     */
    public int getNumero() {
        return numero;
    } // getNumber()

    /**
     * Sets the number of this tuple in the file.
     * 
     * @param number the new number of this tuple in the file.
     */
    public void setNumero(int number) {
        this.numero = number;
    } // setNumber()

    /**
     * Checks two tuple identifiers for equality.
     * 
     * @param o an object to compare this identifier to.
     * @return <pre>true</pre> if the two tuple identifiers are equal
     * <pre>false</pre> otherwise.
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }

        if (!(o instanceof IdentificadorTupla)) {
            return false;
        }
        IdentificadorTupla tid = (IdentificadorTupla) o;
        return getNombreArchivo().equals(tid.getNombreArchivo())
                && getNumero() == tid.getNumero();
    } // equals()

    /**
     * Computes the hashcode of this tuple identifier.
     *
     * @return this tuple identifier's hashcode.
     */
    @Override
    public int hashCode() {
        int hash = 17;
        hash = hash * 31 + getNombreArchivo().hashCode();
        return hash * 31 + getNumero();
    } // hashCode()

    /**
     * Textual representation.
     */
    @Override
    public String toString() {
        return "[" + (getNombreArchivo() != null ? getNombreArchivo() : "")
                + " - " + getNumero() + "]";
    } // toString()
}

Clase Par 
package org.taqque.almacenamiento;

/**
 * @author hernan
 *
 * Representa un par de valores.
 */

public class Par <P, S> {
    /** El primer elemento. */
    public P primero;
    /** El segundo elemento. */
    public S segundo;


    /**
     * Constructor Default.
     */
    public Par() {
        primero = null;
        segundo = null;
    }

    /**
     * Constructor de un nuevo par conociendo su primer y segundo elemento.
     *
     * @param p el primer elemento.
     * @param s el segundo elemento.
     */
    public Par(P p, S s) {
        primero = p;
        segundo = s;
    } // Par()


    /**
     * Representación Textual.
     *
     * @return Representación textual del par.
     */
    @Override
    public String toString() {
        return "(" + (primero != null ? primero : ("null"))
            + ", " + (segundo != null ? segundo : ("null")) + ")";
    } // toString()
}


Clase Convert 
package org.taqque.almacenamiento;

/**
 * @author 
 *
 * Convert: Conversión de tipos entre tipos primitivos y arreglo de bytes
 */
public class Convert {

    public static final int INT_SIZE = 4;
    public static final int LONG_SIZE = 8;
    public static final int SHORT_SIZE = 2;
    public static final int CHAR_SIZE = 2;
    public static final int FLOAT_SIZE = 4;
    public static final int DOUBLE_SIZE = 8;
    
    public Convert() {}

    public static void toByte(int i, byte [] bytes, int o) {
        for (byte b = 0; b <= 3; b++)
            bytes[o+b] = (byte) (i >>> (3 - b)*8);
    }
    
    public static byte [] toByte(int i) {
        byte b[] = new byte[4];
        toByte(i, b, 0);
        return b;
    }

    public static void toByte(short w, byte [] bytes, int o) {
        for (byte b = 0; b <= 1; b++)
            bytes[o+b] = (byte) (w >>> (1 - b)*8);
    }

    public static byte [] toByte(short w) {
        byte b[] = new byte[2];
        toByte(w, b, 0);
        return b;
    } // toByte()

    public static void toByte(long l, byte [] bytes, int o) {
        for (byte b = 0; b <= 7; b++)
            bytes[o+b] = (byte)(int) (l >>> (7 - b)*8);
    }

    public static byte [] toByte (long l) {
        byte b[] = new byte[8];
        toByte(l, b, 0);
        return b;
    } // toByte()

    public static void toByte(char c, byte [] bytes, int o) {
        for (byte b = 0; b <= 1; b++)
            bytes[o+b] = (byte) (c >>> (1-b)*8);
    }

    public static byte [] toByte (char c) {
        byte b[] = new byte[2];
        toByte(c, b, 0);
        return b;
    }

    public static void toByte(float f, byte [] bytes, int o) {
        int i = Float.floatToIntBits(f);
        toByte(i, bytes, o);
    }

    public static byte [] toByte (float f) {  
        byte b[] = new byte[4];
        toByte(f, b, 0);
        return b;
    }

    public static void toByte(double d, byte [] bytes, int o) {
        long l = Double.doubleToLongBits(d);
        toByte(l, bytes, o);
    }

    public static byte [] toByte (double d) {
        byte [] b = new byte[8];
        toByte(d, b, 0);
        return b;
    }

    public static byte [] toByte(String s) {
        byte [] b = new byte[2*s.length()];
        toByte(s, b, 0);
        return b;
    }

    public static byte [] toByte(String s, byte [] bytes, int o) {
        int length = s.length();
        for (int i = 0; i < length; i++) {
            byte [] two = toByte(s.charAt(i));
            bytes[2*i] = two[0];
            bytes[2*i+1] = two[1];
        }
        return bytes;
    }

    public static int toInt (byte b[]) {
        return toInt(b, 0);
    }

    public static int toInt (byte b[], int o) {
        int i = 0;
        for (int b0 = 0; b0 <= 3; b0++) {
            int j;
            if (b[o+b0] < 0) {
                j = (byte) (b[o+b0] & 0x7f);
                j |= 0x80;
            }
            else {
                j = b[o+b0];
            }
            i |= j;
            if (b0 < 3) i <<= 8;
        }
        return i;
    }

    public static short toShort(byte b[]) {
        return toShort(b, 0);
    }
    
    public static short toShort(byte b[], int o) {
        short word0 = 0;
        for (int b0 = 0; b0 <= 1; b0++) {
            short word1;
            if (b[o+b0] < 0) {
                word1 = (byte)(b[o+b0] & 0x7f);
                word1 |= 0x80;
            }
            else {
                word1 = b[o+b0];
            }
            word0 |= word1;
            if(b0 < 1) word0 <<= 8;
        }
        return word0;
    }
    
    public static long toLong (byte b[]) {
        return toLong(b, 0);
    }

    public static long toLong (byte b[], int o) {
        long l = 0L;
        for (int b0 = 0; b0 <= 7; b0++) {
            long l1;
            if (b[o+b0] < 0) {
                l1 = (byte)(b[o+b0] & 0x7f);
                l1 |= 128L;
            }
            else {
                l1 = b[o+b0];
            }
            l |= l1;
            if(b0 < 7) l <<= 8;
        }
        return l;
    }
    
    public static char toChar (byte b[]) {
        return toChar(b, 0);
    }
    
    public static char toChar (byte b[], int o) {
        char c = 0;
        c = (char)((c | (char)b[o]) << 8);
        c |= (char)b[o+1];
        return c;
    }
    
    public static float toFloat (byte b[]) {
        return toFloat(b, 0);
    }
    
    public static float toFloat (byte b[], int o) {
        float f = 0.0F;
        Float float1 = new Float(f);
        int i = toInt(b, o);
        f = Float.intBitsToFloat(i);
        return f;
    }
    
    
    public static double toDouble (byte b[]) {
        return toDouble(b, 0);
    }
    
    public static double toDouble (byte b[], int o) {
        double d = 0.0D;
        Double double1 = new Double(d);
        long l = toLong(b, o);
        d = Double.longBitsToDouble(l);
        return d;
    }

    public static String toString(byte [] b) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < b.length-1; i = i+2) {
            byte [] two = new byte[2];
            two[0] = b[i];
            two[1] = b[i+1];
            sb.append(toChar(two));
        }
        return sb.toString();
    } 
    }


Clase Tupla 
package org.taqque.almacenamiento;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author hernan
 */
public class Tupla {

    /** Identificador de la tupla. */
    private IdentificadorTupla idTupla;
    /** Valores almacenados en la tupla. */
    private List<Comparable> valores;

    /**
     * Constructor de una nueva <code>Tupla</code> vácia.
     */
    public Tupla() {
        this.idTupla = null;
        this.valores = new ArrayList<Comparable>();
    } // Tupla()

    /**
     * Constructor de una nueva tupla dado un identificador y  
     * <code>Lista</code> de valores.
     * 
     * @param idTupla, identificador de la tupla.
     * @param valores el valores a ser añadidos.
     */
    public Tupla(IdentificadorTupla idTupla, List<Comparable> valores) {
        this.idTupla = idTupla;
        this.valores = valores;
    } // Tupla()

    /**
     * Devolver el identificador de la tupla.
     * 
     * @return el identificador de la tupla.
     */
    public IdentificadorTupla getIdTupla() {
        return idTupla;
    } // getIdTupla()

    /**
     * Cambiar el valor de una celda de la tupla.
     * 
     * @param celda, la celda de la tupla a la que se accede.
     * @param valor, el nuevo valor en la celda de la tupla.
     */
    public void setValor(int celda, Comparable valor) {
        valores.set(celda, valor);
    } // setValor()

    /**
     * Cambia los valores de la tupla.
     * 
     * @param valores, una lista de los valores nuevos.
     */
    public void setValores(List<Comparable> values) {
        this.valores.clear();
        this.valores = values;
    } // setValores()

    /**
     * Devuelve la cantidad de celdas de la tupla.
     * 
     * @return numero de celdas en la tupla.
     */
    public int size() {
        return valores.size();
    } // size()

    /**
     * Devuelve los valores de la tupla.
     * 
     * @return valores de la tupla.
     */
    public List<Comparable> getValores() {
        return valores;
    } // getValores()

    /**
     * Devolver la celda de una tupla como tipo primitivo character.
     * 
     * @param celda, la celda de la <code>Tupla</code> accedida.
     * @return un celda específica de la tupla como un tipo primitivo
     * character.
     * 
     */
    public char asChar(int celda) {
        Character c = (Character) valores.get(celda);
        return c.charValue();
    } // asChar()

    /**
     * Devolver la celda de una tupla como tipo primitivo Byte.
     * 
     * @param celda, la celda de la <code>Tupla</code> accedida.
     * @return un celda específica de la tupla como un tipo primitivo
     * Byte.
     * 
     */
    public byte asByte(int celda) {
        Byte b = (Byte) valores.get(celda);
        return b.byteValue();
    } // asByte()

    /**
     * Devolver la celda de una tupla como tipo primitivo Short.
     * 
     * @param celda, la celda de la <code>Tupla</code> accedida.
     * @return un celda específica de la tupla como un tipo primitivo
     * Short.
     * 
     */
    public short asShort(int celda) {
        Short s = (Short) valores.get(celda);
        return s.shortValue();
    } // asShort()

    /**
     * Devolver la celda de una tupla como tipo primitivo int.
     * 
     * @param celda, la celda de la <code>Tupla</code> accedida.
     * @return un celda específica de la tupla como un tipo primitivo
     * int.
     * 
     */
    public int asInt(int celda) {
        Integer in = (Integer) valores.get(celda);
        return in.intValue();
    } // asInt()

    /**
     * Devolver la celda de una tupla como tipo primitivo Long.
     * 
     * @param celda, la celda de la <code>Tupla</code> accedida.
     * @return un celda específica de la tupla como un tipo primitivo
     * long.
     * 
     */
    public long asLong(int celda){
        Long l = (Long) valores.get(celda);
        return l.longValue();
    } // asLong()

    /**
     * Devolver la celda de una tupla como tipo primitivo float.
     * 
     * @param celda, la celda de la <code>Tupla</code> accedida.
     * @return un celda específica de la tupla como un tipo primitivo
     * float.
     * 
     */
    public float asFloat(int celda){
        Float f = (Float) valores.get(celda);
        return f.floatValue();
    } // asFloat() 

    /**
     * Devolver la celda de una tupla como tipo primitivo double.
     * 
     * @param celda, la celda de la <code>Tupla</code> accedida.
     * @return un celda específica de la tupla como un tipo primitivo
     * double.
     * 
     */
    public double asDouble(int celda){
        Double doub = (Double) valores.get(celda);
        return doub.doubleValue();
    } // asDouble() 

    /**
     * Devolver la celda de una tupla como tipo primitivo String.
     * 
     * @param celda, la celda de la <code>Tupla</code> accedida.
     * @return un celda específica de la tupla como un tipo primitivo
     * String.
     * 
     */
    public String asString(int celda) {
        String str = (String) valores.get(celda);
        return str;
    } // asString()

    /**
     * Devolver la celda especificada de la tupla como generic
     * Comparable.
     * 
     * @param celda, la celda de la <code>Tupla</code> accedida.
     * @return la celda especifica de la tupla como generic Comparable.
     */
    public Comparable getValor(int celda) {
        return valores.get(celda);
    } // getValue()

    /**
     * probar la igualdad de objetos.
     *
     * @param o objeto a comparar con la tupla.
     * @return <code>true</code> si la tupla es igual a
     * <code>o</code>, <code>false</code> caso contrario.
     */
    @Override
    public boolean equals(Object o) {

        if (o == this) {
            return true;
        }
        if (!(o instanceof Tupla)) {
            return false;
        }
        Tupla t = (Tupla) o;
        if (size() != t.size()) {
            return false;
        }
        if (!getIdTupla().equals(t.getIdTupla())) {
            return false;
        }
        int i = 0;
        for (Comparable comp : valores) {
            if (!comp.equals(t.getValor(i))) {
                return false;
            }
            i++;
        }
        return true;
    }

    /**
     * Devolver el hash code de la tupla.
     *
     * @return un hash code de la tupla.
     */
    @Override
    public int hashCode() {
        int hash = 17;
        hash += 31 * hash + getIdTupla().hashCode();
        for (Comparable comp : valores) {
            hash += 31 * hash + comp.hashCode();
        }
        return hash;
    }

    /**
     * Representación Textual.
     */
    @Override
    public String toString() {
        return idTupla.toString() + " : " + valores.toString();
    } // toString()
}


Clase GestorIOTupla 
package org.taqque.almacenamiento;

import java.util.Iterator;
import java.util.List;
import java.util.ArrayList;

import org.taqque.modelo.test.Atributo;
import org.taqque.modelo.test.Relacion;

/**
 * GestorIOTupla: Se encarga de entrada y salida de una tupla 
 * para el trabajo con paginas
 *
 * @author hernan
 */
public class GestorIOTupla {

    /** relación a la que pertenecen las tuplas. */
    private Relacion relacion;
    /** El nombre del archivo de la relación. */
    private String nombreArchivo;

    /**
     * Constructor de un nuevo gestor conociendo el esquema de la relación.
     * 
     * @param relacion, es el esquema de la relación.
     * @param nombre del archivo de la relación.
     */
    public GestorIOTupla(Relacion relacion, String nombreArchivo) {
        this.relacion = relacion;
        this.nombreArchivo = nombreArchivo;
    } // GestorIOTupla()

    /**
     * Escribir una tupla a un arreglo de byte -- esto se usará cuando
     * se gestione las tuplas en las páginas.
     * 
     * @param tupla la tupla a ser escrita.
     * @param bytes el arreglo de byte de la tupla a ser escrita.
     * @param inicio el desplazamiento inicial dentro del arreglo de bytes.
     * @return un nuevo desplazamiento en el arreglo de byte, si es -1 hay
     * problemas.
     * 
     */
    public int escribirTupla(Tupla tupla, byte[] bytes, int inicio) {
        // Escribir el id de la tupla
        byte[] b = Convert.toByte(tupla.getIdTupla().getNumero());
        System.arraycopy(b, 0, bytes, inicio, b.length);
        inicio += b.length;
        // escribir los valores de la tupla a un arreglo de bytes
        b = null;

        int celda = 0;
        for (Atributo atr : relacion) {
            inicio = volcadoDeCelda(
                    atr.getTipo(), tupla, celda++, bytes, inicio);
        }

        return inicio;
    } // escribirTupla()

    /**
     * Leer una tupla de un arreglo de bytes -- se utilizara cuando se gestione 
     * las tuplas en paginas.
     * 
     * @param bytes el arreglo de bytes.
     * @param inicio inicio del desplazamiento dentro del arreglo de bytes.
     * @return un objeto par consistiendo en la tupla leida y el nuevo 
     * desplazamiento en el arreglo de bytes.
     * 
     */
    public Par<Tupla, Integer> leerTupla(byte[] bytes, int inicio) {

        // leer el id de la tupla
        byte[] b = new byte[Convert.INT_SIZE];
        System.arraycopy(bytes, inicio, b, 0, b.length);
        int id = Convert.toInt(b);
        inicio += b.length;
        List<Comparable> valores = new ArrayList<Comparable>();
        int celda = 0;
        for (Iterator<Atributo> it = relacion.iterator();
                it.hasNext(); celda++) {
            Par<? extends Comparable, Integer> par = extraer(it.next().getTipo(), bytes, inicio);
            inicio = par.segundo;
            valores.add(par.primero);
        }
        Tupla t = new Tupla(new IdentificadorTupla(nombreArchivo, id), valores);
        return new Par<Tupla, Integer>(t, new Integer(inicio));
    } // leerTupla()

    /**
     * método base para volcar una celda de tupla a un arreglo de bytes.
     * 
     * @param tipo el tipo de la celda.
     * @param t la tupla.
     * @param s la celda de la tupla a ser volcada como arreglo de bytes.
     * @param bytes el arreglo de donde la celda será volcada.
     * @param inicio el inicio de desplazamiento.
     * @return el nuevo desplazamiento en el arreglo.
     * 
     */
    protected int volcadoDeCelda(Class<? extends Comparable> tipo, Tupla t,
            int c, byte[] bytes, int inicio) {
        if (tipo.equals(Character.class)) {
            byte[] b = Convert.toByte(t.asChar(c));
            System.arraycopy(b, 0, bytes, inicio, b.length);
            return inicio + b.length;
        } else if (tipo.equals(Byte.class)) {
            bytes[inicio] = t.asByte(c);
            return inicio + 1;
        } else if (tipo.equals(Short.class)) {
            byte[] b = Convert.toByte(t.asShort(c));
            System.arraycopy(b, 0, bytes, inicio, b.length);
            return inicio + b.length;
        } else if (tipo.equals(Integer.class)) {
            byte[] b = Convert.toByte(t.asInt(c));
            System.arraycopy(b, 0, bytes, inicio, b.length);
            return inicio + b.length;
        } else if (tipo.equals(Long.class)) {
            byte[] b = Convert.toByte(t.asLong(c));
            System.arraycopy(b, 0, bytes, inicio, b.length);
            return inicio + b.length;
        } else if (tipo.equals(Float.class)) {
            byte[] b = Convert.toByte(t.asFloat(c));
            System.arraycopy(b, 0, bytes, inicio, b.length);
            return inicio + b.length;
        } else if (tipo.equals(Double.class)) {
            byte[] b = Convert.toByte(t.asDouble(c));
            System.arraycopy(b, 0, bytes, inicio, b.length);
            return inicio + b.length;
        } else if (tipo.equals(String.class)) {
            String st = t.asString(c);
            int len = st.length();
            byte[] b = Convert.toByte(len);
            System.arraycopy(b, 0, bytes, inicio, b.length);
            inicio += b.length;
            b = Convert.toByte(st);
            System.arraycopy(b, 0, bytes, inicio, b.length);
            return inicio + b.length;
        } else {
            System.err.println("No soporta el tipo: " + tipo.getClass().getName());
            return -1;
        }
    } // volcadoDeCelda()

    /**
     * Método básico para leer una celda de un arreglo de byte.
     * 
     * @param tipo el tipo de la celda a leer.
     * @param bytes el arreglo de bytes como entrada.
     * @param inicio el desplazamiento inicial en el arreglo de bytes.
     * @return un par de (valor, desplazamiento) con el valor leido y el nuevo
     * desplazamiento en el arreglo de bytes.
     * 
     */
    protected Par<? extends Comparable, Integer> extraer(Class<? extends Comparable> tipo, byte[] bytes, int inicio) {
        try {
            if (tipo.equals(Character.class)) {
                byte[] b = new byte[Convert.CHAR_SIZE];
                System.arraycopy(bytes, inicio, b, 0, b.length);
                return new Par<Character, Integer>(
                        new Character(Convert.toChar(b)),
                        inicio + b.length);
            } else if (tipo.equals(Byte.class)) {
                return new Par<Byte, Integer>(bytes[inicio],
                        inicio + 1);
            } else if (tipo.equals(Short.class)) {
                byte[] b = new byte[Convert.SHORT_SIZE];
                System.arraycopy(bytes, inicio, b, 0, b.length);
                return new Par<Short, Integer>(new Short(Convert.toShort(b)),
                        inicio + b.length);
            } else if (tipo.equals(Integer.class)) {
                byte[] b = new byte[Convert.INT_SIZE];
                System.arraycopy(bytes, inicio, b, 0, b.length);
                return new Par<Integer, Integer>(new Integer(Convert.toInt(b)),
                        inicio + b.length);
            } else if (tipo.equals(Long.class)) {
                byte[] b = new byte[Convert.LONG_SIZE];
                System.arraycopy(bytes, inicio, b, 0, b.length);
                return new Par<Long, Integer>(new Long(Convert.toLong(b)),
                        inicio + b.length);
            } else if (tipo.equals(Float.class)) {
                byte[] b = new byte[Convert.FLOAT_SIZE];
                System.arraycopy(bytes, inicio, b, 0, b.length);
                return new Par<Float, Integer>(new Float(Convert.toFloat(b)),
                        inicio + b.length);
            } else if (tipo.equals(Double.class)) {
                byte[] b = new byte[Convert.DOUBLE_SIZE];
                System.arraycopy(bytes, inicio, b, 0, b.length);
                return new Par<Double, Integer>(
                        new Double(Convert.toDouble(b)),
                        inicio + b.length);
            } else if (tipo.equals(String.class)) {
                byte[] b = new byte[Convert.INT_SIZE];
                System.arraycopy(bytes, inicio, b, 0, b.length);
                inicio += b.length;
                int stLength = Convert.toInt(b);
                b = new byte[2 * stLength];
                System.arraycopy(bytes, inicio, b, 0, b.length);
                String str = Convert.toString(b);
                return new Par<String, Integer>(str, inicio + b.length);
            } else {
                return null;
            }
        } catch (ArrayIndexOutOfBoundsException aiob) {
            return null;
        }
    } // extraer()

    /**
     * Calcular el tamaño de bytes de la tupla.
     *
     * @param t la tupla.
     * @return el tamaño de byte de la tupla.
     */
    public int byteSize(Tupla t) {
        return byteSize(relacion, t);
    }

    /**
     * Calcular el tamaño en byte de una tupla dada su relación.      
     *
     * @param rel la relación.
     * @param t la tupla.
     * @return el tamaño en byte de la tupla.
     */
    public static int byteSize(Relacion rel, Tupla t) {
        // una longitud para el id
        int size = Convert.INT_SIZE;
        int celda = 0;
        for (Atributo it : rel) {
            Class<?> tipo = it.getTipo();
            if (tipo.equals(Character.class)) {
                size += Convert.CHAR_SIZE;
            } else if (tipo.equals(Byte.class)) {
                size += 1;
            } else if (tipo.equals(Short.class)) {
                size += Convert.SHORT_SIZE;
            } else if (tipo.equals(Integer.class)) {
                size += Convert.INT_SIZE;
            } else if (tipo.equals(Long.class)) {
                size += Convert.LONG_SIZE;
            } else if (tipo.equals(Float.class)) {
                size += Convert.FLOAT_SIZE;
            } else if (tipo.equals(Double.class)) {
                size += Convert.DOUBLE_SIZE;
            } else if (tipo.equals(String.class)) {
                size += Convert.INT_SIZE + 2 * t.asString(celda).length();
            }

            celda++;
        }

        return size;
    } // byteSize()

    /**
     * Debug main.
     */
    public static void main(String args[]) {
        try {
            List<Atributo> attrs = new ArrayList<Atributo>();
            attrs.add(new Atributo("character", Character.class));
            attrs.add(new Atributo("byte", Byte.class));
            attrs.add(new Atributo("short", Short.class));
            attrs.add(new Atributo("integer", Integer.class));
            attrs.add(new Atributo("long", Long.class));
            attrs.add(new Atributo("float", Float.class));
            attrs.add(new Atributo("double", Double.class));
            attrs.add(new Atributo("string", String.class));
            Relacion rel = new Relacion(attrs);

            List<Comparable> v = new ArrayList<Comparable>();
            v.add(new Character('a'));
            v.add(new Byte((byte) 26));
            v.add(new Short((short) 312));
            v.add(new Integer(2048));
            v.add(new Long(34567));
            v.add(new Float(12.3));
            v.add(new Double(25.6));
            v.add(new String("bla bla"));
            Tupla t = new Tupla(new IdentificadorTupla("redes", 0), v);
            GestorIOTupla man = new GestorIOTupla(rel, "redes");

            java.io.RandomAccessFile raf = new java.io.RandomAccessFile("redes", "rw");

            System.out.println("writing tuple..." + t);
            byte[] bytes = new byte[1024];
            //man.escribirTupla(t, raf);
            man.escribirTupla(t, bytes, 0);
            raf.close();

            raf = new java.io.RandomAccessFile("redes", "r");
            System.out.println("reading tuple...");
            // t = man.leerTupla(bytes);
            Par<Tupla, Integer> st = man.leerTupla(bytes, 0);
            System.out.println(st);
            raf.close();
        } catch (Exception e) {
            System.err.println("Exception: " + e.getMessage());
            e.printStackTrace(System.err);
        }
    } // main()
} // GestorIOTupla


IV) TAREA:
1) Representar el esquema de la relación Esquema_Cliente = (id_cliente, nombre_cliente, direccion_cliente, telefono_cliente), donde:
id_cliente tiene dominio de valores enteros,
nombre_cliente tiene dominio de valores de cadena de caracteres,
direccion_cliente tiene dominio de valores de cadena de caracteres,
telefono_cliente tiene dominio de valores entero largo.

Seguidamente, muestre el esquema creado en pantalla. Modifique el esquema de tal manera que se añada un nuevo atributo denominado tipo_cliente con dominio de valores de tipo carácter luego muéstrelo en pantalla. Finalmente modifique nuevamente el esquema para eliminar el atributo telefono_cliente y luego muestre el esquema resultante.
2) Utilizando las Clases de Software implementado en la Gestión de Tuplas, desarrolle una aplicación para realizar cualquier Esquema de Relación, donde se pueda ingresar "n" tuplas las cuales deben ser escritas en una array de bytes y recuperadas del mismo array.
3) Implemente un gestor de Paginas donde puede almacenar tuplas de una relación en el Disco. puede considerar el tamaño de las páginas en 4k. las páginas están almacenadas en un archivo de disco.


V) REFERENCIAS BIBLIOGRÁFICAS

Laboratorio 0004: Gestión de la Memoria Intermedia

publicado a la‎(s)‎ 28 may. 2012 19:41 por Hernan Nina Hanco   [ actualizado el 4 jun. 2013 8:41 ]

I) Objetivo

  • Implementar una abstracción básica de la Gestión de la Memoria Intermedia como parte de la arquitectura de un Sistema de Gestión de Base de Datos.


II) Marco conceptual

Gestión de la memoria intermedia:

El sistema de base de datos fórmula solicitudes al gestor de la memoria intermedia cuando necesitan bloques de disco. Si el bloque ya esta en la memoria intermedia el gestor envía la dirección de memoria del bloque. Si el bloque no se halla en la memoria intermedia, el gestor de la memoria intermedia asigna en primer lugar espacio al bloque en la memoria intermedia, descartando algún otro bloque si hace falta para hacer sitio para el nuevo bloque. Sólo se vuelve a escribir en el disco el bloque que se descarta si se modificó desde la última vez que se escribió en el disco. A continuación, el gestor de la memoria intermedia lee el bloque del disco y lo escribe en la memoria intermedia, y pasa la dirección del bloque en la memoria principal al solicitante.


LRU:

Estrategía de sustitución en el que se vuelve a escribir en el disco y se elimina de la memoria intermedia el bloque al que se ha hecho referencia menos recientemente.

Página:

Representa un bloque de un disco, que corresponde a las unidades de asignación de almacenamiento en un proceso de acceso a disco. una Página puede contener varios datos o registros de una base de datos.


Más referencia de la teoría en el documento Guía Universitaria de Sistemas de Bases de Datos II sección 1.5 Acceso al almacenamiento.


III) Practicas


Práctica 1) Implementar un Gestor de la Memoria Intermedia.

Se presenta dos clases, la Clase Pagina que representa a un bloque de disco. Luego esta la clase GestorMemoriaIntermedia este representa al gestor de memoria intermedia basado en la estrategía de sustitución LRU.


Clase Pagina


/*

* Creado el 28 de mayo, 2012 por Hernán Nina Hanco

*

* Este trabajo es parte del proyecto Taqque, que corresponde a la

* implementación de un Sistema de Gestión de Base de Datos. Cualquier

* cambio es necesario declararlo en este apartado.

*

* Universidad Nacional de San Antonio Abad del Cusco

* Carrera Profesional de Ingeniería Informática y de Sistemas

* Asignatura: Sistemas de Bases de Datos II

*/


package org.taqque.memoriaintermedia;


/**

* Pagina: Representa un bloque de Disco donde se almacenan los archivos de

* la base de datos

*

* @author hernan

*/

public class Pagina<T> {

   /** Identidicador de la página en el disco. */

   private int numeroPagina;

   /** Datos almacenados en el bloque. */

   private T datos;

   

   /**

    * Crea una nueva pagina conociendo su id de pagina y los datos.

    *

    * @param numeroPagina el ID de esta página.

    * @param datos datos almacenados en esta página.

    */

   

   public Pagina(int numeroPagina, T datos) {

       this.numeroPagina = numeroPagina;

       this.datos = datos;

   }


   public T getDatos() {

       return datos;

   }


   public void setDatos(T datos) {

       this.datos = datos;

   }


   public int getNumeroPagina() {

       return numeroPagina;

   }


   public void setNumeroPagina(int numeroPagina) {

       this.numeroPagina = numeroPagina;

   }

   

   /**

    * Devuelde una representación textual de una página.

    *

    * @return representación textual de esta página.

    */

   @Override

   public String toString()

   {

       return "Numero de Pagina: "+this.numeroPagina + "\t" +

               "Dato de pagina: " + this.datos;

   }

}


Clase GestorMemoriaIntermedia

/*
* Creado el 28 de mayo, 2012 por Hernán Nina Hanco
*
* Este trabajo es parte del proyecto Taqque, que corresponde a la
* implementación de un Sistema de Gestión de Base de Datos. Cualquier
* cambio es necesario declararlo en este apartado.
*
* Universidad Nacional de San Antonio Abad del Cusco
* Carrera Profesional de Ingeniería Informática y de Sistemas
* Asignatura: Sistemas de Bases de Datos II
*/
package org.taqque.memoriaintermedia;

import java.util.LinkedList;
import java.util.Queue;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Representa una abstracción de un Gestor de la Memoria Intermedia
*
* @author hernan
*/
public class GestorMemoriaIntermedia {

   static final Logger logger = Logger.getLogger("Gestion de Buffer");
   /** Representa a los bloques de la memoria intermedia o buffer. */
   private Pagina[] buffer;
   /** Numero de paginas en total en el buffer. */
   private int numeroPaginas;
   /** Posición en el buffer de la ultima pagina colocada. */
   private int posicionUltimaPagina = -1;
   /** cola para el control de sustitución basada en LRU. */
   private Queue colaLRU;

   /**
    * Crea un nuevo Gestor de memoria intermedia.
    *
    * @param numeroPaginas cantidad de paginas en total en el buffer.
    */
   public GestorMemoriaIntermedia(int numeroPaginas) {
       this.numeroPaginas = numeroPaginas;
       // Crear el buffer con paginas vacias
       buffer = new Pagina[numeroPaginas];
       // Crear una cola FIFO
       colaLRU = new LinkedList<Integer>();
   }

   /**
    * Devuelve una pagina conociendo el numero de la página.
    *
    * @param numeroPagina el id de la pagina que queremos devolver
    * @return la página del id de pagina proporcionado.
    */
   public Pagina recuperarPaginaDelBuffer(int numeroPagina) {
       // Verificar si la pagina esta en el buffer
       int posicion = posicionDePaginaEnBuffer(numeroPagina);
       if (posicion >= 0) // la pagina esta en el buffer
       {
           // Marcar Pagina o bloque como recientemente referenciado
           colaLRU.remove(numeroPagina);
           colaLRU.add(numeroPagina);
           // devolver la pagina del buffer al solicitante
           return buffer[posicion];
       }
       return null;
   }

   /**
    * Poner una pagina en el buffer de la memoria intermedia.
    *
    * @param pagina la pagina a ser insertado en el buffer.
    * @return la pagina que sera descartada del buffer si es necesario.
    */
   public Pagina ponerPaginaEnBuffer(Pagina pagina) {
       // Si la pagina esta en el buffer
       if (estaPaginaEnBuffer(pagina)) {
           // no descartar ninguna pagina o bloque
           return null;
       } // Si la pagina no esta en el buffer, pero con espacio en el buffer
       else if (!bufferLLeno()) {
           // Asignar la nueva pagina al bloque o pagina libre del buffer
           posicionUltimaPagina++;
           buffer[posicionUltimaPagina] = pagina;
           // Actualizar la LRU
           colaLRU.remove(posicionUltimaPagina);
           colaLRU.add(posicionUltimaPagina);
           return null;
       } // Si la pagina no esta en el buffer, pero sin espacio en el buffer
       else {
           // recuperar la pagina a descartar
           int numeroPaginaDescartada = (Integer) colaLRU.remove();
           int posicion = posicionDePaginaEnBuffer(numeroPaginaDescartada);
           Pagina paginaDescartada = buffer[posicion];
           buffer[posicion] = pagina;
           colaLRU.add(pagina.getNumeroPagina());
           return paginaDescartada;
       }

   }

   private int posicionDePaginaEnBuffer(int numeroPagina) {
       int posicion = -1;
       for (int i = 0; i < buffer.length; i++) {
           if ((buffer[i] != null)
                   && (numeroPagina == buffer[i].getNumeroPagina())) {
               posicion = i;
               break;
           }
       }
       return posicion;

   }

   private boolean estaPaginaEnBuffer(Pagina pagina) {
       return (posicionDePaginaEnBuffer(pagina.getNumeroPagina()) != -1);
   }

   private boolean bufferLLeno() {
       return numeroPaginas - 1 == posicionUltimaPagina;
   }

   @Override
   public String toString() {
       String resultado = "";
       for (int i = 0; i < buffer.length; i++) {
           resultado += "Pagina[" + i + "]: " + buffer[i] + "\n";
       }
       return resultado + "\n" + this.colaLRU;
   }

   public static void main(String[] args) {
       // Crear un gestor de memoria
       GestorMemoriaIntermedia gestorBuffer = new GestorMemoriaIntermedia(6);
       // Paginas del Disco
       System.out.println("Paginas del Disco: ");
       Pagina[] paginas = new Pagina[10];
       for (int i = 0; i < paginas.length; i++) {
           Pagina pagina = new Pagina(i, "p" + i);
           paginas[i] = pagina;
           System.out.println(pagina);
       }

       System.out.println("Contenido del Gestor: ");
       System.out.println(gestorBuffer);


       for (int i = 0; i < paginas.length; i++) {
           gestorBuffer.ponerPaginaEnBuffer(paginas[i]);
       }

       System.out.println("Contenido del Gestor despues de poner bloques: ");
       System.out.println(gestorBuffer);

       System.out.println("Poner una página al Buffer: ");
       Pagina paginaN = new Pagina(10,"p10");
       Pagina paginaE = gestorBuffer.ponerPaginaEnBuffer(paginaN);
       System.out.println(paginaE);
       System.out.println(gestorBuffer);
       
       
       
       System.out.println("Recuperar una Pagina del Buffer: ");
       Pagina pagina1 = gestorBuffer.recuperarPaginaDelBuffer(7);
       System.out.println(pagina1);
       System.out.println(gestorBuffer);

       System.out.println("Recuperar otra Pagina del Buffer: ");
       Pagina pagina2 = gestorBuffer.recuperarPaginaDelBuffer(1);
       System.out.println(pagina2);
       System.out.println(gestorBuffer);
   }
}

El código del proyecto se encuentra en: 
http://code.google.com/p/taqque/


IV) Tarea

1. Modificar las implementaciones de la práctica, para poder conocer si una página fue modificada en la memoria intermedia y por lo tanto es necesario escribir en disco duro.

2. Modificar la implementación de la práctica para soportar bloques clavados.

3. Modificar las implementaciones de la práctica para resolver la operación:

prestatario |x| cliente

Utilizando las mejores estrategias de MRU y LRU.

Nota.- Para elaborar los trabajos crear un paquete tarea.memoriaintermedia en el trunk del proyecto de code google hosting.

V) Referencias

  • Guía universitaria Sistemas de Gestión de Bases de Datos II

Laboratorio 0000: Detalles de Herramientas de Desarrollo en la Asignatura

publicado a la‎(s)‎ 23 abr. 2012 11:53 por Hernan Nina Hanco   [ actualizado el 4 jun. 2013 13:51 ]

Podcast



I) Objetivos

  • Describir la herramienta de desarrollo a utilizar en la asignatura

II) Marco conceptual


En la presente entrada, se describe en detalle las herramientas de desarrollo utilizadas en la presente asignatura. Para una mejor comunicación y colaboración se ha elegido a Google Hosting Code, como repositorio de código para las aplicaciones escritas en la asignatura, para acceder a este servicio se debe disponer una cuenta de gmail.


Así mismo como IDE para escribir código se elije Netbeans o Eclipse con lenguaje Java. Se elije Java por ser uno de los lenguajes mas popularmente utilizados y ser orientado a Objetos.


Nota.- Existe la libertad de elegir cualquier otro Lenguaje Orientado a Objetos con la posibilidad de gestión de control de versión, Sin embargo, lamentablemente solo se brindara información en base a las herramientas propuestas en la asignatura.


Consultas y preguntas solamente en el grupo: unsaacbd220121@googlegroups.com

Para subscribirse al grupo envié un mail al correo del grupo sin asunto o texto.


Indicaciones
  • Creación de Google Code Hosting
    • Cada estudiante debe habilitar su Google Code Hosting inicialmente ingresando a su cuenta de gmail.
    • Luego, Ingrese a la siguiente dirección:  http://code.google.com/hosting/
    • Complete los datos del Formulario: Nombre del Proyecto, Resumen del proyecto, Descripción, Sistema de control de Versiones (Recomendado Subversion), Licencia de código fuente (Recomendado GNU GPL v2), Etiquetas del proyecto (Recomendado Academic, Java, Database)
    • Una vez creado el proyecto, comparte el proyecto inicialmente con el docente de práctica cuya dirección es la siguiente: (hanconina@nubeuniversitaria.com ó hanconina@gmail.com), puedes compartir accediendo al menú "Administer", luego elije "Sharing", en el cuadro de "Project owners" añade la dirección del docente de practica. no se olvide de Guardar los cambios.
  • Datos para el acceso y gestión de código desde el hosting
    • El el hosting de google, ir al menú "Source" y luego copiar la URL para checkout del código:
      • Ejm.
                    # Project members authenticate over HTTPS to allow committing changes.
                    svn checkout https://taqque.googlecode.com/svn/trunk/ taqque --username hanconina@nubeuniversitaria.com
                                   When prompted, enter your generated googlecode.com password.
    • Tomar en cuenta los datos marcados de rojo URL del repositorio de código y nombre de usuario
    • Finalmente generar el password para acceso al repositorio desde Netbeans o Eclipse haciendo click el enlace:  googlecode.com password  anota el password generado.
  • Manejo de Control de Versiones con Google Code y NetBeans o Eclipse
    • En Netbeans: asegurarse de tener instalado svnclient como referencia de la instalación puede ver en http://netbeans.org/kb/docs/ide/subversion.html ó ver archivos adjuntos (Recomendado). 
    • Una vez instalado el subversión crear un nuevo proyecto de aplicación Java en netbeans.
    • Una vez creado el proyecto en Netbeans se debe importar él mismo donde se utilizara los datos identificados en el apartado anterior.
      • Para Netbeans Click derecho en el proyecto y luego seleccionar "versioning" seguido de "Import into Subversion Repository ..." Luego siga el asistente
      • Ejemplo:
 

III) Practicas de laboratorio
  1. Desarrolle una aplicación para crear un registro de datos de personas utilizando como repositorio el Google Hosting Project y un IDE para java de su preferencia. 

1-10 of 10