viernes, 28 de noviembre de 2008

Obtener listas objetos en IFS

Como obtener listas de objetos en el Integrated File System del AS400.

Habitualmente sabemos navegar desde la pantalla verde con el mandato
WRKLNK OBJ('/') DETAIL(*EXTENDED) DSPOPT(*ALL) pero si desde un programa queremos obtener una lista de archivos del directorio '/home/temp' (por ejemplo) no tenemos un mandato para hacerlo directamente y hemos de volcarlo a spool y leer ese spool o utilizar una API del sistema.

Una solución sencilla, si esta instalado el entorno QSHELL (opción 30 del 5722SS1) , es ejecutar mandatos tipo UNIX, pongo algunos ejemplos de los que se puede conseguir:

Obtener contenido del directorio /home/temp (en el archivo MYLIB/LISTDIR):
  • QSH CMD('ls /home/temp/* >/qsys.lib/mylib.lib/listdir.file/listdir.mbr')
Obtener lista de directorios del sistema (atención puede tardar horas):
  • QSH CMD('find / -type d |grep -v "QSYS.LIB" |grep -v "QNTC">/qsys.lib/mylib.lib/listdir.file/listdir.mbr')
o también:
  • QSH CMD('ls -alR / |grep "/" |grep -v "l" |grep -v "QSYS.LIB">/qsys.lib/mylib.lib/listdir.file/listdir.mbr')

martes, 18 de noviembre de 2008

Prompt selectivo de mandato

La función del prompt selectivo en los mandatos es útil en un programa CL interactivo. Con esta función podemos ahorrarnos algún paso de parámetro en el programa.

El prompt selectivo se utiliza insertando caracteres especiales delante de los parámetros de los mandatos, los valores permitidos son:
  • ?? Muestra el prompt del parámetro y permite cambiarlo.
  • ?* Muestra el prompt del parámetro pero no permite cambiarlo
  • ?- Oculta el parámetro.
  • ?< Muestra el prompt del parámetro y permite cambiarlo, pero el valor por omisión es el que le enviamos desde el programa.
  • ?& Solo se muestra el prompt del parámetro si se pulsa F10 y permite cambiarlo.
  • ?% Solo se muestra el prompt del parámetro si se pulsa F10, pero no permite cambiarlo.
Ademas si colocamos un ? delante del mandato nos modifica el comportamiento de los prompt selectivos:
  • blanco Muestra solo los parámetros con prompt selectivo, no permite F9.
  • ? Muestra prompt del mandato y permite cambiar parámetros y pulsar F9.
Un ejemplo para ilustrar esta función, queremos crear un programa que restaure objetos desde un *SAVF, pero queremos dejar al usuario la elección de ciertos parámetros, de otros informarle de su valor y ocultar el resto aunque estén definidos, para ello usaremos el código siguiente:

RSTOBJ ??OBJ(*ALL) SAVLIB(LIBSAV) ?-DEV(*SAVF) OBJTYPE(*ALL) ?*SAVF(LIBSAVF/SAVF) ??RSTLIB(LIBSAV2)

Al ejecutar el programa obtendremos la siguiente pantalla:


De esta forma dejamos al usuario cambiar que objetos quiere restaurar y en que biblioteca, aunque le mostramos una por omisión y si la deja en blanco el prompt vuelve a mostrar el valor que le hemos pasado desde programa; también puede ver que archivo de salvar se utilizará, pero no el resto de parámetros, ni aun pulsando F10 o F9.

Veamos que ocurre si añadimos el carácter ? delante del mandato RSTOBJ, también añadimos ?- en el parámetro DEV :

? RSTOBJ ??OBJ(*ALL) SAVLIB(LIBSAV) ?-DEV(*SAVF) OBJTYPE(*ALL) ?*SAVF(LIBSAVF/SAVF) ??RSTLIB(LIBSAV2)


Ahora vemos el resto de parámetros obligatorios que no se mostraban antes, excepto DEV que tiene la opción de prompt ?-, y además podemos pulsar F10 para ver el resto de parámetros.

Para controlar el prompt de los parámetros opcionales se utiliza ?% y ?&, aunque puede complicarnos el programa ya que hay parámetros que pueden depender de si usamos otros.

Nota: Si usamos el prompt selectivo también debemos de incluir la siguiente instrucción por si nos pulsan F3=Salir o F12=Cancelar:
MONMSG MSGID(CPF6801) /* F3 o F12 */

Más información en iSeries Information Center

domingo, 2 de noviembre de 2008

Asignar prioridad automáticamente

Como asignar una prioridad automáticamente para ciertos trabajos, o aplicaciones.

Supongamos que tenemos unos trabajos que queremos que tengan cierto tipo de prioridad (alta o baja) en la ejecución, habitualmente se utilizan los parámetros RUNPTY y TIMESLICE, para ello habremos de crear una clase especial para nuestros trabajos y es recomendable también crear un subsistema especial para dichos trabajos.

