Desarrollando en Cobol y Natural sobre Plataforma Mainframe

viernes, 29 de mayo de 2015

Nueva Versión de una Aplicación


jueves, 28 de mayo de 2015

Utilidad JCL ICEMAN para realizar SORT (y 2)

Hace algunas semanas comenzamos a ver la funcionalidad de la utilidad JCL ICEMAN, herramienta empleada para la realización de SORT (ordenación) de registros de ficheros. Recordemos que, tal y como dijimos, se trata de la versión moderna de la utilidad clásica DFSORT.

En la primera parte del post estuvimos viendo algunas de las cláusulas que lleva asociadas la utilidad ICEMAN (ver post Utilidad JCL ICEMAN para realizar SORT - 1). Hoy completaremos la revisión de todas las tarjetas que deben acompañar a esta herramienta para que pueda ejecutar una correcta ordenación mediante el comando SORT. Son la siguientes:

4º) Card SYSIN: Aquí se incluirán las sentencias de control que la utilidad ICEMAN recibirá como entrada. Bajo esta tarjeta se tendrá que especificar la función que debe ser ejecutada por el programa: SORT (ordenar), COPY (copiar) o MERGE (unir).

//SYSIN    DD  *

5º) Comando SORT: A continuación, incluimos el comando SORT bajo la tarjeta SYSIN para indicarle a la utilidad ICEMAN que debe realizar la ordenación de los registros del fichero de entrada y dejar el resultado ordenado en el fichero de salida especificado.

  SORT FIELDS=(1,6,CH,A,8,25,CH,A),DYNALLOC=3390


Como vemos, la cláusula FIELDS del comando SORT viene acompañada de ocho parámetros entre paréntesis. En realidad, en este caso se trata de la información asociada a dos campos de los registros del fichero: (1,6,CH,A) y (8,25,CH,A). Cada uno de los campos que especifiquemos en un SORT tendrá que tener provisionados los siguientes cuatro parámetros.

- Parámetro 1 – Inicio del campo: La ordenación se realizará en función del campo clave que comienza en la posición del registro indicada en este parámetro.

- Parámetro 2 – Longitud del campo: Aquí indicamos la longitud del campo clave que se empleará para realizar la ordenación. Recordemos que dicho campo comenzaba en la posición del registro indicada en el parámetro 1.

- Parámetro 3 – Tipo de Dato: Especifica el tipo de dato (formato) del campo clave seleccionado. Podrá ser CH (Alfanumérico o Numérico no empaquetado), BI (Hexadecimal empaquetado COMP) o PD (Empaquetado COMP-3).

- Parámetro 4 – Tipo de Ordenación: Indica si la ordenación debe ser ascendente (A) o descendente (D).



Se puede realizar la ordenación por tantos campos como se desee, sin más que añadir los datos de un campo a continuación del anterior. Sin ir más lejos, en el ejemplo anterior estamos ordenando por el campo que comienza en 1 (de longitud 6 posiciones) y por el campo que empieza en 8 (de longitud 25 posiciones).

6º) Comando SUM: Finalmente, se incluye el comando SUM para indicarle a la utilidad ICEMAN que, en el fichero de salida, no deben aparecer registros duplicados. En realidad, lo que hace SUM es eliminar aquellos registros que tengan valores idénticos en los campos especificados en el SORT.


A continuación del SUM, en su cláusula FIELDS indicaremos el campo que deseamos que se vaya sumando para todos aquellos registros que estén repetidos. Si se indica NONE, entonces es que no se desea que se sume ningún campo del fichero.

SUM  FIELDS=NONE

Por tanto, en nuestro ejemplo le estamos solicitando a la utilidad ICEMAN que haga una ordenación (SORT) ascendente (A) en función del campo de longitud 6 que comienza en la posición 1 (1,6) y del campo de longitud 25 que comienza en la posición 8 (8,25), ambos con formato Numérico/Alfanumérico No Empaquetado (CH).

Ejecución del comando SORT de la utilidad ICEMAN


Una vez tengamos definidos los parámetros de nuestro SORT en el ICEMAN de nuestro JCL, se podrá proceder a su lanzamiento. Si hemos definido los tarjetas tal y como hemos comentado anteriormente, la ejecución del job no debería darnos ningún error.



En particular, he procedido a lanzar el JCL que estábamos utilizando de ejemplo y el proceso se ha completado correctamente. El retorno RC devuelto ha sido un CONDITION CODE 0000. A continuación, he comprobado que se ha generado el fichero de salida con denominación ATLASPR.UNLOAD.X0005X.POBL.SORT y con todos los registros ordenados. Su contenido es el siguiente.

