martedì 9 ottobre 2018

FUSIONE - Un semplice programma COBOL

L'algoritmo di fusione visto prima si può tradurre in un semplice programma in linguaggio COBOL.
Come già detto le strutture S1 e S2 e OUT in questo caso assumono la forma di tre file.

Il listato COBOL, ridotto ai minimi termini per semplicità ma comunque funzionante, è il seguente:

 IDENTIFICATION DIVISION.                           
*--------------------------------------------------*
 PROGRAM-ID. FUSIONE.                               
*--------------------------------------------------*
 ENVIRONMENT DIVISION.                              
 INPUT-OUTPUT SECTION.                              
 FILE-CONTROL.                                      
* FILE DI INPUT CONTENENTE LA STRUTTURA S1          
     SELECT S1          ASSIGN S1.                  
* FILE DI INPUT CONTENENTE LA STRUTTURA S2          
     SELECT S2          ASSIGN S2.                  
* FILE DI OUTPUT CONTENENTE LA FUSIONE S1+S2        
     SELECT OUT         ASSIGN OUT.                 
*--------------------------------------------------*
 DATA DIVISION.                                     
 FILE SECTION.                                      
 FD S1                                      
     LABEL RECORD IS STANDARD               
     RECORDING MODE IS F                    
     BLOCK 0 RECORDS.                       
 01 S1-REC.                                 
    05 S1-STRING                   PIC X.   
 FD S2                                      
     LABEL RECORD IS STANDARD               
     RECORDING MODE IS F                    
     BLOCK 0 RECORDS.                       
 01 S2-REC.                                 
    05 S2-STRING                   PIC X.   
  FD OUT                                    
      LABEL RECORD IS STANDARD              
      RECORDING MODE IS F                   
      BLOCK 0 RECORDS.                      
  01  OUT-REC                      PIC X.   
*--------------------------------------------------*   
 WORKING-STORAGE SECTION.                              
*--------------------------------------------------*   
*                                                      
 01  KEY1                         PIC X VALUE SPACES.  
 01  KEY2                         PIC X VALUE SPACES.  
*                                                      
*--------------------------------------------------*   
 PROCEDURE DIVISION.                                   
*--------------------------------------------------*   
 P000-MAIN-LINE.                                       
*                                                      
     OPEN INPUT S1.                                    
     OPEN INPUT S2.                                    
     OPEN OUTPUT OUT.                                  
     READ S1 INTO KEY1 AT END MOVE HIGH-VALUE  TO KEY1.
     READ S2 INTO KEY2 AT END MOVE HIGH-VALUE  TO KEY2.
     DISPLAY 'INIZIO PROGRAMMA DI FUSIONE'                     
     PERFORM UNTIL KEY1 = HIGH-VALUE AND KEY2 = HIGH-VALUE     
         IF KEY1 < KEY2                                        
            DISPLAY KEY1 ' < ' KEY2 ' - SCRIVO : ' KEY1        
            WRITE OUT-REC FROM KEY1                            
            READ S1 INTO KEY1 AT END MOVE HIGH-VALUE TO KEY1   
         ELSE                                                  
            IF KEY1 > KEY2                                     
               DISPLAY KEY1 ' > ' KEY2 ' - SCRIVO : ' KEY2     
               WRITE OUT-REC FROM KEY2                         
               READ S2 INTO KEY2 AT END MOVE HIGH-VALUE TO KEY2
            ELSE                                               
               WRITE OUT-REC FROM KEY1                         
               DISPLAY KEY1 ' = ' KEY2 ' - SCRIVO : ' KEY1     
               READ S1 INTO KEY1 AT END MOVE HIGH-VALUE TO KEY1
               READ S2 INTO KEY2 AT END MOVE HIGH-VALUE TO KEY2
            END-IF                                             
         END-IF                                   
     END-PERFORM.                                 
     DISPLAY 'TERMINE PROGRAMMA DI FUSIONE'.      
     CLOSE S1.                                    
     CLOSE S2.                                    
     CLOSE OUT.                                   
     GOBACK.                                      
*                                                 
 P000-EXIT.                                       
     EXIT.                                        
Nella PROCEDURE DIVISION è riportato l'algoritmo visto prima corredato di alcune DISPLAY per esporne in SYSOUT l'operato.

Un Job JCL di lancio può essere il seguente:

//SYSADMX JOB (12345678),SYSADM,MSGCLASS=H,               
//        MSGLEVEL=(1,1),CLASS=A,NOTIFY=&SYSUID           
//STEP1 EXEC PGM=FUSIONE                                  
//STEPLIB DD DSN=SYSADM.LIB.LOAD,DISP=SHR                 
//S1      DD DSN=SYSADM.PE000.S1,DISP=SHR                 
//S2      DD DSN=SYSADM.PE000.S2,DISP=SHR                 
//OUT     DD DSN=SYSADM.PE000.OUT,                        
//           DISP=(,CATLG,DELETE),SPACE=(CYL,(8,8),RLSE), 
//           DCB=(LRECL=1,RECFM=FB)                       

