sábado, 26 de marzo de 2011

Tablas de símbolos , manejo de errores sintácticos y su recuperación.


= Tabla de Símbolos =
Tabla de Símbolos:
Estructura utilizada por el compilador para almacenar información(atributos) asociada a los símbolos declarados en el programa en compilación.
Puede contener adicionalmente:
–símbolos temporales
–etiquetas
–símbolos predefinidos
Conceptualmente: colección de registros
Estructura fuertemente influenciada por aspectos sintácticos y semánticos del lenguaje: Código
Los tipos disponibles en el lenguaje: determinan el CONTENIDO de la tabla.
Las reglas de ámbito: determinan la visibilidad de los símbolos, e.g., el MECANISMO DE ACCESO a la tabla.
= Contenido de la tabla =
Palabras reservadas:tienen un significado especial; NO pueden ser redefinidas.program beginend type vararrayif...
Símbolos predefinidos: Tienen un significado especial, pero pueden ser redefinidos.
•Literales, constantes que denotan un valor
var a:
record
b,c : integer;
end;
Símbolos generados por el compilador:
-Genera el símbolo noname1 para el tipo anónimo correspondiente al registro.
•Símbolos definidos por el programador.
Variables: tipo, lugar en memoria, ¿valor? ¿referencias?.
Tipos de datos : descripción.
Procedimientos y funciones: dirección, parámetros, tipo de resultado.
Parámetros: tipo de variable, clase de parámetro.
Etiquetas: lugar en el programa.
El contenidos de las tablas de símbolos. Operaciones y organización. Atributos, lenguajes no estructurados y estructurados en bloques, representación OO de símbolos y tipos en compiladores de una pasada.
= Administración de la tabla de símbolos =
El análisis semántico conecta las definiciones de las variables con sus usos, checa que cada expresión tenga un tipo correcto y traduce la sintaxis abstracta a una representación mas simple para generar código maquina.
Esta fase es caracterizada por el mantener la tabla de símbolos, la cual mapea identificadores con sus tipos y localidades, también esta tabla puede ser llamada environment, donde cada variable local en un programa tiene un ámbito o scope dentro del cual es visible.
Un ambiente es un conjunto de atados denotados por à.
= Manejo de errores semánticos =
Cuando el checador de tipos detecta un error de tipos o un identificador no declarado, debe imprimir el mensaje de error y continuar.
Esto debido a que normalmente el programador prefiere que le describan todos los errores posibles del programa fuente.
Esto quiere decir, que si un error de tipos es encontrado, no debe producirse un programa objeto por parte del compilador.
Así, las siguientes fases no deben ejecutarse.
Hasta esta etapa (chequeo de tipos), la parte del compilador se conoce con el nombre de “front End”.
REGISTROS DE ACTIVACION
En casi cualquier LP, una función (método) puede tener variables locales que son creadas cuando se llama la función (al entrar a esta).
Diferentes invocaciones a la función pueden existir a la vez, y cada invocación tiene su propia “instanciación” de variables.
En el siguiente método de Java
Int f(int x) {
int y= x+x;
if (y<10)
return f(y);
else
return y-1;
Una nueva instancia de x es creada (e inicializada por el llamador de “f”) cada vez que “f” es llamada. Debido a que existen llamadas recursivas, muchas de esas x existen simultáneamente. Similarmente, una nueva instancia de y es creada cada vez que el cuerpo f es iniciado.
En muchos LP (incluyendo Pascal, C y java), las variables locales son destruidas cuando una función retorna. Ya que las variables locales son creadas y destruidas en una forma LIFO, podemos usar una pila para manejarlas.
• Si los traductores tuvieran que procesar programas
correctas el proceso de implantación se
simplificaría mucho.
• ¿Cómo debe de responder un compilador de
pascal a un código Fortran?
• Ningún método de recuperación de errores
resuelve todos los problemas
Tipos de errores
• Léxicos: como escribir mal un identificador, palabra
clave u operador.
• Sintácticos: como una expresión aritmética con
paréntesis no equilibrados.
• Semánticos: como un operador aplicado a un
operadorando incompatible.
• Lógicos: como una llamada infinitamente recursiva
• La mayoría de los errores se centra en la
fase de análisis sintáctico.
• El manejador de errores debe:
• Informar la presencia de errores con claridad
y exactitud.
Administrador de errores
• Recuperar de cada error con la suficiente
rapidez como para detectar errores posibles.
• No debe retrasar de manera significativa el
procesamiento de programas correctos.
• Debe indicar la línea del error y algún
mensaje informativo
Estrategias de recuperación de
errores
• Modo Pánico
• Nivel de Frase
• Producciones de error
• Corrección global
Recuperación en modo pánico
• Es el más sencillo de implantar.
• El analizador sintáctico desecha
componentes léxicos hasta encontrar un
carácter de sincronización. Estos caracteres
son el punto y como (;) entre otros.
int a.b,c;
struct c {
….
}
main()
{
int a;
}
Recuperación a nivel de frase
• Esta técnica utiliza una corrección de
caracteres adyacentes, ya sea por inserción,
eliminación o intercambio.
• Esta técnica permite sustituir , por ;, etc. Son
traductores que corrigen errores.
Desafortunadamente para muchos casos no
aplican por lo que no se utilizan demasiados.
Producciones de error
• Se pueden generar gramáticas para generar
producciones de error y así de esta forma seguir
con el proceso.
• La dificultad radica en el sentido de encontrar esas
reglas gramaticales para generar error. En algunos
casos sería inclusiva más extensa que la gramática
del propio lenguaje.
• for(i<3, a<10; i++)
Corrección global
• Idealmente, sería recomendable que un
traductor hiciera el mínimo de cambios para
procesar una entrada inválida. Este algoritmo
genera menores costos globales para
realizar cambios.
• El problema radica en que el implementar
estas estrategias son muy costosas en
tiempo y espacio.
= Generadores de código para analizadores sintácticos = YACC/BISON
• YACC (YET ANOTHER COMPILERCOMPILER):
provee una herramienta
general para describir la entrada de un programa de computación.
El usuario de YACC especifica las estructuras de su entrada, junto con el código que será invocado en la medida en que cada una de
esas estructuras es reconocida.
YACC convierte esa especificación en una subrutina que maneja el proceso de entrada.
• La subrutina de entrada producida por YACC llama a la rutina provista por el usuario para devolver el próximo ítem básico de la entrada.
GNU Bison es un generador de parsers de propósito general que convierte una descripción gramatical desde una gramática libre de contexto LALR en un programa en C para hacer el parser.
• Es utilizado para crear parsers para muchos lenguajes, desde simples calculadoras hasta lenguajes complejos.
GNU Bison tiene compatibilidad con Yacc:
todas las gramáticas bien escritas para Yacc, funcionan en Bison sin necesidad de ser modificadas.
• Cualquier persona que esté familiarizada con Yacc podría utilizar Bison sin problemas.
Es necesaria experiencia con C para utilizar Bison
• Yet Another Compiler-Compiler
• Analizador.y (#include “lex.yy.c”) bison
analizador.c (y.tab.c) gcc analizador
• $gcc analizador.c –o analizador -lfl
Estructura de un programa en Bison
%{
Declaraciones globales C
}%
Declaraciones bison
%%
Gramáticas
Nombre:prod1|prod2|…|prodn;
%%
Código auxiliar C
Tips
• Todo lexema debe ser un entero
#define VAR 200 (256)
return (VAR);
Gramática vacía
Gramática: prod1|
prod2|
;

Autor: Luis Eduardo Fernandez Rocha (Contacto Linkedin)

= R a k n A r r o K =

Introducción a Transacciones.

=Introducción=
Desde el punto de vista del usuario la interacción con la base de datos se lleva a cabo mediante operaciones con significado en el modelo semántico (por ejemplo, una transferencia de fondos en un banco)
Desde el punto de vista de la base de datos estas operaciones pueden estar formadas por varias operaciones elementales (por ejemplo, quitar fondos de una cuenta y añadírselos a otra).
Se llama Transacción a una colección de operaciones que forman una unidad lógica de trabajo. Una Transacción es un unidad de la ejecución de un programa que accede y, posiblemente, actualiza varios elementos de datos.
Una Transacción está delimitada por instrucciones de inicio transacción y fin transacción (la transacción consiste en todas las operaciones que se ejecutan entre inicio transacción y fin transacción).
=Concepto de transacción=
Como ya se había comentado anteriormente una Transacción es una unidad de la ejecución de un programa que accede y, posiblemente, actualiza varios elementos de datos.
Una Transacción está delimitada por instrucciones de inicio transacción y fin transacción (la transacción consiste en todas las operaciones que se ejecutan entre inicio transacción y fin transacción).
=Propiedades de una Transacción=
Propiedades de las transacciones que debe mantener el sistema de base de datos para garantizar la integridad de los datos.
Atomicidad: O se realizan adecuadamente, en la base de datos, todas las operaciones de la transacción o no se realiza ninguna de ellas.
Antes de ejecutar Ti: El valor de A es 1000€ y el valor de B es 2000€, durante la ejecución de Ti: Se produce un fallo que impide que la transacción finalice con éxito (fallos de alimentación, fallos de hardware, errores software, etc.)
Ti: leer(A);
A := A - 50;
escribir(A);
leer(B);
B := B + 50;
escribir(B);
Valores reflejados en la Base de Datos:
El valor de A es 950€ y el valor de B es 2000€.
El estado del sistema deja de reflejar el estado real del mundo que se supone que modela à estado inconsistente.
Inconsistente:
Hay que asegurarse que las inconsistencias no sean visibles en un sistema de base de datos, un sistema puede alcanzar en algún momento un estado inconsistente àIncluso si Ti se ejecuta completamente existe un momento en que la base de datos está en
estado inconsistente los estados inconsistentes sólo deben aparecen durante la ejecución de la transacciones la responsabilidad de asegurar la atomicidad es del sistema de base de datos (en concreto del componente de gestión de transacciones)
Consistencia:
La ejecución aislada de la transacción (es decir, sin otra transacción que se ejecute concurrentemente) conserva la consistencia de la base de datos.
El requisito de consistencia es que la suma de A y B no se vea alterada al ejecutar la transacción Si una base de datos es consistente antes de ejecutar una transacción, tiene que seguir siéndolo después de ejecutar dicha transacción.
La responsabilidad de asegurar la consistencia es del
programador que codifica la transacción (la comprobación
de las restricciones de integridad puede ayudar)
Aislamiento: Aunque se ejecuten varias transacciones concurrentemente, el sistema garantiza cada transacción ignora al resto de transacciones (para cada Ti el resto de Tj no ha comenzado o ya ha acabado) incluso tras asegurar las propiedades de atomicidad
y consistencia para cada transacción pueden ocurrir problemas si varias transacciones concurrentes entrelazaran sus operaciones de modo no deseado (produciendo un estado inconsistente)
Ti: leer(A);
A := A - 50;
escribir(A);
leer(B); ß una segunda transacción que modifique A y/o B (a porcentaje)
B := B + 50;
escribir(B);
una segunda transacción que
modifique A y/o B (a porcentaje)
La Base de Datos puede quedar en un estado inconsistente aunque las dos transacciones terminen.
Durabilidad:
Tras la finalización con éxito de una transacción, los cambios realizados en la base de datos permanecen, incluso si hay fallos en el sistema.
-------------------------CONDICIONES-------------------------
Una vez que se completa con éxito la ejecución de una transacción no puede suceder que un fallo del sistema produzca la pérdida de datos.
1.- Las modificaciones realizadas por la transacción se guardan en disco antes de finalizar la transacción.
2.- La información guardada en disco de las modificaciones realizadas por transacción es suficiente para reconstruir dichas modificaciones Condiciones.
La responsabilidad de asegurar la durabilidad es del sistema de base de datos (en concreto del componente de gestión de recuperaciones)
Ejemplos de propiedades.
Sistema Bancario simplificado:
-Constituido por varias cuentas y un conjunto de transacciones que acceden y actualizan dichas cuentas.
-Base de datos residente en disco pero con una porción de la misma
en memoria principal.
-Acceso a través de dos operaciones: leer(X) y escribir(x) (transfiere el dato X desde la Base de Datos/memoria intermedia local de la transacción a una memoria intermedia local de la transacción/Base de Datos)
=Niveles de aislamiento de una transacción=
Las transacciones especifican un nivel de aislamiento que define el grado en que se debe aislar una transacción de las modificaciones de recursos o datos realizadas por otras transacciones. Los niveles de aislamiento se describen en cuanto a los efectos secundarios de la simultaneidad que se permiten, como las lecturas desfasadas o ficticias.
Control de los niveles de aislamiento de transacción:
  • Controla si se realizan bloqueos cuando se leen los datos y qué tipos de bloqueos se solicitan.
  • Duración de los bloqueos de lectura.
  • Si una operación de lectura que hace referencia a filas modificadas por otra transacción:
    • Se bloquea hasta que se libera el bloqueo exclusivo de la fila.
    • Recupera la versión confirmada de la fila que existía en el momento en el que empezó la instrucción o la transacción.
    • Lee la modificación de los datos no confirmados.
El estándar ANSI/ISO SQL define cuatro niveles de aislamiento transaccional en función de tres eventos que son permitidos o no dependiendo del nivel de aislamiento. Estos eventos son:
Lectura sucia. Las sentencias SELECT son ejecutadas sin realizar bloqueos, pero podría usarse una versión anterior de un registro. Por lo tanto, las lecturas no son consistentes al usar este nivel de aislamiento.
  • Lectura norepetible. Una transacción vuelve a leer datos que previamente había leído y encuentra que han sido modificados o eliminados por una transacción cursada.
  • Lectura fantasma. Una transacción vuelve a ejecutar una consulta, devolviendo un conjuto de registros que satisfacen una condición de búsqueda y encuentra que otros registro que satisfacen la condición han sido insertadas por otra transacción cursada.
Los niveles de aislamiento SQL son definidos basados en si ellos permiten a cada uno de los eventos definidos anteriormente. Es interesante notar que el estándar SQL no impone un esquema de cierre específico o confiere por mandato comportamientos particulares, pero más bien describe estos niveles de aislamiento en términos de estos teniendo muchos mecanismos de cierre/coincidencia, que dependen del evento de lectura.
Niveles de aislamiento:
Comportamiento permitido
|-----------------------Nivel de Lectura-----------------------|
Nivel de Aislamiento
Sucia
No Repetible
Fantasma
Lectura no Comprometida
Si
Si
Si
Lectura Comprometida
No
Si
Si
Lectura Repetible
No
No
Si
Secuenciable
No
No
No
Según el estándar SQL, SQL Server permite todos estos niveles, Oracle sólo permite la lectura comprometida y secuenciable. Los niveles se pueden establecer en ambos para cada transacción. Sin embargo esto no es necesariamente cierto.
El estándar SQL trataba de establecer los niveles de aislamiento que permitirían a varios grados de consistencia para querys ejecutadas en cada nivel de aislamiento. Las lecturas repetibles "REPEATABLE READ" es el nivel de aislamiento que garantiza que un query un resultado consistente. En la definición SQL estándar, la lectura comprometida "READ COMMITTED" no regresa resultados consistentes, en la lectura no comprometida"READ UNCOMMITTED" las sentencias SELECT son ejecutadas sin realizar bloqueos, pero podría usarse una versión anterior de un registro. Por lo tanto, las lecturas no son consistentes al usar este nivel de aislamiento.
A mayor grado de aislamiento, mayor precisión, pero a costa de menor concurrencia.
El nivel de aislamiento para una sesión SQL establece el comportamiento de los bloqueos para las instrucciones SQL.
=Grado de Consistencia=
Consistencia es un término más amplio que el de integridad. Podría definirse como la coherencia entre todos los datos de la base de datos. Cuando se pierde la integridad también se pierde la consistencia. Pero la consistencia también puede perderse por razones de funcionamiento.
Una transacción finalizada (confirmada parcialmente) puede no confirmarse definitivamente (consistencia).
· Si se confirma definitivamente el sistema asegura la persistencia de los cambios que ha efectuado en la base de datos.
· Si se anula los cambios que ha efectuado son deshechos.
La ejecución de una transacción debe conducir a un estado de la base de datos consistente (que cumple todas las restricciones de integridad definidas).
· Si se confirma definitivamente el sistema asegura la persistencia de los cambios que ha efectuado en la base de datos.
· Si se anula los cambios que ha efectuado son deshechos.
Una transacción que termina con éxito se dice que está comprometida (commited), una transacción que haya sido comprometida llevará a la base de datos a un nuevo estado consistente que debe permanecer incluso si hay un fallo en el sistema. En cualquier momento una transacción sólo puede estar en uno de los siguientes estados.
· Activa (Active): el estado inicial; la transacción permanece en este estado durante su ejecución.
· Parcialmente comprometida (Uncommited): Después de ejecutarse la ultima transacción.

· Fallida (Failed): tras descubrir que no se puede continuar la ejecución normal.

· Abortada (Rolled Back): Después de haber retrocedido la transacción y restablecido la base de datos a su estado anterior al comienzo de la transacción.

· Comprometida (Commited): Tras completarse con éxito.
>>Aspectos relacionados al procesamiento de transacciones
Los siguientes son los aspectos más importantes relacionados con el procesamiento de transacciones:
· Modelo de estructura de transacciones: Es importante considerar si las transacciones son planas o pueden estar anidadas.
· Consistencia de la base de datos interna: Los algoritmos de control de datos semántico tienen que satisfacer siempre las restricciones de integridad cuando una transacción pretende hacer un commit.
· Protocolos de confiabilidad: En transacciones distribuidas es necesario introducir medios de comunicación entre los diferentes nodos de una red para garantizar la atomicidad y durabilidad de las transacciones. Así también, se requieren protocolos para la recuperación local y para efectuar los compromisos (commit) globales.
· Algoritmos de control de concurrencia: Los algoritmos de control de concurrencia deben sincronizar la ejecución de transacciones concurrentes bajo el criterio de correctitud. La consistencia entre transacciones se garantiza mediante el aislamiento de las mismas.
· Protocolos de control de réplicas: El control de réplicas se refiere a cómo garantizar la consistencia mutua de datos replicados. Por ejemplo se puede seguir la estrategia read-one-write-all (ROWA).
= Instrucciones COMMIT y ROLLBACK =
Una transacción tiene dos finales posibles, COMMIT y ROLLBACK. Por defecto, MySQL trae activado el modo autocommit, es decir, realizada una transacción
(por ejemplo un INSERT, UPDATE o DELETE)
el mismo es confirmado apenas es ejecutado. Para desactivar el autocommit, se puede desactivar el autocomit ejecutando el comando:
SET AUTOCOMMIT=0;
Una vez deshabilitado el autocommit, tendremos que utilizar obligatoriamente el COMMIT para confirmar o ROLLBACK para deshacer la transacción.
Si se quiere deshabilitar el autocommit para una serie de comandos, lo ideal es utilizar START TRANSACTION (sin necesidad de setear el AUTOCOMMIT en 0).
Al ejecutar una transacción, el motor de base de datos nos garantizará la atomicidad, consistencia, aislamiento y durabilidad (ACID) de la transacción (o conjunto de comandos) que se utilice.
Veremos un ejemplo completo, extraído del articulo fuente de esta publicación, donde utilizaremos START TRANSACTION (no es necesario AUTOCOMMIT en 0)
CREATE TABLE `departamentos` (
`CODIGO` INTEGER(11) NOT NULL DEFAULT ’0′,
`NOMBRE` VARCHAR(100),
`PRESUPUESTO` INTEGER(11) DEFAULT NULL,
PRIMARY KEY (`CODIGO`)
)ENGINE=InnoDB
Ahora, insertaremos registros de la tabla departamentos_externos a departamentos mediante una transacción:
START TRANSACTION;
SELECT @A := presupuesto
FROM departamentos_externos
WHERE codigo =11;
INSERT INTO departamentos( codigo, nombre, presupuesto )
VALUES ( 11, ‘Department test’, @A );
COMMIT;
En el ejemplo anterior se guardo el presupuesto del departamento externo 11 en la variable @A y luego fue asignado al presupuesto en la tabla departamentos.
Ejemplo:
START TRANSACTION;
SELECT @A := presupuesto, @B := codigo, @C := nombre
FROM departamentos_externos
WHERE codigo=33;
INSERT INTO departamentos( codigodep, nombredep, presupuesto ) VALUES (@B , @C , @A );
COMMIT ;
Ejemplo:
START TRANSACTION;
SELECT @A:=PRESUPUESTO FROM departamentos_externos WHERE codigo=11;
UPDATE departamentos SET PRESUPUESTO = PRESUPUESTO + @A WHERE codigo=33;
COMMIT;
Utilizando uno de los ejemplos de arriba sale el ejemplo de RollBack.
usando el ejemplo del amigo de arriba.
START TRANSACTION;

SELECT @A:=PRESUPUESTO FROM departamentos_externos WHERE codigo=11;

UPDATE departamentos SET PRESUPUESTO = PRESUPUESTO + @A WHERE codigo=33;

INSERT INTO departamentos_externos(RESUPUESTO) VALUES(‘valor’) WHERE codigo=11;
ROLLBACK;
Siempre recordando que COMMIT se usa para aceptar la transacción y ROLLBACK si deseamos cancelar la transacción.
Una vez que se realizo una o varias consultas (SELECT,UPDATE,DELETE,INSERT…) Tenemos dos opciones:
Aceptar la transacción o cancelar la transacción, para aceptar la transacción y los datos sean ingresados, actualizados, borrados (depende la sentencia que empleo usado) a la base de datos, utilizas COMMIT.
Para cancelar la transacción (es decir cancelar todas las sentencias realizadas) utilizas ROLLBACK. Y cabe recordar que una vez utilizada la sentencia COMMIT ya no puedes usar ROLLBACK.
Al realizar una transacción SQL hay que tener en cuenta que apenas se realice un INSERT, UPDATE o DELETE se genera un bloqueo sobre la tabla y que otros clientes no pueden acceder para escribir esta tabla. Otros clientes podrán realizar SELECTs sobre la tabla, pero no podrán ver los datos del primer cliente hasta que los mismos sean confirmados. Prometo pronto, tratar con más detalle el tema de bloqueos, específicamente el procesamiento concurrente de transacciones.
un ejemplo de cada uno en la norma SQL el comienzo de una transacción se especifica
explícitamente (usualmente begin/start transaction) las transacciones terminan con una de las siguientes instrucciones:
-commit work (compromete la transacción actual)
-rollback work (provoca que la transacción aborte)
Si el programa termina sin ninguna de estas órdenes, los cambios se comprometen o abortan según indique cada sistema.

Autor: Luis Eduardo Fernandez Rocha (Contacto Linkedin)