***************************** Top of Data *****
000002-ALMERIA                  00001300     
000004-SANTANDER                00001500     
000005-TARRAGONA                00001600     
000006-BADAJOZ                  00001700     
000007-SALAMANCA                00001800     
000008-BURGOS                   00001900     
000010-SEGOVIA                  00001100     
000011-TOLEDO                   00001000     
000012-GRANADA                  00000900     
000014-CASTELLON                00000700     
000015-ZARAGOZA                 00000600     
000017-VALENCIA                 00000400     
000018-BARCELONA                00000300     
000019-CIUDAD REAL              00000200     
000020-MADRID                   00000100     
**************************** Bottom of Data ***


Como vemos, los registros ya no están desordenados como en el dataset origen y en este fichero de salida las ciudades aparecen ordenadas en función de su código asociado. Realmente, en este ejemplo nos hubiese bastado con ordenar por el campo 1 del SORT, ya que no hay códigos de población repetidos.


En líneas generales, esta sería la forma de trabajar con la utilidad ICEMAN. De todos modos, aunque sea algo más antigua, en la mayoría de los casos podremos seguir operando con total normalidad mediante la utilidad DFSORT, ya que los comandos básicos son los mismos. Eso sí, lo ideal sería que nuestra instalación dispusiera de ambas alternativas.

Y eso es todo. Esperamos que lo comentado en el texto os sirva para haceros una idea de cómo se puede operar con la utilidad ICEMAN para JCL. Como ya sabéis, todas vuestras dudas serán bienvenidas…

Saludos.

jueves, 21 de mayo de 2015

Utilidad JCL ICEMAN para realizar SORT (1)

La utilidad ICEMAN de IBM para JCL es, básicamente, la versión moderna de la clásica utilidad DFSORT de Mainframe y, como tal, mantiene su misma funcionalidad. Por tanto, cada vez que tengamos la necesidad de ordenar los datos de un fichero para un programa Cobol, podremos recurrir indistintamente tanto a una como a otra.

Utilidad ICEMAN para ordenación de registros


La utilidad ICEMAN se usa para realizar la ordenación de los registros del fichero secuencial indicado y almacenar el resultado ordenado en un nuevo fichero. Aparte de esto, también puede ser empleada en una aplicación Cobol para realizar simples copias de ficheros o para unir el contenido de varios ficheros secuenciales.



Vamos a ver cómo funcionaría esta herramienta Mainframe con un ejemplo. Imaginemos que estamos trabajando con un fichero de poblaciones (denominado SISTEMA.UNLOAD.X0005X.POBL) en el que aparecen únicamente dos campos: el nombre de la ciudad y su código interno asociado. El contenido de dicho fichero es el siguiente.

***************************** Top of Data *****
000020-MADRID                   00000100     
000019-CIUDAD REAL              00000200     
000018-BARCELONA                00000300     
000017-VALENCIA                 00000400     
000015-ZARAGOZA                 00000600     
000014-CASTELLON                00000700     
000012-GRANADA                  00000900     
000011-TOLEDO                   00001000     
000010-SEGOVIA                  00001100     
000002-ALMERIA                  00001300     
000004-SANTANDER                00001500     
000005-TARRAGONA                00001600     
000006-BADAJOZ                  00001700     
000007-SALAMANCA                00001800     
000008-BURGOS                   00001900     
**************************** Bottom of Data ***


Como vemos, los registros mostrados no siguen ningún tipo de ordenación, ni por código ni por nombre. A continuación, en nuestro proyecto nos piden que generemos otro fichero secuencial en el que se muestren todas las ciudades ordenadas por su código interno. Para realizar esta tarea podemos (y vamos a) recurrir a la utilidad ICEMAN.

Recordemos, antes de continuar, que ICEMAN tiene que estar acompañada de un comando que le indique cuál es la acción que queremos ejecutar con la herramienta. Al igual que en el caso del DFSORT, los comandos disponibles son los siguientes.

- SORT: para ordenar los registros de un dataset.
- COPY: para realizar la copia de un fichero completo.
- MERGE: para unir dos ficheros en uno.


Ordenación de registros mediante SORT de ICEMAN


En nuestro caso, como nos han pedido ordenar un fichero secuencial, tendremos que recurrir al comando SORT de ICEMAN. A continuación, mostramos un ejemplo (no es la única solución posible) de cómo se podría implementar el JCL que resolviese el problema propuesto.

