¿Qué es un deadlock o interbloqueo?

Post original en JASoft.org: http://www.jasoft.org/Blog/post/191;Que-es-un-deadlock-o-interbloqueo.aspx

Cuando se trabaja en programación paralela o multisubproceso, una palabra que sale a colación cada dos por tres es «deadlock» (o un «interbloqueo» en castellano). Muchos porgramadores principiantes tienen dudas sobre qué son y cómo se pueden producir, por lo que, a raíz de la pregunta de un alumno de mi curso de fundamentos de C# y .NET, me he decidido a escribir algo que lo explique de manera simple pero efectiva.

Un deadlock, es una situación difícil de reproducir, y se dará sólo en algunas circunstancias muy concretas, por eso son situaciones muy difíciles de prever y de depurar.

Un ejemplo clásico de interbloqueo es el de una cuenta bancaria.

Consideremos el caso de una clase para transferir dinero entre cuentas bancarias, algo así:

class Cuenta 
{ 
   double saldo;

   void Retirar(double cantidad) 
   { 
      saldo -= cantidad; 
   }

   void Ingresar(double cantidad) 
   { 
      saldo += cantidad; 
   }

   void Transferir(Cuenta cuentaOrigen, Cuenta cuentaDestino, double cantidad) 
   { 
      lock(cuentaOrigen) 
      { 
         lock(cuentaDestino) 
         { 
            cuentaOrigen.Retirar(cantidad); 
            cuentaDestino.Ingresar(cantidad); 
         } 
      } 
   } 
}

Este código no parece tener problema alguno, y parece bastante lógico.

DeadlockEn la operación de transferencia bloqueas el acceso a las clases que representan las cuentas de origen y destino para evitar inconsistencias en sus saldos, ya que si no lo bloquearas y otro hilo retira o ingresa dinero mientras se está efectuando otra transferencia podrías tener inconsistencias en los saldos. De esta forma te aseguras de que la operación de transferencia es consistente. Hasta aquí todo controlado…

Pero ¿qué pasa si de repente dos hilos intentan acceder exactamente al mismo tiempo a hacer una transferencia entre las mismas dos cuentas, pero en sentidos contrarios?

Por ejemplo:

Transferir(cuentaA, CuentaB, 1000);

y

Transferir(cuentaB, CuentaA, 500);

Lo que ocurriría es que la primera transferencia bloquearía la cuentaA y la segunda la cuentaB (es la primera línea de código). Al ir a bloquear la segunda cuenta, la primera operación se encontraría con un bloqueo en la cuentaB creado por la otra transferencia, y viceversa. El resultado es que ambas operaciones quedarían bloqueadas indefinidamente porque una estaría esperando debido al bloqueo de la otra: ¡deadlock!

Lo malo de esta situación es que se produce solamente en un caso muy concreto como el que describo, por lo que podríamos hacer nuestro programa, tenerlo en producción y que pasaran meses hasta que surgiera el problema. Y una vez que hubiera surgido no tendríamos forma de saber exactamente qué ha pasado ni ninguna pista de cómo reproducirlo. Por eso los problemas de multi-subproceso son tan complejos.

¡Espero que esto lo aclare un poco!

Efectuar la validación de varios formularios por separado en ASP.NET Web Forms

Post original en JASoft.org: http://www.jasoft.org/Blog/post/Efectuar-la-validacion-de-varios-formularios-por-separado-en-ASPNET-Web-Forms.aspx

input_validationHoy un truco rápido de principiante…

Los grupos de validación surgen para suplir una limitación de los formularios HTML dentro de los formularios Web de ASP.NET. Y es que, por el propio modo de funcionar de los Web Forms, cada página ASPX sólo puede tener un único formulario (en el sentido de que no pueden disponer de más de una etiqueta <form> de HTML). Por ello, si realmente quieres tener en tu página un par de formularios colocados (por ejemplo, uno para darse de alta y otro para hacer login en tu sitio web), realmente sólo existe un único <form> por debajo. Lo normal es agrupar los controles dentro de un panel  para que visualmente se vean separados, y para que se comporten como si realmente fueran dos formularios independientes, las validaciones se hacen de forma separada también.

