Desarrollando en Cobol y Natural sobre Plataforma Mainframe

lunes, 27 de julio de 2015

Utilidad ICETOOL para JCL. ¿Cómo usarla? (1)

La utilidad ICETOOL es una aplicación que se distribuye junto con la herramienta ICEMAN. Se trata de un servicio que es capaz de aprovechar las propiedades y las funciones de DFSORT para ejecutar, en un único paso de JCL, múltiples operaciones sobre varios ficheros secuenciales. Dicho esto, entiendo que no es necesario hacer demasiado hincapié en el considerable ahorro de tiempo que conlleva su empleo.

¿Para qué sirve la utilidad ICETOOL de ICEMAN?


La utilidad ICETOOL nos permite realizar las mismas funciones que las herramientas ICEMAN y DFSORT, pero usando un menor número de pasos en el JCL. Puede que, en un principio, las sentencias ICETOOL nos parezcan menos intuitivas que las de un DFSORT pero, una vez nos hayamos acostumbrado a su empleo, el ahorro de tiempo y de código será considerable.

Aunque, en general, se utiliza para realizar ordenaciones y cruces de registros de ficheros secuenciales, en realidad esta utilidad puede ejecutar muchas funciones más. En total, ICETOOL dispone de 17 operadores que, además, pueden ser usados en combinación unos con otros.



Los operadores mencionados serían los siguientes: COPY, COUNT, DATASORT, DEFAULTS, DISPLAY, MERGE, MODE, OCCUR, RANGE, RESIZE, SELECT, SORT, SPLICE, STATS, SUBSET, UNIQUE y VERIFY. Obviamente, no todos tienen la misma importancia y, de hecho, algunos de ellos no los vamos a usar prácticamente nunca.

Operadores principales de la utilidad ICETOOL


A continuación, vamos a hacer un repaso de los operadores ICETOOL que, según mi opinión, son los más importantes. Aunque (tal y como he dicho antes) tenemos 17 funciones disponibles, muchas de ellas sólo las he usado una vez en mi vida como programador Cobol. Por tanto, no merece la pena dedicar demasiado tiempo a examinarlas.

La lista de los principales operadores ICETOOL de la herramienta ICEMAN (esto es, los que yo empleo más a menudo) es la siguiente.

- Operador COPY: Este comando permite copiar la información de un fichero de entrada a uno o varios ficheros de salida (algo similar, pero más potente, a lo que hace la utilidad IEBCOPY). Esta copia se realiza siguiendo las condiciones especificadas en una ficha de Control definida por nosotros. Un ejemplo del uso de este operador sería el siguiente. 

*------------------------------------------------------
* <<< OPERADOR COPY >>>                               
* COPIA CONTENIDO DEL FICHERO ENTRADA AL FICHERO SALIDA
* LAS CONDICIONES SE INDICAN EN LA FICHA CONTROL
*------------------------------------------------------
  COPY FROM(ENTRADA) TO(SALIDA) USING(CONTROL)    

*------------------------------------------------------
* <<< FICHA CONTROL DE COPY >>>              
* CONDICIONES PARA REALIZAR LA FUNCION COPY
*------------------------------------------------------
  INREC FIELDS=(43,6,1,88)        
  SORT FIELDS=(1,4,PD,A,5,2,PD,A) 
  OUTREC FIELDS=(1,432,433:C' ',6X)
       


- Operador COUNT: Este comando sirve para contar los registros existentes en un fichero de entrada y generar un fichero de salida en el que se imprima el texto que indiquemos y el resultado del contador. Al igual que en el caso anterior, esta acción se realiza cumpliendo las condiciones que especifiquemos en la ficha de Control. 

*------------------------------------------------------
* <<< OPERADOR COUNT >>>         
* CUENTA REGISTROS DEL FICHERO ENTRADA E IMPRIME EL
* RESULTADO EN EL FICHERO SALIDA
*------------------------------------------------------
  COUNT FROM(ENTR) USING(CTRL) WRITE(SALI) TEXT('CONT: ')

