Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2339099
  • 博文数量: 321
  • 博客积分: 3440
  • 博客等级: 中校
  • 技术积分: 2992
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-24 09:08
个人简介

我就在这里

文章分类

全部博文(321)

文章存档

2015年(9)

2014年(84)

2013年(101)

2012年(25)

2011年(29)

2010年(21)

2009年(6)

2008年(23)

2007年(23)

分类: 其他UNIX

2014-06-17 14:24:37

1、as400 磁盘信息监控

#

 

AS/400是一款非常特别的机器,操作系统的名字叫OS/400,我觉得当初创造它的人基本上没有受到UNIX操作系统的影响,当然更没有受到DOS/WINDOWS操作系统的影响。
C++、JAVA有对象的概念,OS/400管理的东西也几乎都叫做对象。
最 初OS/400的文件系统是“库”文件系统。我们知道,UNIX/DOS/WINDOWS等操作系统的文件是放在根目录/子目录中的,允许有多级子目 录,OS/400的“库”文件系统中,“库”相当于UNIX/DOS/WINDOWS等操作系统的子目录,其中可以存放文件等对象,但“库”中不能有其它 “库”(QSYS库是特例,IBM规定其它库均存放在QSYS库中),即相当于子目录只有一级。
到后来,OS/400也同时支持UNIX 类的文件系统,叫做集成文件系统IFS,你写个C程序,编译时选择支持IFS,则也可以读写类似“/usr/local/lib/perl5 /dbsamples”的路径。好象读写IFS的程序跑起来都比较慢。我想,既然要使用UNIX文件系统,何必用AS/400?买台RS/6000不就得 了?所以OS/400中,我们主要还是玩“库”文件系统吧。
OS/400的文件FILE分为源程序文件(SRCPF)、物理文件 (PF)、逻辑文件(LF)、显示文件(DSPF)、打印文件(PRTRF)等很多种。OS/400操作系统与其中的数据库OS/400是紧密集成在一起 的,它的PF、SRCPF就相当于ORACLE等数据库的TABLE,LF类似于ORACLE等数据库的VIEW。源程序文件(SRCPF)其实是一种特 殊的物理文件(PF),它包含3个字段:行号、内容、修改日期,我们写的每一行源程序都保存为其中的一条记录。
OS/400 的文件FILE中有一个特殊的概念:“成员”member。可以理解成member是Table中的一部分记录。对于源程序文件(SRCPF)我们可以把 其所在的“库”理解成UNIX/DOS/WINDOWS下的第1级子目录,file理解成UNIX/DOS/WINDOWS下的第2级子目录,file中 的member理解成UNIX/DOS/WINDOWS下的源程序文件。对于数据文件即物理文件PF,你可以把2007年的数据命名为一个MEMBER, 例如叫DATA2007,再把2008年的数据命名为一个MEMBER,例如叫DATA2008。
OS/400 的PF与DOS/WINDOWS下的xBase/FoxPro的.DBF文件结构有得一比。它是定长字段的记录格式。如果你定义一个10字节长的字符字 段,字段值若填1个字符,则后面以9个EBCDIC编码空格填充。如果你删除一条记录,系统只是做了一个删除标记,就象.DBF一样做个删除标记,不过 IBM可不提供FoxBase那样的RECALL命令来恢复删除的记录。
我们在DOS/WINDOWS下写个C程序,要先把 .c 编译成 .obj,再连接成 .exe 才能运行得到结果。与此对应,OS/400中的C程序是SRCPF中的一个member,.obj的东西在OS/400中叫MODULE,.exe的东西 在OS/400中叫PROGRAM(类型*PGM)。可能是IBM为了防止各位高手研究OS/400可执行程序的秘密从而制造virus,它允许你通过 FTP下载SRCPF、PF等对象到你的PC,但就是不让你下载*PGM对象。