Para conseguirlo se utiliza la propiedad ValidationGroup de los controles así como el control ValidationSummary. Ésta nos permite asociar la validación de un determinado control a un mismo grupo de controles que se validan juntos. Para ello hay que poner el mismo valor en la propiedad ValidationGroup de todos los controles que se deban validar de manera conjunta y hacer lo propio con el control ValidationSummary que recogerá el resultado de la validación conjunta.

Es decir, los pasos a seguir son:

  1. Añades a tu Web Form los controles que forman parte del formulario (etiquetas, cajas de texto, listas desplegables, etc…) así como el botón de enviar el formulario (en el evento OnClick del servidor para éste recoges los datos).
  2. Arrastras uno o más validadores al formulario para comprobar, tanto en cliente como en servidor, que se cubren los campos obligatorios, que son del tipo apropiado, etc… Es decir, haces las validaciones de la forma habitual.
  3. Incorporas un control ValidationSummary para recoger en un solo lugar los mensajes de todos los controles de validación que vayan saltando. Así lo puedes colocar, por ejemplo, a la derecha del formulario, y el usuario ve de un golpe de vista todos los problemas que hay.
  4. Estableces la propiedad ValidationGroup de todos los controles de validación y del ValidationSummary a un valor común, por ejemplo, «FormularioLogin». De esta forma todos los mensajes de estos validadores se mostrarán juntos en el resumen.

Parece realmente fácil, y lo es, pero hay un detalle que debemos tener en cuenta y que generalmente es el obstáculo con el que tropiezan todos los principiantes: se debe establecer la propiedad ValidationGroup no sólo en los controles de tipo Validator y en los controles a validar, sino también en los controles que puedan provocar una validación del formulario en cuestión.

Esto implica que el botón que envía el formulario debe tener en su propiedad ValidationGroup la misma cadena que los controles que debamos validar juntos como consecuencia del envío del formulario.

Si no le estableces esta propiedad al botón y a todos los controles que puedan provocar el envío del formulario al servidor, la validación no se produce y no funcionará el ValidationSummary ni,en realidad, la validación de ninguno de los controles del grupo.

¡Espero que te sea útil!

YouTube and Vimeo advanced viewer extensions for BlogEngine.NET

I was using the YouTubePlayer and VimeoPlayer extensions that come with BlogEngine.NET out of the box. They do a great work showing videos in desktop browsers, but I found some limitations that I wanted to overcome. So I decided to write my own extensions to substitute this two.

The YoutubeViewer and VimeoViewer extensions that I’ve written offer the following features:

  • Automatically embed a viewer for YouTube or Vimeo videos with a simple syntax. The basic syntax is Youtubesyntax and VimeoSyntax where XXXX is the video ID that you can get from the URL (squared in red in the images):

YouTubeID

VimeoID

  • The viewer adapt automatically to the capabilities of the browser used to browse your site. That means that they will be displayed correctly and full-featured even in mobile devices like iPhone, Android or iPad.
  • From the Extensions tab of BlogEngine you can set the default values for the viewer’s Width, Height, Border (Yes or No), Include related videos (YouTube only), Allow Full Screen (YouTube only), Title text color (Vimeo only):

YouTubeSettings
Press to zoom

YouTubeSettings
Press to zoom

  • As long as videos vary a lot in aspect ratio, you can specify the dimensions you want for the video directly in the insertion code, just in case the default settings are not correct, for example: Youtubesyntax2inserts the video with ID 123456 using a viewer of 800 pixels of with and 600 pixels of height. In the same way you can use the Vimeo syntax: VimeoSyntax2

To install just download this ZIP files: YouTubeViewer.zip and VimeoViewer.zip.

Uncompress then and copy the .cs files in the «App_Code/extensions» folder of your BlogEngine.NET blog. I advise you to delete the original YouTubePlayer.cs and VimeoPlayer.cs files.

Go to the Extensions tab of your BlogEngine dashboard and configure the default values for both extensions.

Enjoy!

Cómo cambiar la clave del Key Ring por defecto en Ubuntu 10.10

——-> Post original en JASoft: http://www.jasoft.org/Blog/post/Como-cambiar-la-clave-del-Key-Ring-por-defecto-en-Ubuntu-1010.aspx