*------------------------------------------------------
* <<< FICHA CONTROL DE COUNT >>>           
* CONDICIONES PARA REALIZAR LA FUNCION COUNT
*------------------------------------------------------
  INCLUDE COND=(420,1,CH,EQ,C'.')

- Operador MERGE: Este comando sirve para tomar varios ficheros de entrada y unirlos en un fichero de salida. Esta unión se realizará siguiendo las condiciones indicadas en la ficha de control asociada.

- Operador SORT: Este operador sirve para ejecutar la ordenación de los registros de un fichero de entrada y enviar el resultado a uno o varios ficheros de salida. Esta función sería análoga al SORT realizado por las herramientas DFSORT o ICEMAN, una de las operaciones utilizadas más frecuentemente en el mundo JCL. 

*------------------------------------------------------
* <<< OPERADOR SORT >>>         
* ORDENA REGISTROS DEL FICHERO ENTRADA Y ENVIA EL
* RESULTADO AL FICHERO SALIDA
*------------------------------------------------------
  SORT FROM(ENTR) TO (SALI) USING(CTLR)

*------------------------------------------------------
* <<< FICHA CONTROL DE SORT >>>           
* CONDICIONES PARA REALIZAR LA FUNCION SORT
*------------------------------------------------------
  SORT FIELDS=(1,4,PD,A,5,2,PD,A),DYNALLOC=3390    
  SUM  FIELDS=NONE


- Operador SPLICE: Se trata del operador más polivalente de ICETOOL. Este comando permite cruzar entre sí los registros de un fichero de entrada y realizar operaciones de filtrado, de unión o de coincidencia a partir de los campos de los mismos. Los registros de la entrada pueden proceder de la concatenación de varios ficheros origen y el resultado puede depositarse en uno o varios ficheros de salida.

Los registros a cruzar deben tener la misma longitud y el mismo formato/estructura de campos, pero pueden contener diferente información. Dichos campos podrán ser combinados de la forma que deseemos para generar un nuevo registro de salida. Las condiciones del SPLICE se deberán indicar en la ficha de control asociada.

En el código siguiente podemos ver un ejemplo de SPLICE. Se recogen los registros del fichero de entrada CONCAT y el resultado se deposita en el fichero de salida SALI. En las cláusulas ON indicamos las posiciones de los campos por los que se tiene que realizar el cruce de los registros. En la cláusula WITH se indican las posiciones de los registros del fichero de entrada que deben ser transferidas al fichero de salida. Finalmente, las condiciones del cruce del SPLICE se especifican, como siempre, en la ficha CONTROL asociada. 

*------------------------------------------------------
* <<< OPERADOR SPLICE >>>
* CRUZA LOS REGISTROS DEL FICHERO CONCAT Y EL RESULTADO         
* FILTRADO SE DEPOSITA EN EL FICHERO SALI
*------------------------------------------------------
  SPLICE FROM(CONCAT) TO(SALI) ON(1,4,PD) ON(5,2,PD) -
  WITHALL WITH(1,110) USING(CONTROL)

*------------------------------------------------------
* <<< FICHA CONTROL DE SPLICE >>>                         
* CONDICIONES PARA REALIZAR LA FUNCION SPLICE
*------------------------------------------------------
  OUTFIL FNAMES=OUT,
  INCLUDE=(111,1,CH,EQ,C'D'),
  OUTREC=(112,6,7,55,62:C'&',88,23)



Tal y como hemos dicho al principio, en total ICETOOL dispone de 17 funciones asociadas pero, a la hora de la verdad, las indicadas anteriormente son las que se suelen emplear en el día a día. Eso sí, no viene mal saber que tenemos otras opciones disponibles, por si en algún momento nos hacen falta.