【前言】
    对于AS/400数据库程序员来说,让他们完全抛弃RPG而转向JAVA是不现实、不理智的。这不仅仅是感情上的问题;在技术上,RPG现在仍然是AS /400操作数据库性能最好的语言。迄今为止,IBM也从未在任何资料中宣称JAVA的数据库性能可以全面取代RPG。但不可否认的是,从语言本身来 说,RPG的设计理念、编程方式无疑是落后了,而且过于专业化,在某种程度上,不利于一个操作系统平台的推广。
    而JAVA则是一个“大众化”的编程语言,有着现代编程的全部特征和平易近人的面孔。
    作为IBM力推的工具,在性能上,JAVA不会在RPG后面落后很久。除了数据库领域,IBM为JAVA提供了很多AS/400的系统接口,我们甚至可以 用JAVA编写系统应用。面对现有的大量RPG程序,我们可以采取JAVA与之相结合的方式,改变传统“CL做主控程序,RPG做子程序”的做法,让 JAVA负责系统方面的控制,如登录、用户界面,RPG程序专门负责处理数据,各取所长,给最终用户提供更友好的界面、更简单的操作。
【实现技术】
    现在介绍如何利用分布式程序调用(Distributed Program Call,缩写为DPC)的技术,可以以简单的方式很好地实现JAVA和RPG混合编程。
    DPC是AS/400 Toolbox提供的一个接口,通过它我们可以在JAVA程序中调用一个以其它语言编写的程序(如RPG、CL、COBOL)去完成某项工作。一般 JAVA程序放在客户机上,以远程方式去调用AS/400上的某个RPG程序去处理数据库,如下图:  
【应用事例】
    下面我们假定AS/400上已经存在了一个RPG程序,位于TEST库下,程序名为PGMCALL,这个程序处理某个PF,输入客户编号,返回客户姓名。
    在这里主要是介绍DPC接口,至于这个RPG程序的具体实现,在这里不作赘述。
    我们假定这个RPG有2个入口参数:
         参数名 类型 描述
NUMBER Pack(3,0) 客户编号,仅用于输入
NAME Character(30) 客户姓名,仅用于输出
1、建立一个类:TestDPC,其定义如下:

  1. import java.io.*;
  2. import java.math.*;
  3. import com.ibm.as400.access.*;
  4. public class TestDPC{
  5.    private AS400 as400;
  6.    private ProgramCall pgm;
  7.    private String progname = "/qsys.lib/test.lib/pgmcall.pgm";}
2、添加TestDPC的connectDPC()

  1. public void connectDPC(String system,String user,String password){
  2.    as400=new AS400(system,user,password);
  3.    try
  4.    { //连接相关的Server程序
  5.      as400.connectService(AS400.COMMAND);
  6.    }
  7.    catch(Exception e)
  8.    { System.out.println("连接AS/400服务失败!");
  9.      System.exit(0);
  10.    }
  11.     //建立远程程序对象
  12.    pgm=new ProgramCall(as400);
  13.     //设置参数,并转换为AS/400格式
  14.    ProgramParameter[]parmlist = new ProgramParameter[2];
  15.    AS400PackedDecimal number = new AS400PackedDecimal(3,0);
  16.    parmlist[0] = new ProgramParameter(number.toBytes(new BigDecimal(222)),3);
  17.    AS400Text name = new AS400Text(30);
  18.    parmlist[1] = new ProgramParameter(name.toBytes(""),30);
  19.    try
  20.    { //将程序路径、参数表与ProgramCall对象捆绑
  21.      pgm.setProgram(progname,parmlist);
  22.    }
  23.    catch(Exception e)
  24.    { System.out.println("设置参数失败!");
  25.    }
  26.    try
  27.    { if(pgm.run() = = true)
  28.        { System.out.println(name.toObject(parmlist[0].getOutputData()));
  29.           System.out.println(number.toObject(parmlist[1].getOutputData()));
  30.           System.out.println("远程调用成功!");
  31.        }
  32.      else
  33.        { System.out.println("远程调用失败!");
  34.        }
  35.    }
  36.    catch(Exception e)
  37.    {
  38.         System.out.println("远程调用异常!");
  39.         e.printStackTrace();
  40.    }
  41.   }


