viernes, 14 de agosto de 2015

ICETOOL: Como copiar ficheros en JCL (1)

Entre las muchas funciones de que dispone, la utilidad ICETOOL nos da la posibilidad de hacer copias de ficheros secuenciales en la operativa con JCL. Aunque existen otros servicios que realizan estas mismas operaciones, el rendimiento de ICETOOL es muy superior al de todos ellos.

Copiar Ficheros Secuenciales con ICETOOL


La utilidad ICETOOL nos permite aprovecharnos de las capacidades de la herramienta ICEMAN (DFSORT) para realizar copias de ficheros secuenciales de la manera más optimizada posible. Por tanto, aunque realiza la misma actividad que otros servicios tales como IEBGENER o ICEGENER, la ejecución será más eficiente.

A pesar de que la codificación con ICETOOL de ICEMAN es ligeramente diferente a la clásica (aquí os dejo un enlace a la Guía de Usuario ICETOOL de IBM), la realidad es que no es difícil acostumbrarse a ella. Yo llevo tiempo usándola para copias de ficheros con volúmenes de millones de registros y la verdad es que se agradece la mejora del rendimiento al realizar dicha operación.


Para ver cómo habría que implementar la copia de un fichero secuencial, vamos a usar como base un ejemplo real que estuvimos empleando en su día en uno de nuestros clientes. En primer lugar, muestro el código del paso JCL construido para tal fin.

//*        ****************************************************
//*        * EJECUCION ICETOOL                                *
//*        * COPIA FICHEROS IN1 / IN2 A FICHEROS OUT1 / OUT2  *
//*        ****************************************************
//JJ4605   EXEC PGM=ICETOOL                                          //TOOLMSG  DD  SYSOUT=*                                              //DFSMSG   DD  SYSOUT=*                                              //*        FICHEROS DE ENTRADA                   
//IN1      DD  DSN=&INDICE2..JJTV10K1.X0007X.DDD.F&FECHA..COMP3,     //             DISP=SHR                                             
//IN2      DD  DSN=&INDICE1..UNLOAD.X0005X.&DIA..&TABLA.,            //             DISP=SHR                                              //*        FICHEROS DE SALIDA REFORMATEADOS
//OUT1     DD  DSN=&INDICE1..JJ4605S1.X0060X.DDD.F&FECHA..&TAB..T1,
//             DISP=(NEW,CATLG,DELETE),
//             SPACE=(CYL,(00100,00100),RLSE),             //             UNIT=DISCO                                            //OUT2     DD  DSN=&INDICE1..JJ4605S2.X0060X.DDD.F&FECHA..&TAB..T2,

//             DISP=(NEW,CATLG,DELETE),              
//             SPACE=(CYL,(00100,00100),RLSE),                     //             UNIT=DISCO                                           //TOOLIN   DD  DSN=&INDICE..SYSIN(FITOOL),                        //             DISP=SHR                                            //CTL1CNTL DD  DSN=&INDICE..SYSIN(FICTL1),                        //             DISP=SHR                                             //CTL2CNTL DD  DSN=&INDICE..SYSIN(FICTL2),                        //             DISP=SHR                                             //JJ4605A  EXEC PGM=ABEN3333,                                       //             COND=(4,GE,JJ4605)                                   //CTRNORST DD  DUMMY                                                //*

A continuación, muestro el código de las tres fichas asociadas al paso JCL anterior. La primera de ellas es la ficha TOOLIN y las otras dos son fichas de CONTROL.

*-----------------------------------------------------------------*
* <<< FICHA TOOLIN FITOOL >>>     

* COPIA FICHERO KEYS REFORMATEADO AL FICHERO OUT1 
* COPIA FICHERO MASTER REFORMATEADO AL FICHERO OUT2     
*-----------------------------------------------------------------*
  COPY FROM(IN1)     TO(OUT1)    USING(CTL1)  

  COPY FROM(IN2)     TO(OUT2)    USING(CTL2)

*-------------------------------------------------------             
* <<< FICHA CONTROL FICTL1 >>>                      