Una vez vistos los operadores principales, el próximo día (en un nuevo post) trataremos de ver algo más práctico. La idea será revisar, mediante un ejemplo, de qué forma habría que codificar un paso estándar de JCL para ejecutar un operador de ICETOOL.

Pues nada, quedáis emplazados a la segunda parte de la explicación. Espero que, entre ambos post, la cosa quede lo suficientemente clara como para que podáis empezar a usar la herramienta en alguno de vuestros JCL.

Saludos.

lunes, 20 de julio de 2015

JCL para buscar en múltiples Librerías (y 2)

Hace algunas semanas comenzamos a ver cómo podíamos implementar un JCL que nos permitiese realizar búsquedas de objetos en varias librerías a la vez. Recordemos que este Job nos puede ser muy útil cuando tengamos que buscar cualquier cadena de texto en los programas de una aplicación que esté compuesta de múltiples librerías.

En la primera parte del artículo estuvimos examinando varias de las fichas necesarias para codificar el proceso (ver post JCL para buscar Cobol en múltiples librerías - 1). Hoy vamos a terminar de revisar el resto de las fichas requeridas, de manera que ya tengamos la visión global del JCL de búsqueda.
 
5º) Librerías de Búsqueda: A continuación, en la ficha NEWDD tenemos que introducir todas las librerías en las que deseamos realizar la búsqueda de nuestra cadena de texto. Como vemos, en el ejemplo yo he introducido un total de 12 librerías.

//NEWDD  DD DSN=JJPR.V7R00.CON.JJMU.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJST.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJGU.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJAN.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJPL.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJRG.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJGM.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJTF.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJBL.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJPU.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJRV.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJPR.FUENTES,DISP=SHR


6º) Nombre del fichero con las búsquedas realizadas: En la ficha OUTDD simplemente tendremos que indicar el nombre del fichero secuencial en el que deseamos que se almacenen los resultados de nuestra búsqueda múltiple. En el ejemplo, hemos decidido almacenar esta información en JJPR.V7R01.JJST.BUSCADOR.

//OUTDD  DD DISP=(NEW,CATLG,DELETE),SPACE=(TRK,(10,10)),
//          DSN=JJPR.V7R01.JJST.BUSCADOR 
            


7º) Parámetros de entrada: Aquí  tendremos que introducir la ficha SYSIN que nos permitirá enviar información de entrada a la utilidad ISRSUPC de comparación de códigos.

//SYSIN  DD *                                          


8º) Cadena de texto a buscar: Finalmente, tendremos que especificar el comando SRCHFOR y, a continuación, la cadena de texto que la herramienta debe buscar entre los objetos de todas las librerías indicadas anteriormente. En el ejemplo, tal y como se aprecia, se ha introducido el texto ‘CADENATX’.