//PASO1   EXEC PGM=ICEMAN                             
//*           ****************************************
//*           * FICHERO DE ENTRADA SIN ORDENAR      
//*           ****************************************
//SYSOUT   DD  SYSOUT=*                             
//SORTIN   DD  DSN=SISTEMA.UNLOAD.X0005X.POBL,DISP=SHR
//*           ****************************************
//*           * FICHERO DE SALIDA ORDENADO          
//*           ****************************************
//SORTOUT  DD  DSN=SISTEMA.UNLOAD.X0005X.POBL.SORT, 
//             DISP=(,CATLG,DELETE),UNIT=DISCO,     
//             SPACE=(CYL,(00010,00010),RLSE)       
//SYSIN    DD  *                                    
  SORT FIELDS=(1,6,CH,A,8,25,CH,A),DYNALLOC=3390    
  SUM  FIELDS=NONE                                  
/*                                                  
//*
                                            

A continuación, pasamos a detallar en qué consiste cada una de las tarjetas codificadas en el párrafo anterior.

1º) Card SYSOUT: Aquí tenemos que especificar la ubicación en la que deseamos que se almacenen los mensajes generados durante la ejecución del proceso. La sentencia SYSOUT=* indica que estos mensajes deben enviarse al SPOOL (a la MSGCLASS provisionada en el JCL).

//SYSOUT   DD  SYSOUT=*

2º) Card SORTIN: Aquí se debe especificar el nombre del fichero secuencial origen sobre el que se debe realizar la ordenación de los registros. En el caso del ejemplo, se está indicando el fichero SISTEMA.UNLOAD.X0005X.POBL.

//SORTIN   DD  DSN=SISTEMA.UNLOAD.X0005X.POBL,DISP=SHR


3º) Card SORTOUT: Aquí tendremos que indicar el nombre que deberá tener el fichero de salida generado mediante el comando SORT. Junto al nombre, habrá que especificar las características con las que debe crearse el dataset.

//SORTOUT  DD  DSN=SISTEMA.UNLOAD.X0005X.POBL.SORT, 
//             DISP=(,CATLG,DELETE),UNIT=DISCO,     
//             SPACE=(CYL,(00010,00010),RLSE)
        


El próximo día, en un post adicional, continuaremos viendo la descripción de las tarjetas que deben acompañar a la utilidad si deseamos que ICEMAN proceda a ejecutar el comando SORT. Recordemos que, aparte de la ordenación SORT, esta herramienta también puede realizar las funciones de copiado y de unión.

Y nada más. Os emplazo a la segunda parte del artículo, donde completaremos la revisión de la estructura que debe implementar un comando SORT mediante ICEMAN.

Saludos.

jueves, 14 de mayo de 2015

Error JCL ABEND S837 al ejecutar un Job

El error JCL ABEND S837 es un retorno con el que nos vamos a encontrar de manera frecuente si trabajamos habitualmente con JCL Cobol. Si miramos la salida de uno de estos jobs fallidos, veremos que el detalle del problema es SYSTEM COMPLETION CODE=837  REASON CODE=00000008. Por tanto, la pregunta sería: ¿Cómo podemos solucionar este tipo de error?

Error ABEND S837 en ejecución de JCL Cobol

Obviamente, cuanto mayor experiencia vayamos teniendo con el lenguaje JCL, menos posibilidades hay de que veamos un S837. Pero, de todas formas, nada nos va a librar de cruzarnos con él de vez en cuando.



De hecho, hace algunas semanas, al lanzar un job (denominado JJUNLDIA) en uno de nuestros proyectos, obtuvimos precisamente un ABEND S837. Al revisar el contenido de la salida, pudimos ver que la descripción del error era la siguiente. 

10.43.35 JOB07414  -STEPNAME PROCSTEP    RC   EXCP   CONN       TCB
10.43.35 JOB07414  -PASO1    STEP010     00     81     55       .00
10.47.24 JOB07414  IEC028I 837-08,IFG0554A,JJUNLDIA,STEP030,SYSREC01
   206             JJPR.UNLOAD.X0005X.DIARIO.JJADOR 
10.47.28 JOB07414  $HASP375 JJUNLDIA ESTIMATED  LINES EXCEEDED
10.47.33 JOB07414  $HASP375 JJUNLDIA ESTIMATE EXCEEDED BY
10.47.37 JOB07414  IEA995I SYMPTOM DUMP OUTPUT  252                 
   252             SYSTEM COMPLETION CODE=837  REASON CODE=00000008 
   252              TIME=10.47.24  SEQ=19523  CPU=0000  ASID=012E  
   252              PSW AT TIME OF ERROR  075C1000   80DB8916  ILC 2
   252                NO ACTIVE MODULE FOUND                       
   252                NAME=UNKNOWN                                 
   252                DATA AT PSW  00DB8910 - 41003038  0A0DB20A  00
   252                AR/GR 0: 008D03E8/00DB8B24   1: 00000000/A4837
   252                      2: 00000000/000F4660   3: 00000000/00DB8
   252                      4: 00000000/008A64A8   5: 00000000/00DCF
   252                      6: 00000000/008A674C   7: 00000000/008A6
   252                      8: 00000000/008A676C   9: 00000000/008A7
   252                      A: 00000000/008BC8F8   B: 00000000/00DB8
   252                      C: 00000000/008A7680   D: 00000000/7FFB7
   252                      E: 00000000/00DB85A2   F: 00000000/00000
   252              END OF SYMPTOM DUMP
 10.47.39 JOB07414  -PASO1    STEP030     16  16137   6758       .02

En rojo hemos marcado la parte conflictiva de la ejecución, donde se especifica el error SYSTEM COMPLETION CODE=837  REASON CODE=00000008, y donde se indica cuál es el objeto causante del problema: en este caso, el fichero secuencial JJPR.UNLOAD.X0005X.DIARIO.JJADOR.

IEC028I 837-08,IFG0554A,JJUNLDIA,STEP030,SYSREC01,7820,$GB030
   206             JJPR.UNLOAD.X0005X.DIARIO.JJADOR
SYSTEM COMPLETION CODE=837  REASON CODE=00000008
NO ACTIVE MODULE FOUND

Causa del error ABEND S837

Hay que puntualizar que este JCL se encarga de crear el fichero secuencial mencionado. Por tanto, el problema no tiene nada que ver con que el proceso se haya encontrado con un dataset duplicado ni nada por el estilo.

Este job vuelca los datos de una tabla DB2 en un fichero secuencial y, en realidad, el error se produce por un problema de dimensionamiento del tamaño del fichero de salida. En este caso, estamos hablando de un DB2 con varios cientos de miles de registros y, por tanto, tenemos que ser cuidadosos a la hora de definir las características del dataset en nuestro JCL (aquí podemos ver un ejemplo de cómo se debe crear un fichero secuencial mediante la utilidad IEFBR14).



Echando un vistazo al código, vemos que el fichero de salida estaba definido del siguiente modo en el JCL.

//SYSREC01 DD DSN= JJPR.UNLOAD.X0005X.DIARIO.JJADOR,
//            DISP=(NEW,CATLG,DELETE),UNIT=(DISCO),    
//            SPACE=(TRK,(15,15),RLSE)            

Como se puede apreciar, para su alta se ha establecido en la cláusula SPACE que el fichero se cree usando 15 tracks como espacio primario y 15 tracks como espacio secundario. Esto es, a todas luces, insuficiente para trabajar con una tabla DB2 de varios cientos de miles de registros.

Cómo solucionar un ABEND S837

Por tanto, para solucionar el problema tendríamos que proceder a ampliar tanto el espacio primario como el secundario asignado al fichero de nueva creación. Haciendo esto, el dataset no tendrá problemas para absorber los 600.000 registros al ejecutarse el job.



En nuestro caso, para corregir el error procedimos a definir una nueva cláusula SPACE con dos cilindros como espacio primario y otros dos cilindros como espacio secundario. Recordemos que un cilindro equivale a 15 tracks y, por tanto, dos cilindros serían 30 tracks.

//SYSREC01 DD DSN= JJPR.UNLOAD.X0005X.DIARIO.JJADOR,
//            DISP=(NEW,CATLG,DELETE),UNIT=(DISCO),    
//            SPACE=(CYL,(2,2),RLSE)

Una vez realizado el cambio mencionado, procedimos a relanzar el JCL y, en esta ocasión, el job finalizó sin generar ningún error ni ningún ABEND, mostrando un CONDITION CODE = 0000. De hecho, al chequear el fichero de salida comprobamos que se habían cargado correctamente los 600.000 registros.



Por tanto, si alguna vez obtenéis un error del tipo ABEND S837, aseguraos de que estáis definiendo los ficheros de salida con el suficiente espacio, tanto primario como secundario. Esto os puede ahorrar bastante tiempo a la hora de detectar la causa del problema.

Y eso es todo. Esperamos que lo comentado os sirva para sacaros de un apuro si vuestro job se encuentra en una situación similar. Por supuesto, podéis hacernos cualquier pregunta que consideréis oportuna.

Saludos.

jueves, 7 de mayo de 2015

CA Database Management Solutions for DB2 for ZOS (y 2)

Hace algunas semanas comenzamos a ver qué era y para qué podíamos emplear la herramienta CA Database Management Solutions for DB2 for ZOS. Hoy trataremos de completar la visión global de esta aplicación, de manera que tengamos unas nociones básicas que nos permitan decidir si nos conviene comenzar a utilizarla o no.

En el anterior post estuvimos viendo cuál era el aspecto que tenían los menús de este Gestor de Base de Datos (ver post CA Database Management Solutions for DB2 for ZOS – 1) . Y, a continuación, estuvimos explicando cómo se podía navegar hasta la opción que nos permitía determinar la composición de cada uno de los índices de un fichero DB2.

Se trata de una forma sencilla de identificar cuál es la estructura que tiene una tabla con la que vamos a comenzar a trabajar. La herramienta nos informa de cuántos índices hay asociados al DB2 y cuáles son los campos de los que está compuesto cada uno de ellos. Para nuestros programas Cobol, esto nos será muy útil a la hora de implementar queries SQL con el acceso a DB2 optimizado.



Consulta de Quey generadora de un Indice

Si, por lo que fuese, aparte de tener acceso al contenido de un fichero DB2, quisiésemos conocer la query que se empleó para crear un determinado índice en la tabla, también podremos hacerlo. Para ello, bastará con introducir el comando ‘DDL’ en la columna CMD que había junto a los índices de la tabla.

CMD      TABLE NAME          CREATOR   INDEX NAME  
________ JJPEDITD            JJDB22                
DDL_____                               JJPEDII0    
________                               JJPEDII1    
________                               JJPEDII2    

Al pulsar INTRO se mostrará el detalle con la codificación completa de la query que se utilizó para realizar la generación del índice.

********************************* TOP OF DATA ***
                                                                                                 
SET CURRENT  SQLID ='JJ00917';                  
                                                
 CREATE UNIQUE INDEX JJDB22.JJPEDII0            
       ON JJDB22.JJPEDITD                       
                                                
       (JJPE_ORIGEN                 ASC      
       ,JJPE_ORI                    ASC      
       ,JJPE_ALTA                   ASC      
       ,JJPE_INTERN                 ASC      
       ,JJPE_INTE                   ASC  
       ,JJPE_IN                     ASC  
       ,JJPE_TIEL                   ASC  
       ,JJPE_TIPFAC                 ASC  
       ,JJPE_ARQTEC                 ASC) 
       CLUSTER                              
       USING STOGROUP JJSTGRJ2              
             PRIQTY 816                     
             SECQTY 48                      
             ERASE NO                       
       FREEPAGE 0                           
       PCTFREE 5                            
       BUFFERPOOL BP0                       
       CLOSE NO           
       PIECESIZE 2097152K;

******************************** BOTTOM OF DATA ***

Tal y como se aprecia, en la query se hace referencia a los mismos campos que previamente habíamos visto en la consulta con la opción ‘C’ (Columns). Por tanto, la información mostrada en ambos casos es la misma. Visualizarla de una forma o de otra, con ‘C’ o con ‘DDL’, en realidad sólo va a depender de cuales sean nuestras preferencias. Esta muestra sirve para hacernos una idea de la flexibilidad de la aplicación.

Conclusiones del uso de CA DMS

Como se puede observar, la herramienta “CA Database Management Solutions for DB2 for ZOS” (CA DMS) nos facilita enormemente cualquier tipo de consulta que queramos realizar sobre la estructura de una tabla DB2. Si tenéis la fortuna de disponer de ella en la instalación de vuestro cliente, no dudéis en aprender a utilizarla, os ahorrará mucho trabajo a largo plazo.



Obviamente, la herramienta tiene muchas más opciones disponibles, pero lo comentado es más que suficiente para que os hagáis una idea de cómo sería su empleo. Una vez dominado el acceso básico a CA DMS, no os resultará demasiado difícil ir descubriendo el resto de facilidades por vosotros mismos.

Eso es todo. Esperamos que, si finalmente os decidís a utilizarla, os sirva para ahorrar tiempo en vuestro día a día. De todas formas, no dudéis en comentarnos cualquier cuestión que os surja al respecto.

Saludos.

Related Posts Plugin for WordPress, Blogger...