Un fastidio en Ubuntu es que cuando cambias la clave de tu usuario, de repente empieza a pedirte que la introduzcas cada dos por tres cuando accedes a programas que almacenan claves en el sistema. Por ejemplo, yo utilizo Empathy como cliente de chat, y éste necesita la clave maestra del Key Ring por defecto para poder acceder a la información de las cuentas de chat y poder loguearse para ofrecer el servicio.

Para cambiar la clave lo que hay que hacer es irse a “Sistema·Preferencias·Contraseñas y claves de encriptación” (yo uso todos mis sistemas en inglés, por eso la captura se ve en este idioma):

PasswordsKeys

Pulsa para aumentar

Una vez abierto el programa nos vamos a la pestaña de contraseñas y en el nodo que hay ahí por defecto pulsamos con el botón derecho para elegir la opción de Cambiar la contraseña:

PasswordKeys2

Introducimos la clave vieja y dos veces la nueva haciéndola coincidir con la de la cuenta actual. ¡Listo! Ya no te la volverá a pedir.

¡Espero que te sea útil!

Simular notificaciones PUSH en una página Web

RefreshEn mi último post describía la arquitectura que utilizan tanto iPhone como Windows Phone 7 para enviar notificaciones PUSH desde aplicaciones externas a los usuarios de los teléfonos. La comunicación entre el dispositivo y el servicio de notificaciones se basaba en una conexión “raw” permanentemente abierta entre ambos. Pero ¿cómo podemos simular algo así en una página Web?

Hace poco un alumno de mi curso de preparación del examen 70-515 de desarrollo Web con tecnologías Microsoft, me preguntaba acerca de esta cuestión. En concreto la pregunta iba sobre sobre cómo conseguir el efecto de actualización automática de información que consiguen algunas páginas (como las de apuestas o de información bursátil) en las que el servidor envía información a los clientes sin que haya –aparentemente- una petición explícita por parte de éstos. Este comportamiento se asemeja mucho al de las notificaciones que describía en el anterior post.

Además había creado ya un servicio WCF y tenían una aplicación Windows Forms en la que utilizaban los callbacks de WCFpara conseguir este efecto. La pregunta era también si es posible utilizar los callbacks de WCF en ASP.NET para hacer esto, y en caso negativo qué otras soluciones existen para conseguir algo similar.

Notificaciones en una aplicación Web

En una página Web normal no hay forma de recibir notificaciones PUSH (es decir desde el servidor al cliente, bajo demanda del servidor), que es lo que buscamos. No podemos dejar una conexión abierta por la propia naturaleza de HTTP.

Por otro lado el futuro HTML5 define el manejo de Sockets puros desde JavaScript (desde el modelo de objetos del navegador, vamos) y con eso se solventarán situaciones como esta en el futuro, pero hoy por hoy no es una solución razonable. Además simplificaría programación de cierto bajo nivel. Para mi sería matar moscas a cañonazos: algo que estará bien para cosas muy particulares, pero de uso muy limitado.

Por todo eso la opción real que existe es utilizar PULL desde el cliente, es decir, pedir periódicamente desde el navegador los datos al servidor. En una aplicación Windows Forms la cosa es completamente diferente, pues puedes mantener una conexión abierta todo el tiempo con el servicio WCF y recibir notificaciones de éste, cosa que no es posible hoy en día desde el navegador, como comento.

La mejor manera de hacer esto en una aplicación Web es exponer los datos del servicio WCF como JSON (o como un método estático accedido con retrollamadas de red de ASP.NET AJAX) y hacer llamadas periódicas desde la página Web a dicho servicio para que te devuelva por AJAX los datos pertinentes. Puedes recibir todos los datos o, si hay alguna marca temporal (por ejemplo la fecha y hora de la última comprobación) que te devuelva únicamente los datos que hayan cambiado.
 
Con jQuery, por ejemplo, es muy fácil de hacer, e incluso con jQuery Templates puedes generar la interfaz de lado cliente de modo dinámico, por lo que complicas un poquito el desarrollo pero mejoras la eficiencia del trasiego de información (comparado con usar, por ejemplo, un UpdatePanel, que los carga el diablo).

