/// <summary> /// Puede levantar AbortarEsperarMorirException debido al protocolo Esperar-Morir /// </summary> /// <param name="transaccion">Transaccion que solicita el bloqueo</param> /// <param name="condiciones">Condiciones por la que bloquear</param> /// <param name="tipoBloqueo">Tipo de bloqueo que solicita</param> /// <returns></returns> internal DescriptorBloqueo bloquear(Transaccion transaccion, Condicion condicion, TipoBloqueo tipoBloqueo) { lock (Entradas) { foreach (EntradaBloqueo entrada in Entradas) { if (entrada.igualCondicion(condicion)) { if (entrada.permiteBloqueo(condicion, tipoBloqueo)) { return(entrada.bloquear(transaccion, tipoBloqueo)); } entrada.encolarBloqueo(transaccion); //-> aqui puede leventar exception por protocolo esperar morir while ((entrada.Bloqueado && !entrada.permiteBloqueo(condicion, tipoBloqueo)) || !entrada.desencolarSiEsElSiguiente(transaccion)) { Monitor.Wait(entradas); } if (tipoBloqueo == TipoBloqueo.BLOQUEO_LECTURA) { Monitor.PulseAll(entradas);//porque no eran los primeros, se volvieron a bloquear } return(entrada.bloquear(transaccion, tipoBloqueo)); } } //no estaba la entrada EntradaBloqueo nuevaEntrada = new EntradaBloqueo(this, tipoBloqueo, condicion); Entradas.Add(nuevaEntrada); return(nuevaEntrada.bloquear(transaccion, tipoBloqueo)); } }
internal EntradaBloqueo(ControladorConcurrencia controladorConcurrencia, TipoBloqueo tipo, Condicion condicion) { this.controladorConcurrencia = controladorConcurrencia; this.tipo = tipo; this.condicion = condicion; }
internal Boolean permiteBloqueo(Condicion condicion, TipoBloqueo tipo) { if (igualCondicion(condicion) && Bloqueado) { //si alguno de los 2 es de escritura, no se puede if (this.Tipo == TipoBloqueo.BLOQUEO_ESCRITURA || tipo == TipoBloqueo.BLOQUEO_ESCRITURA) { return(false); } } //distina condicion, o ambos de lectura return(true); }
/// <summary> /// Bloquea para esa transaccion, debe controlarse antes de llamar a este mensaje /// </summary> /// <param name="transaccion"></param> internal DescriptorBloqueo bloquear(Transaccion transaccion, TipoBloqueo tipo) { //este control es por las dudas if (Tipo == TipoBloqueo.BLOQUEO_ESCRITURA && Bloqueado) { throw new Exception("Ya estaba bloqueado como escritura"); } bloqueado = true; this.tipo = tipo; bloqueados.Add(transaccion); DescriptorBloqueo descriptor = new DescriptorBloqueo(this, transaccion); transaccion.agregarBloqueado(descriptor); return(descriptor); }
/// <summary> /// Puede levantar AbortarEsperarMorirException debido al protocolo Esperar-Morir /// <para>Esto indica que la transaccion se abortó</para> /// </summary> /// <param name="transaccion"></param> /// <param name="tabla"></param> /// <param name="condicion"></param> /// <param name="tipoBloque"></param> /// <returns></returns> public void bloquear(Transaccion transaccion, Condicion condicion, TipoBloqueo tipoBloque) { controladorConcurrencia.bloquear(transaccion, condicion, tipoBloque); }