gentoo linux, java, software libre y otras hierbas
ene, 28 2008 - 3:02 pm

Activar logging de errores PHP en openSuse

Específicamente si estás usando openSuse con el servidor web Apache y PHP que viene por defecto, habrás notado algo realmente molesto: mientras estás programando, si tienes algún error en el código PHP, en vez de mostrarse el error, el archivo y la línea donde se encuentra el error, el navegador web no muestra nada.

Esto es porque, por defecto, el servidor de php5 de openSuse viene con el logging de errores de PHP desactivado (sobre Apache). Para cambiar esta configuración debes editar el archivo php.ini que se encuentra en /etc/php5/apache2/php.ini, y quitar los comentarios de ciertos valores:

sudo vim /etc/php5/apache2/php.ini

Los valores que buscamos vienen desactivados, puesto que están “comentariados“, es decir, tienen un punto y coma (;) al principio de la línea, o posiblemente estén en Off. Para activarlos deberás borrar el punto y coma (;) o cambiar el Off por On.

En resumen los valores que buscamos son (y deben quedar como en la lista) :

  • display_errors = On
  • display_startup_errors = On
  • html_errors = On
  • error_prepend_string = “<font color=ff0000>”
  • error_append_string = “</font>”

Las dos últimas variable indican las etiquetas a mostrar antes y después del error, y como podrás deducir es para ponerles un color y que resalte más.

Luego de hacer las modificaciones pertinentes, debemos reiniciar el servidor Apache si estaba corriendo:

/etc/init.d/apache2 restart

Eso es todo. Espero les sea de ayuda!

Sin comentarios | deja el tuyo

ene, 28 2008 - 1:45 pm

[código] La interfaz Runnable en Java

En ejemplos anteriores hemos creado clases que heredan de la clase Thread las cuales soportan subprocesamiento múltiple; y sobreescribimos el método run para especificar las tareas a realizar concurrentemente. Sin embargo, puesto que en Java NO existe la herencia múltiple (como en C++) ¿cómo podemos hacer entonces que una clase, que ya hereda de otra distinta a Thread, soporte subprocesamiento múltiple? La respuesta es sencilla: implementar la interfaz Runnable. De hecho la clase Thread implementa a Runnable.

Al implementar la interfaz Runnable en una clase, un objeto puede manipular objetos de esa clase como objetos Runnable. Y tal como cuando heredamos de Thread, debemos declarar y sobrecargar el método run().

Cuando una clase utiliza un objeto Runnable para manipular subprocesos, este crea un objeto Thread y asocia el objeto Runnable con ese objeto Thread (¿enredado? para nada; sigue leyendo y verás que es muy sencillo). La clase Thread posee constructores que pueden recibir objetos Runnable, por ejemplo el constructor

public Thread(Runnable objetoRunnable)

especifica que el método run() del objeto objetoRunnable es el que debe invocarse cuando el subproceso comience a ejecutarse. Por otro lado, el construtor

public Thread(Runnable objetoRunnable, String nombreHilo)

crea un objeto Thread con el nombre nombreHilo, y especifica que el método run() del objeto objetoRunnable es el que debe invocarse cuando el subproceso comience a ejecutarse. ¡Veamos un ejemplo para entender mejor!

Código fuente

El siguiente applet (CaracteresAleatorios.java) demuestra el uso de la interfaz Runnable: Leer el resto de la entrada…

11 Comentarios | deja el tuyo

ene, 27 2008 - 6:41 pm

[código] Sincronización de subprocesos – Búfer Circular

En los ejemplos anteriores de subprocesamiento en Java, utilizabamos la sincronización para garantizar que dos hilos manipulen correctamente los datos en un búfer compartido. Sin embargo, es probable que nuestra aplicación no tenga un rendimiento óptimo. Si los dos subprocesos operan a distintas velocidades, es probable que uno de ellos pase la mayor parte del tiempo esperando. Por ejemplo, en los anteriores ejercicios compartiamos una variable entera. Entonces, si por ejemplo el productor realiza sus tareas a una mayor velocidad que el consumidor, este debe esperar al consumidor; y viseversa. Incluso, suponiendo que los subprocesos se ejecutan a la misma velocidad relativa, cabe la posibilidad que uno u otro proceso se retrase, haciendo que se pierda la sincronización entre los mismos.

