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
|
DOCENCIA UNIVERSITARIA > Sistemas de Bases de Datos II > Laboratorio de Sistemas de Bases de Datos II >