Por supuesto tampoco pasa nada si no quieres complicarte la vida y si la aplicación no mueve entre cliente y servidor una cantidad ingente de datos, puedes usar un UpdatePanel de ASP.NET AJAX combinado con un Timer de ASP.NET AJAX para refrescar el listado en la página sin ni siquiera tener que escribir código. Eso sí, si lo haces desactiva el ViewState de la rejilla para que no pesen mucho los postbacks al servidor. Lo malo del UpdatePanel es, como es sabido, que en realidad se recarga la página completa y se transmite el ViewState (que hay que mantener bajo control o te ralentiza mucho), pero si logras controlar el tamaño de la información transferida entre cliente y servidor y viceversa, es una opción rápida y sencilla de implementar, sin escribir una sola línea de código. Lo cual es estupendo 🙂

En este caso además, en cuanto al rendimiento, dependerá del periodo de refresco que le establezcamos al Timer. Una página Web no puede funcionar igual que una aplicación de escritorio por la propia naturaleza del medio, que es diferente: es desconectado, puede haber muchos potenciales usuarios y las peticiones a un servidor pueden llegar a saturarlo si hay muchos clientes, la propia página si hay muchos datos puede tardar en recargarse… Para hacer cosas en tiempo real no es lo adecuado, desde luego. Ahora bien si va a ser usada por poca gente en una Intranet, por ejemplo, y las peticiones no cargan en exceso el servidor quizá podamos bajar el periodo del Timer sin problemas, aunque no a décimas der segundo ni nada parecido…

En resumen, para mi la mejor opción es usar jQuery Templates para generar directamente desde el lado cliente la interfaz: devolver los datos desde el WCF en formato JSON, consumirlos desde $.Ajax() y recrear la interfaz con los nuevos datos. Es eficiente, rápido, no carga el servidor, etc… muchas ventajas, pero es más complicado que usar controles ASP.NET AJAX de servidor como el UpdatePanel.

¡Espero que te resulte útil!

Arquitectura: Cómo funcionan las notificaciones en los teléfonos móviles (iPhone, Windows Phone…)

Los smartphone actuales tienen mayor potencia que muchos ordenadores de hace solo unos años, y además tienen la característica fundamental de que están siempre conectados a Internet, bien a través de 3G o de WiFi. Eso los hace muy adecuados para todo tipo de aplicaciones que consuman información en tiempo real (o “casi-real”), así como la implementación de servicios que impliquen el consumo de información muy actualizada (noticias, avisos, mensajes, etc…).

Por ejemplo, Windows Phone 7 dispone de 3 tipos de notificaciones: las “Tostadas” (Toast) que son mensajes informativos que saltan en cualquier momento, las de “Baldosas” (Tile) que se muestran directamente en los rectángulos que representan tu aplicación en la portada, y las “raw” que se reciben directamente en la aplicación cuando está en ejecución. En esta figura la franja verde de la parte superior es una notificación Toast y en las baldosas podemos ver numeritos que se corresponden con notificaciones Tile:

WP7Notificaciones

En el caso de iOS para iPhone y iPad, las notificaciones son similares y disponemos de diálogos aún más visibles (equivalentes a los Toast) así como numeritos en los iconos equivalentes a los Tile (por ejemplo el correo en la parte inferior de esta figura):

iPhoneNotificaciones

El problema de la batería

Si desarrollas aplicaciones para móviles y quieres mostrar al usuario avisos e información en tiempo real obtenidos a partir de información externa tienes básicamente dos formas teóricas de conseguirlo:

  1. Si el usuario está usando tu aplicación puedes mostrar las notificaciones que creas convenientes, pues tienes toda su atención. Si la información se genera en Internet (como es habitual) puedes realizar llamadas periódicas a un servicio externo que te devuelva la información necesaria (por ejemplo, que te muestre las últimas noticias o lo que sea que consumes).
  2. Si tu aplicación no está siendo utilizada podrías tener una especie de servicio o “demonio” ejecutándose en el teléfono que realice comprobaciones periódicamente, y si hay algo que notificar que muestre un diálogo, actualice un panel de información o directamente lance tu aplicación.

