Laboratorio de Sistemas de Bases de Datos II
Laboratorio 0009: Aplicaciones con modelos semiestructurados XML
I) OBJETIVOS
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
|
Laboratorio 0008: Aplicaciones con transacciones
I) OBJETIVOS
Ver Guía de la Asignatura III) PRÁCTICAS DE LABORATORIO /*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 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
|
Laboratorio 0007: Aplicaciones de Índices
I) OBJETIVOS
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
|
Laboratorio 0006: Indices de Árboles B+
I) OBJETIVOS
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
|
Laboratorio 0005: Gestión de Almacenamiento y de Relación
I) OBJETIVOS
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
|
Laboratorio 0001: Almacenamiento con diccionario de datos o Catalogo del sistema
I) OBJETIVOS
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
V) Refeerencias
|
Laboratorio 0003: Gestión de páginas
I) OBJETIVOS
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) 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:
|
Laboratorio 0002: Gestión de Tuplas
I) OBJETIVOS
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
I) Objetivo
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
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
|
Laboratorio 0000: Detalles de Herramientas de Desarrollo en la Asignatura
I) Objetivos
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
svn checkout https://taqque.googlecode.com/svn/trunk/ taqque --username hanconina@nubeuniversitaria.com When prompted, enter your generated googlecode.com password.
|