【要点说明】
   使用DPC技术最关键的地方是参数要在AS/400和JAVA两种格式之间转换,这里我着重对涉及参数的几个方法介绍。
(1)ProgramParameter[]parmlist = new ProgramParameter[2];
说明:建立参数数组,数组元素个数即参数的个数。
(2)AS400PackedDecimal number = new AS400PackedDecimal(3,0);
     parmlist[0] = new ProgramParameter(number.toBytes(new BigDecimal(222)),3);
     AS400Text name = new AS400Text(30);
     parmlist[1] = new ProgramParameter(name.toBytes(""),30);
说明:设置两个参数,并转换为AS/400格式。注意ProgramParameter的构造函数有三种方式:
     public ProgramParameter(byte data[])——该参数只用于输入,以字节流方式传送。
     public ProgramParameter(int size)——该参数只用于输出,指定输出字节大小。
     public ProgramParameter(byte data[],int size)——该参数输入输出均可。
     例中用toBytes()方法将JAVA对象转换为字节流。
(3)pgm.run()
说明:执行远程程序,如果远程程序正常运行返回true,否则返回false。
(4)name.toObject(parmlist[0].getOutputData())
说明:取得返回值并从AS/400格式转换为JAVA的Object。
Command to list Database file members 一些有价值的资料






 

WRKACTJOB
这 个使用的频率应该是最高的吧,在这里只提一个比较有用的用法:Coding的时候断线异常退出时,再登录之后,用2进入刚才编辑的程序,不是会报错“正在 被使用”嘛。除了等一会,一直等到它自动退出之外,还可以用WRKACTJOB + 10,来查找刚才自己的那个进程(显示出来的命令应该是STRSEU),然后把它KILL掉就行了。
DSPFD
DSPFD + PF名,查看文件的信息,包括文件的MEMBER数,总记录数,被删除的记录数,CCSID等等。
DSPFD + LF名,查看逻辑文件的键值,结合DSPDBR,可以找出一个PF文件对应的所有LF文件的键值。
DSPFD + 库名 + *MBRLIST,可以看到该库之下所有的文件名。
这个命令可以使用*OUTFILE,将输出变成一个文件。灵活运用,将会是很多自行编写的工具的基础之一。
DSPFFD
注意,和上面的命令相差一个“F”,表示查看PF文件的字段信息。比如该PF文件共有多少个字段,每个字段的类型如何。
与DSPFD相似,DSPFFD也可以使用*OUTFILE,将输出变成一个文件。同理,灵活运用,也是众多自行编写工具的基础。
MRGSRC
比较两个程序的差异。按照A、B、A的顺序,MRGSRC时,A程序在上面,B程序在下面,白色的地方,即表示两个程序的差异。
F13表示接受当前差异,F17表示接受所有差异,F16表示继续查找下一处差异。
在接受差异时,表示按照B程序,更改A程序。(即B程序不变)
把SPLF变成MEMBER(源文件)
必须知道SPLF名,以及生成SPLF的JOB、USR、NUMBER名
CRTSRCPF FILE(库名/SRCPF) RCDLEN(212) IGCDTA(*YES)
CHGPF FILE(库名/SRCPF) CCSID(935)
CRTPF FILE(库名/PF) RCDLEN(200) IGCDTA(*YES)
CPYSPLF FILE(SPLF名) TOFILE(库名/PF) +
JOB(NUMBER名 / USER名 / JOB名) SPLNBR(*LAST)
CPYF FROMFILE(库名/PF) TOFILE(库名/SRCPF) +
TOMBR(MBR0001) MBROPT(*ADD) FMTOPT(*CVTSRC)
最后,SRCPF下的MBR001就是SPLF转成的MEMBER
当然,做为中间转换的临时文件,PF文件会保留SPLF的信息。
把MSGF变成SPLF
CHGSYSLIBL LIB(QSYS2989)
DSPMSGD RANGE(*FIRST *LAST) MSGF(MSGF所在库名/MSGF名) +
DETAIL(*BASIC) OUTPUT(*PRINT)
CHGSYSLIBL LIB(QSYS2989) OPTION(*REMOVE)
这个命令,再结合上面的“把SPLF变成MEMBER”,就可以把MSGF搞成MEMBER,然后再FTP到WINDOWS上,就可以很方便地查找已定义的MSG信息了。
不过必须要有权限执行CHGSYSLIBL这个命令。
DSPOBJD
根据程序名,查找编译时源代码所在的库名、SRCFILE名。
DETAIL参数用“*SERVICE”,OBJTYPE选项用“*PGM”
不过好象RPGLE的程序用这个命令查不出来,要用DSPPGM命令。
DSPPGM
根据目标
DSPPGM + RPGLE程序名,参数用“*MODULE”,然后再选择5,就可以看到编译时RPGLE程序时,源代码所在的库名,SRCFILE名。
DSPDBR
根据物理文件查其对应的所有逻辑文件
DSPPGMREF
查找程序与PF、LF的关系。
PGM参数用“*ALL”,OUTPUT参数用“*OUTFILE”,OBJTYPE参数用“*ALL”,然后执行,再输入输出文件名与所在库就可以了。然之后,就可以SQL在这个生成的文件中查找(生成的过程可能会有点慢,要耐心)。
在 生成的文件中,字段WHRFNM,表示记录格式名。举例来说,如果物理文件更改过,那么物理文件与逻辑文件就都重新编译过了,所以它们对应的的所有的程序 都要重新编译,通常物理文件与逻辑文件使用相同的记录格式名(当然,如果不同就算了)这时就需要按记录格式名来查找。比如SELECT * FROM 刚生成的文件 WHERE WHRFNM = “记录格式名”,找出所有涉及到这个记录格式名的程序。
在生成的文件中,字段WHFNAM,表示文件名,包括物理文件与逻辑文件。比如说当我们只修改了某个逻辑文件时,那么当然是只需要重新编译与该逻辑文件有关的程序,也就是说只根据文件名来查找就足够了。
RTVCLSRC
如果编译CL程序时,不是刻意带*NONE参数,那么一般来说CL程序都可以使用这个命令来反编译。具体用途试试便知
RGZPFM
重整文件,即回收已删除记录的空间。不过这个命令我没实际用过。
WRKMSGQ QSYSOPR
显示错误信息
CHGCMGDFT
更改某些命令的默认参数,如更改CRTPF的WAITRCD参数:
CHGCMDDFT CMD(QSYS/CRTPF) NEWDFT(‘WAITRCD(*IMMED)’)