SRCHFOR  'CADENATX'
/*
          

La ejecución del JCL con todos estos pasos puede demorarse bastantes minutos, sobre todo si hemos especificado una cantidad importante de librerías. En cualquier caso, si hemos detallado correctamente todas las fichas del proceso, el job debería completarse sin problema alguno.

Ejecución del JCL de Búsqueda en Librerías Múltiples


Imaginemos que el JCL termina sin generar ningún ABEND. Una vez finalizado el proceso, la información de la búsqueda quedará almacenada en el fichero secuencial JJPR.V7R01.JJST.BUSCADOR, donde podremos consultar los resultados tantas veces como deseemos.


Para ello, tendremos que ir a la opción 3.4 del ISPF y buscar los datasets JJPR.V7R01.JJST*. Al hacer esto, en mi terminal aparece la siguiente información.

Command - Enter "/" to select action               
------------------------------------------------------
            JJPR.V7R01.JJST.BUSCADOR              
            JJPR.V7R01.JJST.BUSCEXPL              
***************************** End of Data Set list ***


Como se aprecia, en el listado aparecen dos ficheros y uno de ellos es el que acaba de generar nuestro proceso de búsqueda: JJPR.V7R01.JJST.BUSCADOR.  A continuación, podríamos seleccionar este objeto y visualizar su contenido.

***************************** Top of Data ******************************
1  ISRSUPC   -   MVS/PDF FILE/LINE/WORD/BYTE/SFOR COMPARE UTILITY- ISPF
  LINE-#  SOURCE SECTION                    SRCH DSN:    JJPR.V7R00.CON.
                                                                     
                                                                     
  JJTD00CO CONCAT#(4)       ----------- STRING(S) FOUND ----------------
                                                                      
       7         PROGRAM-ID.     CADENATX.                           
      14        *   PROGRAMA    : CADENATX                           
    1695                MOVE 'CADENATX'       TO PROGRAMA-W          
                                                                     
1  ISRSUPC   -   MVS/PDF FILE/LINE/WORD/BYTE/SFOR COMPARE UTILITY- ISPF
      SEARCH-FOR SUMMARY SECTION            SRCH DSN:    JJPR.V7R00.CON.
                                                                     
 LINES-FOUND  LINES-PROC  MEMBERS-W/LNS  MEMBERS-WO/LNS  COMPARE-COLS  L
         3      7231209            1           5639           1:80   

              
THE FOLLOWING PROCESS STATEMENTS (USING COLUMNS 1:72) WERE PROCESSED:
   SRCHFOR  'CADENATX'                                              
                                                                    
THE FOLLOWING "SRH" FILE CONCATENATED DATA SETS WERE SPECIFIED:
   (1)    JJPR.V7R00.CON.JJMU.FUENTES                               
   (2)    JJPR.V7R00.CON.JJST.FUENTES                               
   (3)    JJPR.V7R00.CON.JJGU.FUENTES                               
   (4)    JJPR.V7R00.CON.JJAN.FUENTES                               
   (5)    JJPR.V7R00.CON.JJPL.FUENTES                               
   (6)    JJPR.V7R00.CON.JJRG.FUENTES                                
   (7)    JJPR.V7R00.CON.JJGM.FUENTES                               
   (8)    JJPR.V7R00.CON.JJTF.FUENTES                               
   (9)    JJPR.V7R00.CON.JJBL.FUENTES                               
  (10)    JJPR.V7R00.CON.JJPU.FUENTES                               
  (11)    JJPR.V7R00.CON.JJRV.FUENTES                               
  (12)    JJPR.V7R00.CON.JJPR.FUENTES                               
                
**************************** Bottom of Data ****************************


En la salida podemos observar que, una vez revisadas las 12 librerías, el literal ‘CADENATX’ ha sido encontrado en una única ubicación: se trata del objeto Cobol denominado JJTD00CO. De hecho, el texto buscado aparece hasta 3 veces en dicho programa. Esto se indica claramente al principio del fichero JJPR.V7R01.JJST.BUSCADOR.

  JJTD00CO CONCAT#(4)       ----------- STRING(S) FOUND -------
                                                                      
       7         PROGRAM-ID.     CADENATX.
      14        *   PROGRAMA    : CADENATX
    1695                MOVE 'CADENATX'       TO PROGRAMA-W
     


Conclusiones de la Búsqueda en Librerías Múltiples


Como se puede ver, la ejecución de este JCL buscador nos ha permitido revisar rápidamente varias librerías a la vez (hasta 12, en el ejemplo) y detectar cuáles son los objetos de las mismas que contienen la cadena de texto buscada. La información extraída queda almacenada en un fichero secuencial, donde será fácilmente accesible siempre que necesitemos acudir a ella.

Esta forma de búsqueda supone un considerable ahorro de tiempo frente al procedimiento que hay que realizar mediante la utilidad estándar Search-For Utility (3.14) del ISPF. Obviamente, quien quiera puede seguir usando la 3.14 para búsquedas múltiples. Sin embargo, aunque nos cueste al principio, yo creo que es importante adaptarse y aprender a utilizar las herramientas que nos van a consumir menos tiempo a largo plazo.


De hecho, si seguís los pasos que hemos examinado a lo largo del post, no creo que tengáis muchos problemas para elaborar vuestro propio JCL buscador. En cualquier caso, tened en cuenta que tendréis que adaptarlo a las características particulares de vuestra instalación y a las librerías que tenga asociadas vuestra aplicación.

Pues nada, eso es todo por hoy. Espero que, con lo explicado, os haya quedado clara la forma de realizar búsquedas múltiples. Si tenéis alguna duda al respecto, ya sabéis que podéis incluirla en los comentarios de aquí abajo y yo trataré de resolverla lo antes posible…

Saludos.

lunes, 13 de julio de 2015

JCL para buscar en múltiples Librerías (1)

Cualquier programador Cobol que haya trabajado con la herramienta ISPF conoce la ventana “Search-For Utility” (opción 3.14).  Dicha utilidad resulta enormemente cómoda para localizar una cadena de texto entre los componentes de una determinada librería. Por desgracia, la opción 3.14 no nos permite buscar algo en varias librerías a la vez. Hoy veremos una forma de solucionar este problema y de llevar a cabo dicha acción.


Buscar algo en varias librerías a la vez

 

Imaginaos, como me pasó a mi hace algunas semanas, que tuviésemos que identificar cuáles son los programas de nuestra aplicación que invocan a un determinado objeto. Si nuestro sistema tiene una única librería, podremos usar la utilidad Search-For Utility y obtener el resultado rápidamente. Por desgracia, la instalación de este cliente tiene hasta 12 librerías distintas y, por tanto, sería algo tedioso ejecutar las búsquedas una a una con la opción 3.14 del ISPF. ¿Cómo podríamos agilizar este proceso?

Una de las formas de subsanar este problema sería crearnos un JCL que vaya ejecutando, de forma secuencial, la búsqueda de la cadena en cada una de las librerías afectadas. Esta es la solución que vamos a analizar hoy y, al final del post, no os debería resultar difícil replicar el procedimiento en vuestra propia instalación.


Para abordar esta tarea, en primer lugar voy a mostrar uno de los Jobs que suelo emplear para realizar las búsquedas en múltiples librerías.

//SEARCH1B JOB (0,AT60,1440,0005),                         
//             '60360000000.CDD',MSGLEVEL=(1,1),        
//             MSGCLASS=X,CLASS=A,REGION=4M,NOTIFY=&SYSUID
//*                                                     
//BORRAR1  EXEC PGM=IEFBR14
//*                                
//FICHERO  DD  DSN=JJPR.V7R01.JJST.BUSCADOR,         
//             DISP=(MOD,DELETE),                       
//             SPACE=(TRK,0),                           
//             UNIT=DISCO                                
//*                                                     
//BORRAR1A EXEC PGM=ABEN3333,                           
//             COND=(4,GE,BORRAR1)                      
//CTRNORST DD  DUMMY                                    
//*                                                     
//SEARCH  EXEC PGM=ISRSUPC,                           
//            PARM=(SRCHCMP,'')                          
//*                                     
//NEWDD  DD DSN=JJPR.V7R00.CON.JJMU.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJST.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJGU.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJAN.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJPL.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJRG.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJGM.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJTF.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJBL.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJPU.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJRV.FUENTES,DISP=SHR
//       DD DSN=JJPR.V7R00.CON.JJPR.FUENTES,DISP=SHR
//* 
//OUTDD  DD DISP=(NEW,CATLG,DELETE),SPACE=(TRK,(10,10)),
//          DSN=JJPR.V7R01.JJST.BUSCADOR           
//SYSIN  DD *                                         
SRCHFOR  'CADENATX'
/*


A continuación, voy a intentar explicaros con un poco de detalle qué es lo que tenemos que especificar en cada una de las fichas del JCL anterior.

Fichas del JCL de búsqueda en librerías múltiples



A la hora de tratar de trasladar a nuestras propias librerías cualquier JCL que encontremos publicado en un blog, lo importante es que tengamos claro para qué sirve cada una de las fichas de las que se compone. En caso contrario, lo más probable es que, al menor contratiempo, ya no seamos capaces de adaptar el código.

Para que este proceso os resulte lo más sencillo posible, vamos a ir repasando en detalle cada una de las fichas anteriores.

1º) Borrado del fichero de salida: En primer lugar, vamos a proceder a borrar el fichero donde se van a volcar los datos obtenidos por el proceso. Hay que tener en cuenta que el JCL va a usar un fichero secuencial para ir almacenando toda la información que vaya recogiendo en la búsqueda por las distintas librerías. Y, como este dataset podría estar ya creado debido a una ejecución previa, lo primero que tenemos que hacer es un borrado del mismo.

//BORRAR1  EXEC PGM=IEFBR14


2º) Nombre del fichero a borrar: En la ficha FICHERO tendremos que introducir el nombre del fichero secuencial que debe ser borrado por la utilidad IEFBR14 (especificada en el paso anterior). En el ejemplo, se trata del fichero JJPR.V7R01.JJST.BUSCADOR.

//FICHERO  DD  DSN=JJPR.V7R01.JJST.BUSCADOR,        
//             DISP=(MOD,DELETE),                      
//             SPACE=(TRK,0),                          
//             UNIT=DISCO



3º) Control de errores: En la ficha BORRAR1A establecemos un control de errores del paso anterior. En el caso de que, al ejecutar BORRAR1, se obtenga un código de retorno RC (Return Code) igual o mayor que 04, se lanzará el programa ABEN3333. Este paso no es obligatorio y lo incluiremos en nuestro JCL sólo si queremos establecer una gestión de errores específica en un proceso concreto.

//BORRAR1A EXEC PGM=ABEN3333,                          
//             COND=(4,GE,BORRAR1)                     
//CTRNORST DD  DUMMY
                                  

4º) Utilidad de Búsqueda: En la ficha SEARCH incluiremos una invocación, mediante el comando PGM, a la utilidad ISRSUPC. Esta herramienta forma parte del catálogo estándar de servicios y permite comparar códigos mediante JCL. En la cláusula PARM se especificarán los parámetros con los que se debe ejecutar dicha utilidad.

//SEARCH  EXEC PGM=ISRSUPC,                          
//            PARM=(SRCHCMP,'')



El próximo día, en un nuevo post, continuaremos viendo cómo se debe implementar el Job para realizar una búsqueda en varias librerías a la vez. Recordad que es importante tener claro en qué consiste cada una de la fichas del JCL antes de ponerse a lanzar el proceso sin ton ni son.

Pues nada, eso es todo por hoy. Quedáis invitados a la segunda parte del artículo, en la que espero que os quede totalmente clara la forma en la que hay que codificar este procedimiento.

Saludos.

viernes, 10 de julio de 2015

Universo Cobol llega a las 30.000 visitas

Justo cuando el blog está cumpliendo los 2 años de vida, hoy tengo que pasarme por aquí para celebrar con vosotros que Universo Cobol acaba de llegar a las 30.000 visitas. En los primeros meses parecía imposible que pudiese alcanzarse esa cifra con un blog de Cobol, pero las estadísticas no engañan y nos están diciendo que ya hemos llegado a ese hito tan relevante.


Quería agradeceros vuestro granito de arena a todos los que os pasáis por aquí de vez en cuando. Sin vuestra ayuda esto no habría sido posible (evidentemente). Espero que las cosas sigan así de bien para el entorno Mainframe y que, dentro de otro par de años, podamos celebrar las 60.000 visitas.

¡Gracias a todos!

Saludos.

Related Posts Plugin for WordPress, Blogger...