Como programadores, no debemos hacer suposiciones acerca de las velocidades relativas de los subprocesos concurrentes asíncronos, puesto que existen muchos factores que pueden afectar el tiempo de ejecución de los subprocesos (el sistema operativo, el usuario, el entorno de red, etc.).

El método que vamos a emplear en este ejemplo para minimizar el tiempo de espera que sufren los subprocesos que comparten recursos es crear un búfer circular. Con este nuevo enfoque, en vez de tener una única variable compartida, tendremos un arreglo de búferes. De esta forma, si el productor produce valores a mayor velocidad de la que el consumidor pueda consumirlos, almacenará los valores en posiciones distintas del arreglo (mientras haya espacio). Esto permite al productor hacer su tarea, aún cuando el consumidor no esté listo para realizar la suya. De igual forma, si en ciertas ocaciones el consumidor recoge valores a mayor velocidad de la que el productor pueda consumirlos, este puede buscar otros valores adicionales en el arreglo (si los hay) que el productor pudo haber producido con anterioridad.

Observa además, querido lector, que usar un búfer circular sería inapropiado si los procesos se ejecutan a diferentes velocidades conscientemente. Es decir, si por ejemplo sabemos que el consumidor se ejecuta siempre a mayor velocidad, no necesitariamos espacios adicionales puesto que el productor no tendría tiempo de llenarlas. De igual forma, si el productor se ejecutase siempre a mayor velocidad que el consumidor, necesitariamos un arreglo con infinitas posiciones.

En el ejemplo que veremos en breve (muy similar a los que habíamos visto antes), demuestra cómo un productor y un consumidor utilizan un búfer circular (en este caso un arreglo de tres celdas) mediante la sincronización.

Además, como valor agregado, veremos algo avanzado acerca de las interfaces gráficas. En este ejemplo tanto productor como consumidor (procesos independientes), modifican el contenido de un objeto de interfaz gráfica (en este caso un JTextArea). Puesto que los componentes gráficos de Swing no son “a prueba de subprocesos”, cabe la posibilidad de que si diferentes tareas están manipulando el mismo componente los resultados visuales no sean correctos. Todas las interacciones sobre los objetos GUI de Swing deben llevarse a cabo un proceso a la vez. Generalmente, este subproceso es el subproceso despachador de eventos (tambien conocido como el subproceso manejador de eventos). La clase SwingUtilities (del paquete java.swing), proporciona el método estático invokeLater para ayudar a realizar esta tarea. El método invokeLater especifica que las instrucciones de procesamiento de la GUI deben ejecutarse posteriormente, como parte del subproceso despachador de eventos. El método invokeLater recibe un objeto que implemente la clase Runnable (del paquete java.lang). Toda clase que implemente Runnable debe declarar el método run(). Los subprocesos en el siguiente ejemplo, que muestran su salida en la GUI, pasan objetos de la clase SalidaRunnable al método invokeLater. Cada objeto SalidaRunnable contiene una referencia al objeto JTextArea en el que se muestra la salida, y una cadena del mensaje a mostrar. Cuando el programa llama a invokeLater, la actualización del componente GUI se pondrá en la cola para ejecutarse en el subproceso despachador de eventos. Luego, el método run de la clase SalidaRunnable será invocado, haciendo el el componente JTextArea se ejecute actulice de forma segura.

Resultado del ejemplo

Código fuente

La interfaz Bufer.java especifica los métodos llamados por el Productor y el Consumidor: Leer el resto de la entrada…

Un comentario | deja el tuyo

« Entradas anteriores
Entradas recientes »