DSPDBR + 物理文件名,查看该物理文件对应的逻辑文件

CLRPFM 清空文件

wrksplf     显示工作池

StrDBG 进入调试状态

EndDBG 终止调试

Go LICPGM      安装程序菜单

Go ASSIST      辅助菜单

DspWSUsr       显示用户信息

Go CMDFile     命令菜单

Go Major       主菜单

SNDMSG           发送消息

SNDBRKMSG       发送中断消息

DSPMSG           显示消息

WRKMSG           处理消息

WRKMSGQ         处理消息队列

CRTMSGQ         创建消息队列

DLTMSGQ         删除消息队列

CHGMSGQ         修改消息队列

CLRMSGQ         清除消息队列

DSPOBJD          显示对象描述符

WRKOBJ          管理对象

MOVOBJ          移动对象

RNMOBJ          重命名对象

CRTDUPOBJ       创建对象副本

WRKOBJPDM       进入程序开发对象管理器

CPYF            复制文件

CHKOBJ          检查对象

ALCOBJ          分配对象

DLCOBJ          收回对象

WRKOBJLCK       进入锁定对象

CLRLIB           清除库

CRTLIB          创建库

CPYLIB           复制库

DLTLIB          删除库

DSPLIB          显示库

DSPLIBD         显示库描述符

WRKLIB          管理库

CHGCURLIB       改变当前库

ADDLIBLE        加入库列表节点

CHGLIBL         改变库列表

RMVLIBLE        删除库列表节点

EDTLIBL         编辑库列表

CHGSYSLIBL      改变系统库列表

WRKFLR      管理文件夹