//SYSOUT DD SYSOUT=* 

Come si vede in esso semplicemente dichiariamo i file elaborati dal programma e allochiamo il file prodotto in output.

Popoliamo i due files in input come segue:

S1 = 1,3,5,7,9
S2 = 2,4,6,7

E lanciamo il JCL.
Al termine dell'esecuzione il file OUT conterrà i valori:

OUT = 1,2,3,4,5,6,7,7,9

mentre in SYSOUT potremo vedere le DISPLAY poste nel programma:

********************************
INIZIO PROGRAMMA DI FUSIONE     
1 < 2 - SCRIVO : 1              
3 > 2 - SCRIVO : 2              
3 < 4 - SCRIVO : 3              
5 > 4 - SCRIVO : 4              
5 < 6 - SCRIVO : 5              
7 > 6 - SCRIVO : 6              
7 = 7 - SCRIVO : 7              
9 > 7 - SCRIVO : 7              
9 <   - SCRIVO : 9              
TERMINE PROGRAMMA DI FUSIONE    

********************************

Come già detto, questo è un programma minimale. Manca ad esempio la gestione degli errori in fase di I/O, tipicamente tramite FILE-STATUS ma rende bene l'idea dell'operato dell'algoritmo.






















venerdì 5 ottobre 2018

Fusione, un algoritmo.

Con riferimento al post precedente, un algoritmo che realizzi la fusione fra due strutture dati potrebbe essere il seguente:

Supponiamo che le strutture S1 e S2 siano due file e che si voglia scrivere in output un nuovo file contenente l'unione dei due input.

L'idea di base è di memorizzare la chiave di fusione in una variabile "key1" per S1 e "key2" per S2 e lavorare sulle relazioni logiche che possono crearsi fra queste due variabili.

  1. Se key1 è minore di key2, S1 andrà in output e un nuovo valore di S1 sarà letto;
  2. Se key1 è maggiore di key2, S2 andrà in output e un nuovo valore di S2 sarà letto;
  3. Se key1 è uguale a key2, uno fra S1 e S2 andrà in output e un nuovo valore sia di S1 che di S2 sarà letto;
Questa serie di confronti andrà avanti fino a quando tutte le letture saranno completate.
Per gestire il caso, frequente, di file di grandezza diversa si avrà cura, nel caso uno dei due file termini prima dell'altro, di porre la chiave corrispondente ad un valore "tappo" (Tipicamente in COBOL si usa HIGH-VALUE).
In questo modo una delle due condizioni 1 e 2 sarà sempre verificata provocando lo scarico dell'altro file in output.

L'algoritmo precedente può essere espresso in pseudo-codifica nel modo seguente:

START
    OPEN S1, S2,OUT;
    READ S1 IN KEY1 AT END KEY1=HV;
    READ S2 IN KEY2 AT END KEY2=HV;
    PERFORM UNTIL KEY1=HV AND KEY2=HV
        IF KEY1 < KEY2 THEN
             WRITE OUT FROM S1;
             READ S1 IN KEY1 AT END KEY1=HV;
        ELSE
             IF KEY1 > KEY2 THEN
                 WRITE OUT FROM S2;
                 READ S2 IN KEY2 AT END KEY2=HV;         
             ELSE
                  WRITE OUT FROM S1;
                  READ S1 IN KEY1 AT END KEY1=HV;
                  READ S2 IN KEY2 AT END KEY2=HV;
             END-IF;
       END-IF;
    END-PERFORM;
    CLOSE S1,S2,OUT
END




venerdì 7 novembre 2014

Fusione e Bilanciamento

Siano date due strutture dati, S1 e S2, ordinate entrambe secondo la stessa chiave e nello stesso senso. Un algoritmo che date in input S1 e S2, produce in output una terza struttura S3 derivante dalla unione delle due in input è detto di Fusione.
Facendo una analogia con la teoria degli insiemi, S3 può essere visto come l'insieme Unione di S1 e S2.

Ad esempio, siano:

  • S1 = {1,3,4,5,7,9}
  • S2 = {2,4,6,7,8,10}

Tramite un algoritmo di fusione possiamo ottenere:

  • S3 = {1,2,3,4,4,5,6,7,7,8,9,10}


A differenza della Fusione, il Bilanciamento, pur essendo del tutto simile, produce in genere una struttura identica ad una delle strutture in input, detta Guida, ma arricchita delle informazioni dell'altra struttura sugli elementi che si "bilanciano". 
Siano ad esempio, S1 una struttura contenente una lista ordinata di Userid e S2 una struttura contenente una anagrafica completa per Userid. Si supponga di voler associare agli elementi della lista S1 alcune informazioni prelevate da S2, ad esempio il nome e cognome.