* SE INDICA COMO SE DEBE REFORMATEAR EL FICHERO IN1              *-------------------------------------------------------             
  SORT FIELDS=(1,4,PD,A,5,2,PD,A)                                   

  OUTREC FIELDS=(1,21,193X,215:C'D',9,6)                            

*-----------------------------------------------------------------*
* <<< FICHA CONTROL FICTL2 >>>

* SE INDICA COMO SE DEBE REFORMATEAR EL FICHERO IN2          *-----------------------------------------------------------------*
  INREC FIELDS=(1,6,1,208)                                          

  SORT FIELDS=(1,4,PD,A,5,2,PD,A)                                   
  OUTREC FIELDS=(1,214,215:C' ',6X)

Detalle de Fichas del operador COPY de ICETOOL


Una vez mostrado el código estándar de un paso JCL que utiliza ICETOOL para copiar ficheros secuenciales, vamos a ver con un poco más de detalle en qué consisten cada una de las fichas requeridas por este proceso.


1º) Invocación a ICETOOL: La primera ficha es simplemente la invocación a la herramienta ICETOOL mediante el comando estándar EXEC PGM.

//JJ4605   EXEC PGM=ICETOOL

2º) Fichas IN1 e IN2: Se trata de las fichas en las que vamos a declarar el nombre de los ficheros de entrada que van a ser empleados por la utilidad. En nuestro ejemplo, hablamos de los ficheros &INDICE2..JJTV10K1.X0007X.DDD.F&FECHA..COMP3 y &INDICE1..UNLOAD.X0005X.&DIA..&TABLA.

//*        FICHEROS DE ENTRADA                   
//IN1      DD  DSN=&INDICE2..JJTV10K1.X0007X.DDD.F&FECHA..COMP3,     //             DISP=SHR                                             
//IN2      DD  DSN=&INDICE1..UNLOAD.X0005X.&DIA..&TABLA.,            //             DISP=SHR

3º) Fichas OUT1 y OUT2: En este caso, hablamos de las fichas empleadas para indicar los nombres de los ficheros de salida de la utilidad. En el ejemplo, son los ficheros &INDICE1..JJ4605S1.X0060X.DDD.F&FECHA..&TAB..T1 y &INDICE1..JJ4605S2.X0060X.DDD.F&FECHA..&TAB..T2.

//*        FICHEROS DE SALIDA REFORMATEADOS
//OUT1     DD  DSN=&INDICE1..JJ4605S1.X0060X.DDD.F&FECHA..&TAB..T1,
//             DISP=(NEW,CATLG,DELETE),
//             SPACE=(CYL,(00100,00100),RLSE),             //             UNIT=DISCO                                            //OUT2     DD  DSN=&INDICE1..JJ4605S2.X0060X.DDD.F&FECHA..&TAB..T2,

//             DISP=(NEW,CATLG,DELETE),              
//             SPACE=(CYL,(00100,00100),RLSE),                     //             UNIT=DISCO  

Tal y como se puede apreciar, al tratarse de ficheros nuevos, en la declaración estamos definiendo la estructura con la que tienen que crearse ambos datasets. En este caso, se darán de alta con memoria principal y memoria secundaria de 100 cilindros.


4º) Ficha TOOLIN: Llegamos a la ficha en la que tenemos que indicar cuál es el operador que tiene que ejecutar la utilidad ICETOOL (en particular, aquí se apunta al objeto FITOOL). Como queremos realizar una copia de ficheros secuenciales, tendremos que incluir el comando COPY (uno para cada fichero a copiar).

* <<< FICHA TOOLIN FITOOL >>>    
  COPY FROM(IN1)     TO(OUT1)    USING(CTL1)  
  COPY FROM(IN2)     TO(OUT2)    USING(CTL2)
 
El próximo día, en la segunda parte, continuaremos viendo cuáles son las fichas necesarias para que nuestro JCL ejecute una copia de ficheros mediante ICETOOL. Entre ambos post ya nos debería quedar una idea bastante clara de cómo hay que implementar el proceso.

