IBM Support

如何通过User Space调用IBM i List API

Technical Blog Post


Abstract

如何通过User Space调用IBM i List API

Body

文本介绍了IBM i List API 的概念,并阐述了User Space与List API的关系及注意事项。举例说明如何通过User Space获取List API返回的内容。

 

1. User Space简介

User Space是类型为*USRSPC的IBM i对象,可以存储任何用户自定义数据。User Space是位于系统域或用户域的持久化对象。具有以下三个特点:

  • 可以自动扩展
  • 能在job或系统之间共享数据
  • User Space及其数据在系统IPL(Initial Program Load)后依然存在

用户可以通过QDEVELOP/CRTUSRSPC USRSPC(<User Space Name>) 命令或Create User Space (QUSCRTUS) API创建User Space,User Space的预定义大小为16MB。需要注意的是,如果用户拥有对User Space的*CHANGE权限,当List API返回的数据量超过User Space预定义的大小时,List API能够自动增大User Space的容量。 否则,User Space中的数据将不全,List API将返回一个类似于CPF3CAA 的authority error错误信息。

IBM i 系统上所有List API 均具有统一的数据结构,方便开发人员使用(参见参考文献List API 数据结构)。List API数据结构中包含输入参数、头,和List输入部分。

IBM i提供了以下命令或API操作User Space:

  • 创建User Space

              API“QUSCRTUS”或命令“CRTUSRSPC”用于创建一个User Space

  • 删除User Space

              API“QUSDLTUS”或命令“DLTUSRSPC”用于删除一个User Space

  • 读取User Space中的数据

              API“QUSRTVUS”可以读取User Space中的数据

  • 更改User Space中的数据

              API“QUSCHGUS”能够改变User Space中的数据

 

2. List API简介

应用程序通常可以通过调用List API来获取IBM i上某种对象的集合。例如,使用QpzListPtfGroups API 能够返回IBM i 系统上的PTF组的集合;QSYLSTVC API能够返回系统上认证list上证书的集合。如果用户向IBM i系统请求两个或多于两个的对象时,可以考虑使用User Space,这样List API返回的数据便可以存储在User Space中。除了List API返回的数据以外,User Space中还含有一些元信息告诉用户如何读取其中的数据,这些元信息包括:

  • 数据起点
  • 数据元素个数
  • 每个数据元素的长度

当然,在调用List API之前,需要准备好API需要的各种参数,也要指定用于存储返回数据的User Space的名字。每个API需要的参数格式不尽相同,详细情况请参考IBM Info Center

通过程序读取User Space中的数据时,程序员可以根据编程语言是否支持指针而采取不同的读取方式。如果编程语言支持指针,可以直接将User Space的地址赋给一个指针读取或改变其中的内容;如果编程语言不支持指针,则可以利用API“QUSRTVUS”读取User Space中的内容。

 

3. 示例程序

下面我们通过清单1举例说明如何使用User Space获取List API QpzListPtfGroups返回的IBM i 系统上的PTF组的集合。

清单1使用User Space LSTPTFGRP存放QpzListPtfGroups API返回的内容,QTEMP为LSTPTFGRP所在的Library。程序首先删除同名的User Space并创建新的User Space,避免因API返回的数据被写入到一个存在数据的User Space中引起数据混乱;然后调用QpzListPtfGroups API,将数据存入User Space;最后读取User Space中的数据。

QpzListPtfGroups API的输入参数包括User Space名、数据返回的格式代码和PTF Group名的字符集代码,error_code存放错误信息。读取User Space时轮询每个Entry的信息,并在读取结束后删除该User Space,避免改User Space被其他程序使用导致的数据混乱。运行该程序,终端将打印出该IBM i上所有的PTF Group。QpzListPtfGroups API的详细介绍参见IBM I Info Center QpzListPtfGroups的介绍。

清单1. 在程序中使用User Space获取List API返回的内容

1   #include <stdio.h>

2   #include <qusec.h>     /*error code结构 */

3   #include <qusgen.h>    /*User Space 相关头文件 */

4   #include <quscrtus.h>  /*使用QUSCRTUS API创建User Space */

5   #include <qusdltus.h>

6   #include <qusptrus.h>

7   #include <qpzgroup.h>   /* PTF Group 头文件 */

8   #define USRSPC_PTFGRP         "LSTPTFGRP QTEMP     "   /* User Space名 */

9   /* User Space 描述*/