Quindi avremo, ad esempio :
  • S1 = {U4,U5,U8,U10,U25}
  • S2 = {(U1,n1,c1),(U2,n2,c2),(U3,n3,c3),(U4,n4,c4),(U5,n5,u5),...,(U8,n8,c8),...,(U10,n10,c10),...,(U25,n25,c25),...,(U100,n100,u100)}

Dove :

  •  "Un" (n=1..100) sono le Userid;
  •  "nn" e "cn" (n=1..100) sono i nomi e cognomi associati alle userid
Il programma di bilanciamento "guidato" da S1, cercherà in S2 le informazioni mancanti per comporre in out una struttura S3 del tipo:
  • S3 = {(U4,n4,c4),(U5,n5,u5),(U8,n8,c8),(U10,n10,c10),(U25,n25,c25)}



martedì 4 novembre 2014

Algoritmi di Base su Mainframe

Esistono alcuni algoritmi che chiunque programmi in ambito Mainframe dovrebbe conoscere e sapere implementare.
Fondamentalmente essi si possono raggruppare in tre categorie:
1) Bilanciamento (Merge);
     E' utilizzato quando, date due strutture dati ordinate secondo una certa chiave (La stessa per entrambe) si vuole creare una terza struttura risultante dalla fusione delle due ed ordinata secondo la stessa chiave.
2) Rottura di chiave;
    Una rottura di chiave si applica quando, data una struttura dati ordinata secondo una certa chiave, si vogliono eseguire elaborazioni su tutti i dati afferenti uno stesso valore della chiave (Totalizzazioni, conteggi). Era molto utilizzato per la produzione di report stampabili.
3) Ordinamento (Sort);
    Si applica quando è necessario ordinare una struttura dati secondo una chiave in senso ascendente o discendente. Normalmente quando la struttura è un sequenziale, l'operazione viene eseguita da JCL. Un sort a programma si può applicare a liste di dati da visualizzare e contenuti un tabelle di memoria.




giovedì 9 maggio 2013

Mixed Case in ambiente CICS

Per Default , CICS converte tutti i caratteri inseriti in maiuscolo. Si possono quindi inserire stringhe in maiuscolo e minuscolo ma, alla pressione di ENTER o di un un tasto funzione, i caratteri vengono convertiti in maiuscolo e così passati alla transazione in esecuzione. Normalmente si lascia questo comportamento predefinito in atto.
Tuttavia  vi sono casi in cui è comodo se non necessario avere la possibilità di inserire valori sia maiuscoli che minuscoli. Se i è permesso l'accesso ai comandi CICS appropriati, è possibile disattivare la funzione maiuscole CICS e impostare il terminale CICS per consentire l'input misto.


In primo luogo, è necessario determinare l'ID terminale. Un modo per farlo è con il comando CEMT:


 CEMT I TASK                                                                   

  STATUS:  RESULTS - OVERTYPE TO MODIFY                                         
+ Tas(0000137) Tra(Y1V3)           Sus Tas Pri( 240 )                          
     Sta(U ) Use(USER02  ) Uow(CB551DE4EF184551)                               
  Tas(0000537) Tra(YD@K)           Sus Tas Pri( 001 )                          
     Sta(S ) Use(USER02  ) Uow(CB551DEA9C3AF051) Hty(EKCWAIT )                 
  Tas(0011591) Tra(CEMT) Fac(L$YV) Sus Ter Pri( 255 )                          
     Sta(TO) Use(U0G3685 ) Uow(CB554B0AA361CE4D) Hty(ZCIOWAIT)                 
  Tas(0011715) Tra(CEMT) Fac(L1NC) Run Ter Pri( 255 )                          
     Sta(TO) Use(U0G9621 ) Uow(CB554BD2F3CEB04A)                               
                                                                               
                                                                               
L' ID terminale verrà segnalato all'interno del blocco 'Fac (....)'.
In molti sistemi, il vostro ID terminale sarà diverso ogni volta che si accede al CICS.

Quindi, immettere il comando per disattivare maiuscolo:


 CECI SET TERM (L1NC) NOUCTRAN                                     

 STATUS:  COMMAND EXECUTION COMPLETE                         NAME= 
  EXEC CICS  SET TERminal( 'L1NC' )                                

La corretta esecuzione del comando si può verificare inserendo il nome di una transazione nota ma in caratteri minuscoli. Il CICS non riconoscerà la transazione.                                                                               

Per tornare alla situazione di default basterà immettere il comando

CECI SET TERM (L1NC) UCTRAN                                                                               
                                         

(Liberamente tradotto e proficuamente utilizzato da http://softwaremiracles.com)