El problema con la primera estrategia es que el usuario no puede estar usando tu aplicación todo el rato, por lo que no puedes depender de esto para mostrar alertas, que por definición, pueden llegar en cualquier momento, cuando son necesarias.

La segunda estrategia tiene un problema fundamental: ningún sistema operativo para móviles que se precie te va a permitir hacer algo así.

Imagínate que el sistema operativo lo permitiera: no sólo tu aplicación, sino potencialmente docenas de ellas, estarían lanzando peticiones en segundo plano a servicios de Internet, con la cadencia que ellas mismas consideraran, es decir, potencialmente decenas de conexiones cada minuto a Internet. El resultado: tu batería agotada en un par de horas y de paso tu tarifa plana (que no es plana, sino ondulada pues tiene un límite) agotada en pocos días.

Otros efectos secundarios serían mucha memoria consumida, elevada demanda del procesador, conexiones lentas, fallos de conectividad, lentitud del terminal… Y como los usuarios no saben si eso es culpa de las aplicaciones o del sistema operativo, el resultado adicional es que dirían que “iPhone/WP7 es una porquería”, algo que –por supuesto- no le interesa a ningún fabricante.

Conclusión: tu aplicación no puede enviar alertas ni notificaciones por si misma.

Servicios PUSH de notificaciones

Dado que está claro que los teléfonos lo permiten: ¿cómo es posible conseguir esta funcionalidad en una de nuestras aplicaciones si tenemos la limitación anterior?. Pues todos los sistemas operativos funcionan de una manera similar, y para conseguirlo utilizan una arquitectura distribuida en la que tu teléfono, su servicio y un servicio que tú debes programar tienen que trabajar en armonía. Es lo que voy a explicar teóricamente en este post.

Aunque cada S.O. tiene sus particularidades, todos funcionan de una manera similar, así que comprendiendo esta arquitectura nos servirá para trabajar en cualquier plataforma.

Existen tres piezas del mecanismo que deben trabajar conjuntamente para que todo el sistema funcione: el terminal, un servicio propio que debemos programar y un servicio de notificaciones que proporciona el fabricante (Microsoft o Apple). El servicio propio se encargará de lanzar las notificaciones cuando sea necesario (tendremos que programarlo, claro está), usando para ello como intermediario el servicio del fabricante.

El siguiente esquema ilustra el funcionamiento general de este tipo de sistemas:

ArquitecturaPUSH

· Paso 1: Primeramente nuestra aplicación debe indicar al sistema operativo que desea recibir notificaciones y alertas desde el servicio PUSH, para lo cual existe una API concreta en cada plataforma. Se hace una llamada a un método especial que se conecta al servicio PUSH del fabricante para registrar el terminal y la aplicación (paso 1 en la figura). Esta operación sólo se lleva a cabo una vez, y luego ya no es necesaria.

· Paso 2: Como resultado de esta operación el servicio devuelve a nuestra aplicación una URI (identificador universal de recursos). Ésta es única para ese teléfono y esa aplicación, lo cual nos asegura que podremos enviar mensajes específicamente a ese usuario y no a otros. En el caso de Apple no es exactamente una URI sino un token o testigo único, pero a efectos prácticos es lo mismo.

· Paso 3: Esa URI que hemos obtenido es necesario pasársela al servicio que hemos creado y que tendremos disponible en Internet. A partir de este momento nuestro servicio sabe cómo debe comunicar las nuevas alertas y eventos al servicio del fabricante.

· Paso 4: Nuestro servicio se encarga de recuperar la información que necesitemos notificar, bien sea un nuevo mensaje recibido, un resumen de noticias, etc… dependerá de la utilidad de nuestra aplicación. Es este servicio el que se encarga de verdad de estar trabajando en segundo plano para obtener la información, dado que no podemos tenerlo en el teléfono estará en Internet. Para este tipo de aplicaciones se prestan muy bien los servicios en la nube como Azure que además ofrecen sistemas de colas muy apropiados para estas aplicaciones.

Bien, cuando se determina que es necesario enviar una notificación se hace una llamada a la API del servicio PUSH del fabricante. A este servicio se le pasa la URI obtenida en el paso 3 y una breve información de forma que se enviará la notificación al terminal correcto pues la URI,  por definición, es única.