10  #define USRSPC_PTFGRP_DESC  "User space for QpzListPtfGroups                 "

11  int main(int argc, char* argv[])

12  {

13    Qus_Generic_Header_0100_t* header; /* 指向User Space header的指针*/

14    Qpz_LSTG0100_t* listdata; /* 指向User Space数据部分的指针 */

15    Qus_EC_t error_code; /* 错误代码 */

16    int i;

17    error_code.Bytes_Provided = sizeof(Qus_EC_t);

18    QUSDLTUS(USRSPC_PTFGRP,&error_code); /* 删除同名的User Space,避免数据混乱*/

19    error_code.Bytes_Provided = sizeof(Qus_EC_t);

20    QUSCRTUS(USRSPC_PTFGRP, "          ", 10240, " ","*ALL      ",

21             USRSPC_PTFGRP_DESC, "*YES      ", &error_code);   /* 创建一个新的User Space */

22    if(error_code.Bytes_Available)

23    {

24       printf("QUSCRTUS error: Exception_Id:[%s]\n",

25       error_code.Exception_Id);

26       return;

27     }

28    error_code.Bytes_Provided = sizeof(Qus_EC_t);

29    //调用系统API QpzListPtfGroups,列出系统上PTF组的集合

30    QpzListPtfGroups(USRSPC_PTFGRP, "LSTG0100", 37, &error_code);

31    if(error_code.Bytes_Available) /* 调用QpzListPtfGroups失败,处理错误信息 */

32    {

33       printf("QpzListPtfGroups error: Exception_Id:[%s]\n",

34       error_code.Exception_Id);

35       return;

36     }

37     error_code.Bytes_Provided = sizeof(Qus_EC_t);

38     QUSPTRUS(USRSPC_PTFGRP, &header, &error_code); /* 获得User Space的指针 */

39     if(error_code.Bytes_Available)  /* 调用QUSPTRUS失败,处理错误信息 */

40     {

41        printf("QUSPTRUS error: Exception_Id:[%s]\n",

42        error_code.Exception_Id);

43        return;

44      }

45      /* 读取User Space中的信息 */

46      listdata = (Qpz_LSTG0100_t*)(((char*)header) + header->Offset_List_Data);

47      for(i = 0; i < header->Number_List_Entries; i++) /* 轮询每个Entry */

48      {

49         printf("listdata[%d]:[%s][%d][%d]\n", i, listdata[i].Name, listdata[i].Level,

50                listdata[i].Status);

51       }

52       error_code.Bytes_Provided = sizeof(Qus_EC_t);

53       QUSDLTUS(USRSPC_PTFGRP,&error_code); /* 删除该User Space */

54   }

在代码清单1中,第13行至第28行是为了调用QpzListPtfGroups API准备各个参数,包括准备错误信息存放位置,创建User Space等。其中第20行和第21行创建User Space,用于存放QpzListPtfGroups API返回的内容。

需要注意的是:List API 本身并不返回数据,只返回list包含对象的个数,真正的对象信息被存储到User Space中。因此,用户在调用List API之前需要预先创建一个User Space,并在调用List API时指定该User Space。List API返回的每条数据长度都相等,该长度需要从User Space中获得。

第30行调用QpzListPtfGroups API。代码第38行使用QUSPTRUS API获取读User Space的指针,准备读取QpzListPtfGroups API。代码第46行至第51行一次轮询List API返回到User Space中的每条记录,并打印输出记录内容。最后,代码第53行删除该User Space。

以上介绍了IBM I List API和User Space的概念,以及二者的关系。并通过一段C语言程序举例说明IBM I List API的用法。除C语言外,IBM i List API还支持其他语言的调用,包括Java等。IBM i 信息中心举例说明了以下四种语言的用法:

  • OPM RPG
  • ILE CL
  • ILE RPG
  • ILE COBOL

 

参考文献

1. IBM i 信息中心List API 介绍

2. List API 数据结构

3. User Space Java doc

 

作者:张荣荣、王胜军

了解更多关于IBM i 的信息,请关注IBM i 新浪官方微博@IBMiChina

 

[{"Business Unit":{"code":"BU058","label":"IBM Infrastructure w\/TPS"},"Product":{"code":"SWG60","label":"IBM i"},"Component":"","Platform":[{"code":"PF025","label":"Platform Independent"}],"Version":"","Edition":"","Line of Business":{"code":"LOB57","label":"Power"}}]

UID

ibm11144732