30 julio 2014

SQL en modo multitarea y multi-hilo (Parte 5 de 8)

Ejecución de un “worker”


El método $start() causa que la tarea especificada para el “worker” sea ejecutada como un subproceso en segundo plano. Por lo tanto no se produce pausa o espera alguna, la aplicación continua con su ejecución. Observe el siguiente ejemplo, el cual presupone que disponemos de la variable “iWorkerObj” correctamente definida, tal y como se puede observar a continuación…

;; iWorkerObj es una variable de tipo Object definida bajo instancia
Calculate Params as row(
iSQLText,'192.168.0.10’,iUser,iPassword,iDBName)
Do Params.$redefine(query,hostname,username,password,database)
Do iWorkerObj.$init(Params)
Do iWorkerObj.$start() Returns #F

…el método $run() (proporcionado sólo con fines de depuración y pruebas) es análogo a $start(), pero no debe ser usado en modo de explotación, ya que el “worker” es ejecutado sobre un único hilo quedando bloqueado hasta que la tarea asignada concluye.

Una vez iniciado el objeto “worker” puede ser ejecutado varias veces si así se desea, siempre y cuando el objeto-sesión suministrado siga estando disponible o bien el grupo de sesiones (sesión-pool) disponga de una o más sesiones libres de uso y las credenciales de inicio de sesión sigan siendo válidas. Cualquiera de las variables vinculadas (bind) ya suministradas, serán reutilizadas cada vez que se ejecute el “worker”.

Si se produce un error durante la ejecución de un $init(), $start() o $run(), se enviará un mensaje de error mediante las propiedades del objeto denominadas $códigoerror y $erroreext.

Procesado de los resultados de un “worker”


Una vez concluida la tarea asignada al “worker”, se invocará uno de los dos métodos de devolución disponibles:

  • $completed()
    Este método es invocado junto con un parámetro de tipo “row” que contiene dos columnas: “Results”: con una lista de una sola columna con cero o más conjuntos de resultados SQL y “Errors”: una lista de dos columnas con los valores ErrorCode y ErrorMsg.

  • $cancelled()
    Este método es invocado (sin paso de parámetros) y se produce cuando el usuario ejecuta un $cancel() sobre el objeto “worker” mientras está en ejecución. Los resultados pendientes son descartados.

A menudo sucede que una misma librería contiene objetos “worker” de diferentes tipos, cada uno de ellos con una tarea específica (sentencia SQL) e iniciados en modo asíncrono. Por lo tanto, la responsabilidad sobre el tratamiento de los resultados depende del uso que demos a los métodos indicados anteriormente, es en ellos donde se podrá obtener información sobre los resultados y ponerlos a disposición de la aplicación. A modo de ejemplo, describimos un posible uso del método $completed().

Calculate List as pRow.Results.1.1 ;;extrae el primer conjunto de resultados
Calculate Errors as pRow.Errors ;;extrae la lista con los posibles errores
If Errors.$linecount()>0
    Do method reportError(Errors)
Else
    Do method updateWindow(List) ;; procesa resultados
End If
Calculate iThreadCount as $cinst.$threadCount ;; obtiene el número de hilos en proceso


En caso de que los resultados devueltos por $completed() deban ser mostrados sobre una ventana, necesitaremos dibujar de nuevo su instancia (la de la ventana) y si se trata de un “remote-form”, el cliente deberá contactarse de nuevo con el servidor para su actualización.

Estados de un “worker”


Para consultar el estado en que se pueda encontrar un objeto “SQL worker” deberemos hacer uso de su propiedad $state. Que podrá informar de los siguientes:

  • kWorkerStateCancelled – El “worker” ha sido cancelado.
  • kWorkerStateClear – El “worker” se ha iniciado.
  • kWorkerStateComplete – El “worker” ha concluido.
  • kWorkerStateError – Se ha producido un error (ver $errortext).
  • kWorkerStateRunning – El “worker” está actualmente en ejecución.

Ejemplo de uso:

If iWorkerObj.$state=kWorkerStateRunning&iWorkerObj.$waitforcomplete=kTrue
     Calculate iMesg as 'En ejecución (esperando su conclusión)'
     Quit method
End If



21 julio 2014

SQL en modo multitarea y multi-hilo (Parte 4 de 8)

Iniciación de un objeto “worker”


El objeto “worker” deberá ser iniciado para un hilo, antes de ser ejecutado. Lo haremos mediante el suministro de una sentencia SQL y sus variables vinculadas (bind) que precise. Los datos necesarios para el inicio de una sesión con la base de datos o el nombre del grupo de sesiones (si estamos usando una pila de sesiones) también podrán ser suministrados durante el proceso de iniciación.

El parámetro de inicialización deberá ser suministrado con el método $init(), por medio de una variable de tipo “row”, que contendrá los valores para cada uno de sus atributos. El nombre de cada atributo corresponderá con el de cada una de sus columnas. A continuación, mostramos los que serán reconocidos por el objeto “worker”: (sensible al uso de mayúsculas y minúsculas)

Atributo Descripción
session Un objeto-sesión activo (session object) o referencia a un objeto-sesión. Deberá corresponder a una conexión en uso y utilizable.
poolname El nombre de un grupo de sesión existente. El “worker” tomará un objeto-sesión del grupo indicado y devolverá el control.
hostname Nombre host/IP del servidor de base de datos.
database Nombre de la base de datos a utilizar al inicio de sesión.
username Nombre del usuario a utilizar para el inicio de sesión.
password Contraseña del usuario para el inicio de sesión.
query Sentencia SQL que deberá ser ejecutada por el “worker”.
bindvars Es una lista con los valores de las variables vinculadas (bind). Las variables “bind” son leídas según el orden de las columnas. Si la lista contiene varias filas, la consulta será ejecutada para cada una de las filas.

Si se proporciona el atributo “session”, el resto de atributos de inicio de sesión, es decir, el “hostname”, “username” y “password” serán ignorados, ya que se presupone que el objeto-sesión está en estado utilizable. Nota importante: Si se usa de éste modo, la sesión deberá ser considerada como reservada para su uso exclusivo con “worker”. Cualquier intento de compartir un objeto-sesión que está siendo utilizado por un “worker”, que (dicho sea de paso) cuenta con su propio hilo de ejecución, los resultados serán impredecibles.

Al igual que en el caso del atributo “session”, los parámetros de inicio de sesión indicados también serán ignorados si se suministra el atributo “poolname”. En este modo, el “worker” intentará obtener una sesión del grupo de sesiones referenciado, liberándolo de nuevo tras su ejecución. En el caso de aportarse ambos atributos, (“sesión” y “poolname”) se ignorará el “poolname”.

Cuando no se aportan ninguno de ambos atributos, (“sesión” y “poolname”), se crea en ese instante un objeto-sesión interno. En éste caso deberán indicarse las credenciales para el inicio de la sesión, tales como el nombre de host/IP, nombre de usuario y su contraseña. Tenga en cuenta que, aunque estos atributos serán leídos al ejecutarse el método $init(), el “worker” no intentará iniciar la sesión hasta que los métodos $run() o $start() sean invocados. Éste modo de uso, causa que la sesión sea activada/desactivada automáticamente, cada vez que la tarea o “worker” se completa o bien es cancelada. En caso de que necesite modificar uno o más atributos de la sesión, antes de ejecutar el método $run() o $start(), podrá hacerlo mediante obtener una referencia al objeto-sesión al que pertenece el “worker”, usando para ello el método $sessionref(), por ejemplo, si quisiéramos modificar el puerto asignado, podríamos hacer lo siguiente:

Do iWorkerObj.$sessionref(lObjRef) Returns #F
Do lObjRef.$port.$assign(5435)


La texto SQL suministrada a través del atributo “query” podrá contener cualquier sentencia SQL, pero puesto que se trata de aprovechar la capacidad del multiproceso y multi-hilo, se espera que se trate de una declaración que normalmente le lleva una apreciable cantidad de tiempo al servidor para su ejecución, por ejemplo; una SELECT, UPDATE o DELETE con muchas filas y/o tablas implicadas. El texto de la “query” también podrá contener una o más variables vinculadas, especificadas en la forma ya conocida @[...].

Los valores de las variables vinculadas deberán suministrarse por medio del atributo “bindvars”. La lista es guardada por medio del método $init() y leida cuando se ejecuta la tarea o “worker”. En el caso de que la lista contenga varias filas, el “worker” volverá a ejecutar la sentencia SQL suministrada para cada una de las filas, pasando los valores de cada variable vinculada, en correspondencia con el orden de sus columnas.

Tenga en cuenta que el “worker” no tendrá en cuenta los nombres de las variables especificadas en el texto SQL, a la hora de establecer la correspondencia con sus valores, ya que ésta será establecida de acuerdo a su posición y no según sus nombres.

SQL en modo multitarea y multi-hilo (Parte 3 de 8)

Creación de objetos “SQL Worker”


Los objetos “worker” son creados como sub-clases (de tipo “SQL Worker”) de una clase objeto Omnis (Omnis object class). Por ejemplo, si queremos usarlo contra una base de datos Oracle, seleccionaríamos desde el cuadro de diálogo “Select Object”, el valor pertinente para su propiedad $superclase en: .ORACLE8DAM.Worker Objects\OracleWorker.
Naturalmente lo que queremos es poder acceder a las diferentes funciones del objeto “worker” desde el código de nuestra aplicación, para ello deberemos crear una o más variables de tipo objeto en el ámbito de instancia, fijando el objeto “worker” creado, como sub-tipo de dichas variables.

15 julio 2014

SQL en modo multitarea y multi-hilo (Parte 2 de 8)

Métodos de los objetos “SQL Worker”
Método Descripción
$init() $init(ParamRow). Inicia o restablece un objeto “worker” preparándolo para realizar una tarea.*
$start() Ejecuta una tarea o “worker” como un subproceso (ejecución en segundo plano, tenga en cuenta que el programa continuará su ejecución no se producirá ningún tipo de bloqueo o detención)*
$run() Ejecuta una tarea en modo “único-hilo” (se detienen todos los procesos a la espera de una respuesta). Este método se aporta sólo con la finalidad de que pueda realizar pruebas de ejecución.*
$cancel() Cancela una tarea o “worker”, que está siendo ejecutada como subproceso (en segundo plano).*
$sessionref() $sessionref(ObjectRef). Devuelve la referencia del objeto de sesión, al que pertenece el “worker” en uso.*
$completed() Es ejecutado por el propio “worker”, tras concluirse su ejecución.
$cancelled() Es invocado en el caso de que se produzca la cancelación de un “worker” que se estaba ejecutándose en segundo plano.
*Si es ejecutado con éxito devolverá kTrue o en caso contrario kFalse.


Propiedades de los objetos “SQL Worker”
Propiedad Descripción
$cancelifrunning Si es kFalse (por defecto), se concluirá la ejecución de los “worker” que hayan podido quedar huérfanos. Si es kTrue, se informará sobre su estado.
$waitforcomplete Si es kTrue (por defecto), el “Interface Object” se mantiene a la espera de que el “worker” en ejecución termine, antes de habilitarse para la ejecución de otro. Si es kFalse, el “worker” en ejecución es liberado, permitiéndose la ejecución de otro en su lugar.
$state Devuelve el estado actual del “worker”, el cual podrá ser: kWorkerStateCancelled, kWorkerStateClear, kWorkerStateComplete, kWorkerStateError o kWorkerStateRunning.
$errorcode Contiene el código de error. (Si se produce).
$errortext Contiene el texto del error. (Si se produce).
$threadcount Contiene el número de subprocesos “worker” que están actualmente bajo supervisión del “Thread Timer Object”.  (Control multi-hilo)

14 julio 2014

SQL en modo multitarea y multi-hilo (Parte 1 de 8)

Omnis Studio 6 permite el lanzamiento de sentencias SELECT como subprocesos independientes y desligados del hilo principal, hasta que el servidor ha procesado los resultados. Para habilitar esta funcionalidad, los DAM’s posibilitan ahora la creación de “SQL Workers”, denominación otorgada a las instancias creadas con éste propósito mediante el uso de variables objeto (SQL) y disponibles con los nuevos DAM’s para Oracle, ODBC, JDBC, MySQL, PostgreSQL, DB2, Sybase, y SQLite.

Los objetos “SQL Worker” pueden ser (por ejemplo) asignados a los diferentes campos de tipo lista usados en un formulario y que (nótese) serán cargados en modo asíncrono, lo que podría ser usado para conseguir acelerar en gran manera la carga de datos en un formulario, ya que además se hace uso de la característica añadida del multi-hilo (procesamiento en paralelo de sentencia SQL) junto con la capacidad multitarea aportada por los “SQL Workers”.

¿Cómo funciona?

Los objetos “SQL Worker” contienen los siguientes métodos principales:
  • $init()
  • Inicia o restablece un objeto “worker” dejándolo listo para realizar su tarea

  • $start()
  • Ejecuta una tarea o “worker” como un subproceso (ejecución en segundo plano, tenga en cuenta que el programa continuará su ejecución no se producirá ningún tipo de bloqueo o detención)

  • $cancel()
  • Cancela una tarea o “worker”, que está siendo ejecutada como subproceso (en segundo plano)

Esto es sólo una descripción general, por supuesto contamos con una serie de propiedades que nos permiten (por ejemplo) descartar una tarea en ejecución para hacer uso de otra en su lugar, cancelar tareas que se hayan podido convertir en “huérfanas” o simplemente informaros del estado en que se encuentre una determinada tarea o “worker”.

Los objetos “worker” son creados como sub-clases (tipo “SQL Worker”) de una clase objeto Omnis. Después deberemos iniciar el objeto con una sentencia SQL y sus variables vinculadas (bind) que precise. Los datos necesarios para el inicio de una sesión con la base de datos o el nombre del grupo de sesiones (si estamos usando una pila de sesiones) también podrán ser suministrados durante el proceso de iniciación.

Para la instanciación de un subproceso “SQL Worker” se usa el método $start(). Al concluirse su ejecución, se invocará automáticamente al método $completed() o al $cancelled(), al que se pasará el conjunto de resultados o bien la información del error producido.

08 julio 2014

jsClient: Cofiguración del wrapper JavaScript

Configuración del wrapper


La estructura del archivo de configuración ha cambiado y ahora se proporciona un formato genérico para todas los dispositivos móviles soportados. El archivo config.xml contiene la dirección URL de la página con el “remote-form” JavaScript y dependiendo de la plataforma, podrá contener un número variable de otros parámetros (esto se  describe en la nota técnica correspondiente). El config.xml está basado en la siguiente estructura:

≤? Xml version="1.0" encoding="UTF-8"≥
≤settings≥
   ≤apptitle≥0≤/apptitle≥
   ≤menuincludesettings≥1≤/menuincludesettings≥
   ≤menuincludeoffline≥1≤/menuincludeoffline≥
   ≤menuincludeabout≥1≤/menuincludeabout≥
   ≤settingsfloatcontrols≥0≤/settingsfloatcontrols≥
   ≤settingsscaleform≥1≤/settingsscaleform≥
   ≤settingsallowhscroll≥0≤/settingsallowhscroll≥
   ≤settingsallowvscroll≥0≤/settingsallowvscroll≥
   ≤settingsmaintainaspectratio≥0≤/settingsmaintainaspectratio≥
   ≤settingsonlinemode≥1≤/settingsonlinemode≥
   ≤serveromnisweburl≥http://172.19.250.25:5911≤/serveromnisweburl≥
   ≤serveronlineformname≥/jschtml/RFonline≤/serveronlineformname≥
   ≤serveromnisserver≥≤/serveromnisserver≥
   ≤serveromnisplugin≥≤/serveromnisplugin≥
   ≤serverofflineformname>rfOffline≤/serverofflineformname≥
   ≤serverappscafname≥mylib≤/serverappscafname≥
   ≤testmodeenabled≥0≤/testmodeenabled≥
   ≤testmodeserverandport≥172.19.250.25:5911≤/testmodeserverandport≥
≤/settings≥

El config.xml contiene las siguientes propiedades estándar:

  • AppTitle
La aplicación mostrará una barra de título en la parte superior.

  • MenuIncludeSettings
La opción de menú “Ajustes” estará disponible en tiempo de ejecución.

  • MenuIncludeOffline
La opción de menú para cambiar al modo “off-line”, estará disponible en tiempo de ejecución.

  • MenuIncludeAbout
La opción de menú “Acerca de” estará disponible en tiempo de ejecución.

  • SettingsFloatControls
Esta propiedad sólo es significativa cuando SettingsScaleForm es "0" (falso). En este caso, el cliente hará uso de la nueva propiedad $screensizefloat presente en cada control de los “remote-forms” jsClient. Al aplicar el tamaño de la pantalla, el cliente hará uso de $screensizefloat para hacer flotar los bordes de los controles, usando para ello las mismas reglas definidas para los $edgefloat (tenga en cuenta que son los valores del componente los que están soportados, sino sólo los valores relacionados con sus bordes). Si el “form” es más ancho o más alto que la pantalla, la flotación se produce sólo si los parámetros SettingsAllowHScroll o SettingsAllowVScroll están en estado falso. El modo en que los controles floten dependerá de la diferencia entre el ancho o la altura de la pantalla actual y el ancho o la altura diseñada en el “remote-form” y siempre según el valor más próximo al de su propiedad $screensize. El valor de $screensizefloat es guardado tras cada ajuste del $screensize del “remote-form”.

  • SettingsScaleForm
Si se ajusta a "1" (true), el cliente escalará el “form” hasta ajustarse al espacio de pantalla disponible. El factor de escala es el ancho de la pantalla o su altura dividido por la anchura o altura del valor más cercano a $screensize. Se usa, el tamaño real de la pantalla, el cual incluyen las áreas reservadas al sistema operativo, tales como la barra de estado.

  • SettingsAllowHScroll y SettingsAllowVScroll
Deberá fijar sus valores a "1" si desea permitir el desplazamiento horizontal o vertical del “form” respectivamente, o "0" en caso contrario.

  • SettingsMaintainAspectRatio
Si se ajusta a "1", el escalado mantiene la relación de aspecto del “form”. Si está activado y en función del estado de SettingsAllowHScroll y SettingsAllowVScroll, será posible reducir el factor de escala en una dirección específica, con el fin de ajustar el “form” y su centrado vertical u horizontal según se requiera.

  • SettingsOnlineMode
La aplicación se iniciará en modo “On-line”.

  • ServerOmnisWebUrl
URL del servidor Omnis o del Servidor Web. Si utiliza un servidor de Omnis debería ser http://:. Si utiliza un servidor web deberá ser la URL raíz de su servidor Web, http://miservidor.com.
  • ServerOnlineFormName
Ruta del “form” en el fichero .htm del ServerOmnisWebUrl. De modo que si usted está testando una aplicación en construcción sobre un servidor de aplicaciones Omnis, será de la forma /jschtml/miform.htm, pero si está utilizando un servidor web, la URL tendrá la forma /omnisapps/miform. (¡Sin añadir la extensión .htm!)
De modo que las propiedades ServerOmnisWebUrl y ServerOnlineFormName son sólo necesarias para “forms” usados en modo “on-line”. El resto de propiedades son sólo para el modo “off-line”.
  • ServerOmnisServer
Servidor Omnis ≤Dirección IP≥:≤Puerto≥.
  • ServerOmnisPlugin
Si se está utilizando un servidor web con plug-in para conectar con Omnis, será la ruta a añadida desde el raíz ServerOmnisWebUrl. Por ejemplo: /cgi-bin/omnisapi.dll

  • ServerOfflineFormName
Nombre del formulario “on-line”. (¡No añada .htm!)
  • ServerAppScafName
Nombre de la aplicación SCAF. Será el mismo nombre que tiene la librería.
  • TestModeEnabled
Permite activar el modo de pruebas (Pulsando Ctrl-M se permitirá testar el “form” sobre el dispositivo remoto)
  • TestModeServerAndPort
Dirección ≤ipaddress≥:≤puerto≥, si se desea hacer uso del modo test mediante Omnis Studio Developer.
También es posible modificar estos parámetros pulsando el botón de menú en el dispositivo móvil y activando las opciones de cambio. La aplicación recuerda el último ajuste realizado a través del menú, por lo que la configuración suministrada mediante el fichero config.xml sólo servirá para suministrar los valores iniciales del wrapper.

02 julio 2014

jsClient: Testando “remote-forms” incluidos en un wrapper JavaScript

Durante el desarrollo es posible la apertura de un “remote-form” JavaScript incluido en un wrapper, mediante la opción “Test Form Mobile” (Ctrl-M), siempre que el wrapper esté configurado y habilitado para ello (de lo contrario sólo podrá testar los “forms” sobre un navegador de tipo escritorio y antes de la configuración del wrapper). Esta opción aparece debajo de la opción “Test Form” en el menú contextual del “remote-form”. La opción “Test Form Mobile” se mostrará sólo bajo las siguientes circunstancias:
  1. Que esté habilitado el "modo test" en el dispositivo remoto (ver el menú de aplicación en caso de Android, y el de configuración del sistema en caso de iOS)
  2. Que estén habilitadas las opciones correspondientes sobre el servidor de aplicaciones Omnis, mediante los parámetros para el modo “test form”.

La propiedad $designshowmobiletitle determinará si será o no visible el título de la aplicación wrapper, mientras se esté utilizando la opción “Test Form Mobile” (Ctrl-M). Para su implementación deberá consignar el título a mostrar sobre el fichero config.xml.

01 julio 2014

¿Qué podemos esperar de Omnis Studio 6.1?

64 bits


El ejecutable Omnis ha sido rediseñado para funcionar con procesadores de 64 bits, aún así deberemos esperar un poco, pues inicialmente sólo estará disponible en la modalidad servidor. Estaremos atentos desde éste blog al anuncio sobre su disponibilidad en la modalidad SDK. 

 

Componentes JavaScript


Los controles JavaScript tendrán una apariencia "nativa" es decir, mostraran el aspecto que corresponda a la plataforma en que se estén ejecutando. Su estilo vendrá determinado por las reglas CSS correspondientes. Estos componentes estarán localizados como un nuevo grupo dentro del "Component Store". Además de esto, todos los componentes han sido optimizados para mejorar su rendimiento, siendo posible alternar entre diferentes tamaños de pantalla ($screensize) soportados por un "remote-form", mediante simplemente pulsar las teclas Ctrl-N/Cmnd-N o bien seleccionando la opción correspondiente del menu contextual.
 

Nueva herramienta para la sincronización de componentes


Permite la configuración automática de los componentes ya utilizados en los "remote-form" según los diferentes diseños, lo que se traducirá en un considerable ahorro de tiempo a la hora de hacer que nuestras aplicaciones ofrezcan un mejor aspecto.
 

Servicios Web


Se añade soporte para servicios web "RESTful": permite tanto la creación de la interfaz de usuario necesaria para el uso de servicios web RESTful, como el hacer disponible el código  para el acceso a clientes externos. Además, de esto se ha añadido un nuevo componente externo denominado OJSON para permitir el uso de objetos basados en​JSON con RESTful.

Vista previa de impresión


Se ha rediseñado la ventana de vista previa, permitiendo al usuario seleccionar el texto de las páginas en pantalla, además de poder navegar por ellas mediante un índice conteniendo una miniatura de las mismas, situado al margen de la ventana.
 

Tarea inicial de la librería (Library Startup Task)


Una nueva preferencia denominada $clibstartuptask nos permitirá indicar cual será la tarea de inicio para la lbrería en ejecución.
 

Número máxima de líneas de código permitidas en un sólo método


¿Habías pensado alguna vez en escribir una aplicación Omnis en un sólo método? ;-)
El número máximo de líneas en un método ha sido aumentado de 1.024 a 256.000.
 

Comparar variables


Ahora es posible establecer comparaciones entre variables binarias, variables de objeto y  variables de referencia a objetos, con la única precaución de que las usadas en cada lado del operador sean del mismo tipo.
 

Separadores multi-hilo


Cada hilo (en un servidor de aplicaciones Omnis multi-hilo) puede tener sus propios identificadores de separación para el punto decimal, indicador de miles y forma decimal usada en importaciones, almacenados bajo la propiedad $separators.
 

Eliminación automática de "Object references" (referencias a objetos)


Las referencias a objetos se borran automáticamente cuando ya no sean necesarias con el fin de liberar memoria.