Los que ya tenemos unos añitos y hemos llegado al AS/400 desde sus abuelos (el S/34 y
su sucesor, el venerado S/36) recordamos con añoranza una instrucción del lenguaje OCL
que decía lo siguiente:// IF ACTIVE-Nombre Procedimiento (Hacer tal cosa...)
Esta sencilla instrucción nos permitía poder controlar si un procedimiento en
concreto estaba en ejecución en ese momento y de esa forma decidir, de forma automática,
lo que debíamos hacer a continuación.
Por ejemplo: Un proceso de contabilización de facturas que es incompatible consigo
mismo podía, a través de esta instrucción, auto-controlarse evitando que dos usuarios
solicitaran el mismo proceso a la vez.
Sin embargo, y a pesar de la gran utilidad de esta instrucción, el OS/400 (desde sus
orígenes) no incluye ningún mandato equivalente, con lo cual podemos hacer 2 cosas:
- Fiarnos de la buena voluntad y coordinación de los usuarios.
- Simular, lo más parecido posible, el añorado IF ACTIVE.
El ejemplo que se describe a continuación pretende simular esta función, eso sí con
limitaciones, todos los procesos que debamos controlar deberán ser conocidos "a
priori" cosa que no ocurría con IF ACTIVE que podía ser incluido en cualquier
momento del desarrollo, sin afectar al procedimiento que deseábamos controlar. Este
ejemplo está basado en el caso descrito anteriormente, un proceso de contabilización de
facturas incompatible consigo mismo y que consigue avisar al usuario de que dicho proceso
ya ha sido solicitado:
/* */
/* FACTURACION - ENLACE A CONTABILIDAD (PETICION) */
/* */
PGM
/* Definición de variables */
DCLF FILE(TIFE01FM) RCDFMT(TIFE0102)
DCL VAR(&FECENL) TYPE(*CHAR) LEN(8)
DCL VAR(&PANTALLA) TYPE(*CHAR) LEN(10)
/* Si ya está activo el enlace da error */
ALCOBJ OBJ((TIFE01C *PGM *EXCL)) WAIT(0) (1)
MONMSG MSGID(CPF1002) EXEC(DO)
SNDRCVF RCDFMT(TIFE0102)
GOTO CMDLBL(FINAL)
ENDDO
/* Solicita fecha tope para enlace */
CALL PGM(TIFE01) PARM(&FECENL)
/* Somete el resto del proceso de enlace */
IF COND(&FECENL *NE ' ') THEN(DO)
RTVJOBA JOB(&PANTALLA)
SBMJOB CMD(CALL PGM(TIFE01C1) PARM(&FECENL +
&PANTALLA)) JOB(ENLACECONT) JOBQ(QS36EVOKE)
ENDDO
/* Desbloquea objeto de control */
DLCOBJ OBJ((TIFE01C *PGM *EXCL)) (2)
FINAL: ENDPGM
/* */
/* FACTURACION - ENLACE A CONTABILIDAD (PROCESO) */
/* */
PGM PARM(&FECENL &PANTALLA)
/* Definición de variables */
DCL VAR(&FECENL) TYPE(*CHAR) LEN(8)
DCL VAR(&ULTFRA) TYPE(*CHAR) LEN(24)
DCL VAR(&PANTALLA) TYPE(*CHAR) LEN(10)
DCL VAR(&EJERCICIO) TYPE(*CHAR) LEN(2)
DCL VAR(&ERROR) TYPE(*CHAR) LEN(1)
/* Bloquea objeto de control */
BLOQUEO: ALCOBJ OBJ((TIFE01C *PGM *EXCL)) WAIT(0) (3)
MONMSG MSGID(CPF1002) EXEC(GOTO CMDLBL(BLOQUEO))
...Resto del programa...
/* Desbloquea objeto de control */
FINAL: DLCOBJ OBJ((TIFE01C *PGM *EXCL)) (4)
ENDPGM
Como habéis podido comprobar, el primer CL lo primero que hace (1) es bloquearse a sí
mismo (podría bloquear cualquier otro objeto) y en el caso de que ya esté bloqueado
presenta una pantalla avisando que el proceso no se puede ejecutar y finaliza.
El segundo CL (sometido por el primero si todo va bien) también bloquea el mismo
objeto (3) la diferencia es que, si está bloqueado, no da ningún error simplemente se
mete en un bucle esperando que el programa que le ha llamado (el que tiene el bloqueo) lo
libere (2).
Antes de finalizar el segundo CL, se desbloquea el objeto (4) para que el proceso pueda
ser llamado de nuevo. Este último punto no es necesario si el proceso se ejecuta en BATCH
(como en este caso) pero será imprescindible si el segundo CL es ejecutado en modo
interactivo ya que los bloqueos de objetos se mantienen durante toda la ejecución del
trabajo, a no ser que se desbloqueen explícitamente como en este caso.
La ventaja de usar este método frente a otros basados en la creación de objetos o
actualización de Areas de Datos estriba en que en el caso de que el proceso se interrumpa
(el famoso corte de luz cuando menos hace falta) de esta forma no queda "basura"
en el sistema y cuando se re-inicia, todo queda tal cual estaba antes del
"apagón".
Espero que este pequeño truco consuele a los que, como yo, todavía añoramos algunas
funciones del desaparecido SSP.
Juan Ramon García

|