WRKLNK     管理对象链接

与子系统描述相关的命令:

STRSBS                启动子系统

ENDSBS                终止子系统

WRKSBS         管理子系统

WRKSBSJOB     管理子系统作业

CHGSBSD      改变子系统描述
CRTSBSD   创建子系统描述
DLTSBSD    删除子系统描述
DSPSBSD    查看子系统描述
PRTSBSDAUT 打印子系统描述
WRKSBSD    可对子系统描述进行创建、修改、删除等操作

CRTPF FILE(TESTLIB/PFLIST) RCDLEN(200) IGCDTA(*YES)

                  File                                                      
Opt File        Nbr   Job         User        Number Queue       Library  
    QPUOPRTF       3 ST000001 USER01 552332 QPRINT     QUSRSYS  
    QPUOPRTF       4 ST000001 USER01 552332 QPRINT     QUSRSYS

CPYSPLF FILE(QPUOPRTF) TOFILE(TESTLIB/QDDSSRC) SPLNBR(3) TOMBR(PFLIST)
SQL是与平台无关的数据库操作语言,虽然它无法处理iSeries上包含多成员的物理文件(表),但是它与RPG/COBOL一样,是可以处理写入数据库文件的物理文件成员。所以,您可以通过命令OVRDBF和SQL一起来处理多成员的物理文件:
OVRDBF FILE( name ) TOFILE( toname ) MBR( name ) OVRSCOPE( *JOB )
这里有几点值得注意的地方:
1. 您只能OVERRIDE一个成员,而不是所有成员;
2. 参数OVRSCOPE( *JOB )保证了OVERRIDE的动作即使在不同的activation group中执行,也能被识别;
3. 建议使用参数OVRSCOPE( *JOB ),除非您希望明确的限定OVERRIDE的范围。
要解除OVERRIDE,请使用命令DLTOVR:
DLTOVR FILE( name ) LVL( *JOB )
参数LVL的意义相当于OVRDBF命令中的参数OVRSCOPE,指定了OVERRIDE的范围。
根据您使用SQL的不同方法,OVERRIDE成员的方法也不尽相同:
1. iSQL环境:
在iSQL环境中,最简单的方法是在进入SQL环境之前在5250命令行运行命令OVRDBF,如果您已经进入了iSQL环境,您也可以使用以下的命令启动5250命令行:
CALL QCMD
在执行完OVRDBF命令后,按F3就可以退出5250命令行,返回iSQL环境,注意,如果您指定的参数OVRSCOPE( *JOB ),系统仍然能够识别您要OVERRIDE的内容。
2. 嵌入式SQL环境:
在嵌入式SQL环境中,要想OVERRIDE一个成员,就要使用QCMDEXC,举例说明,在ILE RPG中,您定义的QCMDEXC原型为:
d runCommand pr extpgm( 'QCMDEXC' )
d command_ 999 const
d size_ 15p 5 const
d commandSize s 15p 5 inz( 999 )
接着, 在执行SQL语句之前运行以下的OVERRIDE:
/free
runCommand( 'OVRDBF FILE(name) TOFILE(name) ' 'MBR(name) OVRSCOPE(*JOB)': commandSize )
/end-free
3. ODBC/OLE DB环境:
3.1 通过存储过程调用来实现OVRDBF
在ODBC中是可以通过调用要运行的命令的系统API来执行该命令。通过这种技术,就可以在执行SQL之前将您希望使用的成员使用OVRDBF命令来OVERRIDE。例如:
CALL QSYS.QCMDEXC('OVRDBF FILE(USER1) TOFILE(MYLIB/USER1) MBR(COMPANY) OVRSCOPE(*JOB)', 0000000066.00000)
其中:0000000066.00000分别是10位/5位的固定长度的十进制字段,在例子中的值66是单引号中全部字符的长度,包括空格。注意:剩下的数字位必须为0。
下面的URL上有一个Visual Basic ODBC的例子,请参阅:

3.2 通过SQL别名来实现OVRDBF
在OS/400 R430及以上版本支持SQL有关别名的语句。为每一个您需要访问的成员创建一个别名,并通过在ODBC中访问这些别名来达到访问不同成员的目的。由于别 名是固定的,所以只需要创建一次,任何SQL工具,例如:iSQL,3.1中提到的ODBC例程,等等,都可以用来创建这些别名。例如:
CREATE ALIAS MYLIB.FILE1MBR1 FOR MYLIB.MYFILE(MBR1)
CREATE ALIAS MYLIB.FILE1MBR2 FOR MYLIB.MYFILE(MBR2)
创建了不同的别名后,PC上的应用就可以指定MYLIB.FILE1MBR1 或 MYLIB.FILE1MBR2 来访问您想要访问的成员了。
在ODBC中使用别名的注意事项:
1. 一个别名被ODBC目录功能返回的类型是"ALIAS"。有一些应用可能不会把别名当成可用的表名显示在数据库中;
2. 即使物理文件,库不存在了,别名依然可以独立存在(类似于符号连接);
3. 在SQL语句中使用别名参照的成员是有一些限制的,具体内容参照DB2 for AS/400 SQL Reference (SC41-5612)
书中的详细描述。

通过JTOPEN API 集成文件系统获取OS/400系统库/文件中的MEMBER


  1. private String listMembersOfIFSFile() throws IOException{
  2.    AS400 system = new AS400(host, userName, password);
  3.    IFSFile file=new IFSFile(system,"/QSYS.LIB/"+libName+".LIB/"+tabName+".FILE");
  4.    Calendar calendar = Calendar.getInstance();
  5.    int days=calendar.get(Calendar.DAY_OF_YEAR);
  6.    String memberStart="Q"+days;
  7.    List<String> members=new ArrayList<String>();
  8.    // 获取当天的member列表
  9.    try {
  10.    if(file.isDirectory()){
  11.     String[] strs=file.list();
  12.     for(int i=0;i<strs.length;i++){
  13.      if(strs[i].startsWith(memberStart)){
  14.       members.add(strs[i]);
  15.      }
  16.     }
  17.    }
  18.   }finally{
  19.    system.disconnectAllServices();
  20.   }
  21.   /*
  22.    * 如果当天的member列表大小为1,就获取当前值;否则如果member大小大于1则
  23.    * 取列表中时间最大的那一个
  24.    */
  25.   String mem=null;
  26.   if(members.size()==1){
  27.     mem=members.get(0);
  28.   }else if(members.size()>1){
  29.     String member1=members.get(0).substring(0,members.get(0).indexOf("."));
  30.     for(int i=1;i<members.size();i++){
  31.       String member2=members.get(i).substring(0,members.get(i).indexOf("."));
  32.       member1=member1.substring(member1.length()-6,member1.length());
  33.       member2=member2.substring(member2.length()-6,member2.length());
  34.       member1=member1.substring(0,2)+":"+member1.substring(2,4)+":"+member1.substring(4,member1.length());
  35.       member2=member2.substring(0,2)+":"+member2.substring(2,4)+":"+member2.substring(4,member2.length());
  36.       DateFormat df = new SimpleDateFormat("HH:mm:ss");
  37.       try {
  38.      Date date1=df.parse(member1);
  39.      Date date2=df.parse(member2);
  40.      if(date1.before(date2)){
  41.       mem=members.get(i);
  42.       member1=members.get(i).substring(0,members.get(0).indexOf("."));
  43.      }
  44.     } catch (ParseException e) {
  45.     }
  46.     }
  47.   }
  48.   return mem;
  49.   }
  50. }


AS400内存管理
AS400 服务器采用的是数据库操作系统,对于400系统的内存使用信息来说分析内存的使用情况是一件复杂的事情。OS/400独特的系统结构导致内存使用率对于 OS/400系统来说并无实际意义,OS400系统内存使用率一般都在90%以上。OS/400系统内存使用信息主要表现在系统的内存池(包括共享内存 池)的性能参数上来,比如池大小、保留大小、最大活动线程数、DB Faults、DB Pages及Non DB Faults、Non DB Pages等。

阅读(2968) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~