Pues nada, eso es todo por hoy. Creo que no hace falta que insista: estáis invitados a la segunda parte del artículo. Espero veros por aquí para completar la revisión del COPY ICETOOL.

Saludos.

lunes, 3 de agosto de 2015

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

Hace algunas semanas comenzamos a ver en qué consistía la utilidad ICETOOL de la herramienta ICEMAN. Se trata de un servicio que, en los JCL, simplifica enormemente la codificación de los pasos de ordenación, de copia o de cruce de registros de ficheros.

En la primera parte del post estuvimos viendo cuáles son las principales funciones que se pueden realizar con la utilidad ICETOOL (ver post Utilidad ICETOOL para JCL. ¿Cómo usarla? - 1). En esta segunda parte trataremos de explicar cómo se debe implementar un operador ICETOOL en un paso estándar de JCL.

¿Cómo se ejecuta la utilidad ICETOOL en un JCL?


Una vez expuestas las diferentes alternativas de las que disponemos con esta utilidad, nos quedaría pendiente ver cómo se podría desarrollar una función ICETOOL desde un JCL. En realidad, el empleo de esta herramienta en un paso JCL no tiene más dificultad añadida que la de cualquier otra utilidad clásica (tal como IEBGENER, IEBCOPY o DFSORT).

Para demostrarlo, vamos a incluir como ejemplo un fragmento de código con un paso JCL en el que se va a emplear la función COUNT de ICETOOL para contar el número de registros existentes en un fichero secuencial de entrada. Se trata del siguiente. 

//*    *********************************************     
//*    * PASO DE ICETOOL PARA CONTAR LOS REGISTROS *     
//*    *********************************************     
//JJ0101   EXEC PGM=ICETOOL                                         
//TOOLMSG  DD SYSOUT=*                                              
//DFSMSG   DD SYSOUT=*                                              
//INPUT    DD  DSN=SIST.UNLOAD.X0005X.DIA.POBL,           
//             DISP=SHR                                             
//OUT      DD  DSN=SIST.JJ0101S1.X0060X.DDD.FECHA.POBL,
//             DISP=(,CATLG,DELETE),                                
//             SPACE=(TRK,(00010,00010),RLSE),                      
//             UNIT=DISCO                                           
//TOOLIN   DD  DSN=SIST.SYSIN(CONTCT01),                      
//             DISP=SHR                                             
//CTL1CNTL DD  DSN=SIST.SYSIN(CONTCT02),                      
//             DISP=SHR                                             
//*
                                                                 

Las dos fichas asociadas a este paso JCL (denominadas CONTCT01 y CONTCT02), serían las siguientes. 

*------------------------------------------------------------*
* <<< FICHA TOOLIN CONTCT01 >>> 
* FICHA PARA REALIZAR EL COUNT DE LOS REGISTROS DE ENTRADA   *
*------------------------------------------------------------*
  COUNT FROM(INPUT) USING(CTL1) WRITE(OUT) TEXT('CONT: ')

*------------------------------------------------------------*
* <<< FICHA CONTROL CONTCT02 >>>
* FICHA PARA INDICAR LAS CONDICIONES DEL RECUENTO            *
*------------------------------------------------------------*
  INCLUDE COND=(48,1,CH,EQ,C'.')



Como vemos, para implementar una función ICETOOL en un JCL únicamente hay que incluir una serie de Fichas con un formato predefinido. A continuación, pasamos a repasarlas con un poco más de detalle.

1º) Invocación de ICETOOL: En la primera línea del paso tenemos que incluir la llamada a la utilidad ICETOOL. Esto se hace mediante una simple ejecución estándar del comando EXEC PGM. 

//JJ0101   EXEC PGM=ICETOOL

2º) Ficha INPUT: En esta declaración se debe incluir el nombre del fichero de entrada que va a ser empleado por la función ICETOOL (el  operador correspondiente a dicha función será definido más adelante). En nuestro ejemplo estamos usando el fichero SIST.UNLOAD.X0005X.DIA.POBL. 

//INPUT    DD  DSN=SIST.UNLOAD.X0005X.DIA.POBL, 
//             DISP=SHR