El procedimiento a seguir para crear este entorno especial:
  1. Crear la cola de trabajos asociada al subsistema:
  2. CRTJOBQ JOBQ(QGPL/SPECIAL) TEXT('Job queue for specials jobs Subsystem')
  3. Crear el subsistema:
  4. CRTSBSD SBSD(QGPL/SPECIAL) POOLS((1 *BASE) (2 *SHRPOOL1)) MAXJOBS(*NOMAX) TEXT('Subsystem for specials jobs')
  5. Con esto conseguimos que el trabajo, de tipo subsistema, se ejecute en el pool de memoria base y el resto de trabajos del subsistema se ejecutaran en el pool de memoria *SHRPOOL1.
  6. Añadir la cola de trabajos al subsistema:
  7. ADDJOBQE SBSD(QGPL/SPECIAL) JOBQ(QGPL/SPECIAL) MAXACT(*NOMAX) SEQNBR(10)
  8. Poner *NOMAX, o el numero máximo de trabajos, que queremos que se ejecuten por esa cola, el numero de secuencia es importante por si tenemos más de una cola de trabajos.
  9. Crear la nueva clase:
  10. CRTCLS CLS(QGPL/SPECIAL) RUNPTY(25) TIMESLICE(10000) PURGE(*NO) TEXT('Class for subsystem of special jobs')
  11. Asignar las entradas de direccionamiento para solo los trabajos batch que queramos usen la nueva clase:
  12. ADDRTGE SBSD(QGPL/SPECIAL) SEQNBR(10) CMPVAL('SPECIAL') PGM(QCMD) CLS(QGPL/SPECIAL) POOLID(2)
  13. Añadir entradas de direccionamiento para el resto de trabajos:
  14. ADDRTGE SBSD(QGPL/SPECIAL) SEQNBR(9999) CMPVAL(*ANY) PGM(QCMD) CLS(*LIBL/QBATCH) POOLID(2)
  15. Con estas dos entradas de direccionamiento conseguimos que:
  16. Los trabajos que, en la descripción de trabajo, envían como direccionamiento el valor RTGDTA('SPECIAL') usaran la clase QGPL/SPECIAL que les asignará un RUNPTY de 25 y un TIMESLICE de 10.000.
  17. El resto de trabajos usará la clase QGPL/QBATCH, que les asigna un RUNPTY de 50 y un TIMESLICE de 5.000.
  18. En ambos casos los trabajos se ejecutaran por el POOLID 2, o sea en este caso en el *SHRPOOL1 (ver paso 5).
  19. A continuación creamos una nueva descripción de trabajo, o modificar la que queramos usar, para que los trabajos se sometan por el nuevo subsistema:
  20. CRTJOBD JOBD(QGPL/SPECIAL) JOBQ(QGPL/SPECIAL) TEXT('Job description for special jobs') RTGDTA('SPECIAL')
  21. También podemos someterlos con SBMJOB, pero entonces habrá que acordarse de comprobar y modificar manualmente el parámetro RTGDTA en el mandato SBMJOB, en caso contrario usaran la clase por omisión asignada a *ANY.
  22. Si además queremos usar el mismo subsistema para que se conecte alguna pantalla tendremos de:
  23. Añadir el pool de memoria interactivo al subsistema:
  24. CHGSBSD SBSD(QGPL/SPECIAL) POOLS((1 *BASE) (2 *SHRPOOL1) (3 *INTERACT))
  25. Añadir una entrada de direccionamiento para los trabajos interactivos:
  26. ADDRTGE SBSD(QGPL/SPECIAL) SEQNBR(20) CMPVAL('QCMDI') PGM(QCMD) CLS(*LIBL/QINTER) POOLID(3)
  27. Añadir el nombre de dispositivo de pantalla que tendrá acceso al subsistema:
  28. ADDWSE SBSD(QGPL/SPECIAL) WRKSTN(Device_name)
  29. Con esto conseguimos que los trabajos interactivos se les asigne los valores de la clase QINTER y que son de RUNPTY 20 y un TIMESLICE de 2.000.
  30. Además se ejecutaran en el pool de memoria para trabajos interactivos (*INTERACT), optimizando de esta forma el funcionamiento del ajuste automático de rendimiento del sistema:
  31. Ahora solo nos queda:
  32. Asignar memoria al pool compartido *SHRPOOL1, si no lo estamos usando (podemos comprobarlo con WRKSHRPOOL):
  33. CHGSHRPOOL POOL(*SHRPOOL1) SIZE(256) ACTLVL(1)
  34. Finalmente arrancar el nuevo subsistema:
  35. STRSBS SBSD(QGPL/SPECIAL)
  36. El tamaño del pool y el nivel de actividad se irán ajustando automáticamente si tenemos el ajuste de rendimiento del sistema activado:
  37. DSPSYSVAL SYSVAL(QPFRADJ)


Nota:
Si queremos deshacer la asignación de memoria en *SHRPOOL1 ejecutar el mandato CHGSHRPOOL POOL(*SHRPOOL1) SIZE(*NOSTG)


¿Como podemos controlar la memoria asignada a estos trabajos y de esta forma controlar el ajuste automático del sistema?, entonces habéis de leer la entrada Memoria para subsistema publicada anteriormente.