Si la aplicación ya no existe (porque el usuario la desinstaló) en el caso de Microsoft la llamada devuelve un código específico para indicarlo. En el caso de Apple existe un “servicio de Feedback” que debemos consultar periódicamente y que contiene los tokens que han sido eliminados (por haber desaparecido la aplicación) y a las cuales ya no debemos notificar más. Es más incomodo.

Existe un límite en cuanto al tamaño de la información que se le puede pasar al servicio PUSH. En el caso de iOS es de 256 bytes, mientras que en el de Windows Phone es de cuatro veces más (1024 bytes).

También existe un límite por defecto en el número de peticiones que nuestro servicio puede enviar al servicio PUSH del fabricante que en el caso de Microsoft son 500 notificaciones  al día para una misma URI. No dispongo de esa información en el caso de Apple.

· Paso 5: el servicio PUSH recibe la notificación desde nuestro servicio y la encola para ser enviada al terminal. Si éste está conectado se envía inmediatamente, si no permanece en la cola a la espera de que vuelva a establecerse la conexión para esa URI.

Si el terminal no está conectado y se acumulan varias notificaciones para la misma aplicación el servicio PUSH sólo envía la última para no saturar al usuario, así que pueden perderse notificaciones concretas. La conexión entre el terminal y el servicio está asegurada mediante TSL. Eso es así tanto en Microsoft como en Apple.

Los servicios de notificación PUSH funcionan creando un único conducto de comunicación entre el dispositivo móvil y el servicio del fabricante en la nube. Este conducto se constituye a través de un socket “raw” que no se cierra pero que apenas consume recursos y sólo transfiere información estrictamente cuando es necesario. Es el típico modelo de suscripción/publicación o PUSH, que contrasta frente al modelo de petición/respuesta habitual en la Web en que, en este caso y como hemos visto, es el servidor el que envía la información al cliente cuando es necesario y no depende de que éste la solicite (no hay peticiones desde el terminal). En la wikipedia hay un pequeño artículo al respecto si quieres aprender un poco sobre este tipo de conexiones.

Gracias a ello sólo es necesario un canal abierto entre el teléfono y el servicio para recibir todas las notificaciones. El S.O. del móvil se encarga de notificar a la aplicación apropiada del modo adecuado según el tipo de notificación recibido por el canal y su contenido. De esta forma apenas se consumen datos y los escasos recursos del teléfono (rendimiento, memoria y batería) se preservan perfectamente.

Como vemos es un método que complica un poco la vida a los programadores, pero que a cambio permite disponer de un servicio casi en tiempo real sin poner en peligro la estabilidad de los terminales.

Si estás interesado en conocer más sobre el funcionamiento en la práctica de estos servicios de notificación aquí te dejo los enlaces a la documentación concreta en Microsoft y en Apple.

De regalo: cómo actualizar automáticamente un Tile sin usar PUSH

Si lo anterior te parece muy complejo de desarrollar (al fin y al cabo implica no sólo saber de desarrollo para el terminal sino también desarrollo Web y/o para la nube), en el caso de Windows Phone existe la posibilidad de obtener actualizaciones automáticas de baldosas (Tiles) sin necesidad de desarrollar un servicio ni pasar por el intermediario PUSH.

Se trata de definir una URL que devuelve una imagen que se usará automáticamente para dibujar el Tile. El propio teléfono se encargará de actualizarla con la periodicidad que indiquemos. Esta periodicidad no puede ser cualquiera sino únicamente una de los cuatro valores de la enumeración UpdateInterval, a saber: cada hora, cada día, cada semana o cada mes. O sea, como mínimo cada hora, menos no se puede.

Por lo tanto no nos sirve para actualizaciones en tiempo real, pero sí que será suficiente para otros tipos de aplicaciones que no necesiten esa inmediatez.

Otra limitación es que la imagen debe pesar menos de 80 KB y además debe tardar en cargar menos de 15 segundos (si tenemos muchos usuarios deberemos tener un ancho de banda suficiente para asegurar esto).

Aún así me parece una opción muy interesante y a tener en cuenta. Es además, muy sencilla de implementar.

¡Espero que te resulte útil!