3º) Ficha OUT: De manera análoga a la ficha anterior, aquí tendremos que indicar el nombre que deseamos que tenga el fichero de salida que se va a crear al ejecutar la función ICETOOL correspondiente. En el ejemplo es el fichero SIST.JJ0101S1.X0060X.DDD.FECHA.POBL. 

//OUT      DD  DSN=SIST.JJ0101S1.X0060X.DDD.FECHA.POBL,
//             DISP=(,CATLG,DELETE),
//             SPACE=(TRK,(00010,00010),RLSE),
//             UNIT=DISCO

4º) Ficha TOOLIN: En esta ficha es en la que vamos a indicar cuál es la función ICETOOL que debe ejecutarse en nuestro paso. En el ejemplo se ha usado la función COUNT, pero también podría haberse empleado cualquiera de los 17 operadores que actualmente hay disponibles para la herramienta (COPY, MERGE, SORT, SPLICE, DISPLAY, etc…). 

  COUNT FROM(INPUT) USING(CTL1) WRITE(OUT) TEXT('CONT: ')

5º) Ficha de Control CTL1CNTL: Aquí se incluye la sentencia (o sentencias) de control asociada a la función ejecutada en la ficha anterior. En nuestro caso, el control INCLUDE COND=(48,1,CH,EQ,C’.’) está indicando que sólo se deben contar aquellos registros del fichero de entrada que en la posición 48 tengan un punto (‘.’). 

  INCLUDE COND=(48,1,CH,EQ,C'.')



Si implementamos todas las fichas anteriores tal y como se ha expuesto, no deberíamos tener ningún problema con la ejecución del paso TOOLIN. Obviamente, las primeras veces que trabajemos con esta herramienta nos resultará algo más complicado de lo que en realidad es, pero lo mismo ocurre con cualquier otra utilidad de cualquier otro lenguaje de programación.

Conclusiones de la utilidad ICETOOL de ICEMAN


En el ejemplo hemos podido ver cómo debería codificarse un paso JCL de recuento de registros mediante el comando COUNT de la utilidad ICETOOL de ICEMAN. Pero no exigiría mucho esfuerzo adicional implementar un paso de copia (COPY), de ordenación (SORT), de unión (MERGE) o de cruce de registros (SPLICE).



Tal y como puede apreciarse, la ventaja de esta herramienta es que nos permite realizar, en un mismo paso, varias acciones con ficheros, con el consiguiente ahorro de código y de tiempo. En el ejemplo comentado anteriormente se realizaron en un solo paso las siguientes acciones: 

- Filtrar los registros del fichero de entrada que tenían un determinado carácter en una posición definida.
- Contar el número de registros que cumplían con la anterior condición de filtrado.
- Y generar un fichero de salida con una línea de texto en la que se informa del resultado del recuento de registros.

En un JCL normal tendríamos que haber empleado tres pasos para ir realizando cada una de las acciones anteriores. Por tanto, incluso en un job tan sencillo, ya hemos conseguido algo de ahorro. En realidad, cuanto más compleja sea la funcionalidad a desarrollar en el JCL, mayor será el número de acciones que podremos incluir en un único paso ICETOOL y, por consiguiente, mayor será la optimización alcanzada.



Mi recomendación es que, si disponéis de ella en vuestra instalación, aprendáis a utilizar esta herramienta. En cuanto alcancéis un poco de agilidad con su manejo, agradeceréis la simplificación de pasos que se producirá en vuestros JCL. Si, a pesar de todo lo indicado, os sigue pareciendo más clara la forma clásica de implementar los pasos, obviamente podréis seguir codificando tal y como lo hacíais hasta ahora. Llegados a ese punto, se tratará de una decisión personal de cada programador.

Pues nada, espero que con todo lo comentado os haya quedado bastante claro cómo es el funcionamiento global de la herramienta ICETOOL y cuáles son las funciones que se pueden ejecutar con ella. Como ya sabéis, todas vuestras dudas serán bienvenidas en el apartado de comentarios de este post…

Saludos.