第十四章 Caché 命令大全 JOB 命令

第十四章 Caché 命令大全 JOB 命令

在后台运行进程。

重点

  1. 判断JOB是否启动成功$ZCHILD
  2. 如何判断JOB执行完毕 ,最佳方法是在正在运行的代码中提供某种类型的日志记录和错误捕获,或设置全局变量,并检测。
  3. JOB 冒号之间参数的含义。
  4. 启动JOB进程后,Caché会为其分配单独的内存分区,并为其分配唯一的JOB编号(也称为进程ID或PID)。JOB号存储在$JOB特殊变量中。
  5. $ZCHILD只能告诉远程作业已创建;它不会告诉远程作业是否成功运行。确定远程进程是否运行无错误并运行到完成的最佳方法是在正在运行的代码中提供某种类型的日志记录和错误捕获。远程JOB机制不会以任何方式通知父进程远程进程错误或远程进程终止,无论成功与否。在正在运行的代码中捕获错误。

大纲

JOB:pc jobargument,...
J:pc jobargument,...

其中,jobargument是以下参数之一:

本地 JOB:

routine(routine-params):(process-params):timeout
routine(routine-params)[joblocation]:(process-params):timeout
routine(routine-params)|joblocation|:(process-params):timeout

##class(className).methodName(args):(process-params):timeout
..methodName(args):(process-params):timeout
$CLASSMETHOD(className,methodName,args):(process-params):timeout

远程 JOB:

参数

代码 描述
pc 可选-后置条件表达式。
routine 要由JOB创建的进程执行的例程。
routine-params 可选-要传递给例程的参数列表,以逗号分隔。这些参数可以是值、表达式或现有的局部变量名。如果指定,则需要使用括号。例程参数只能传递到本地JOB
className.methodName(args) ..methodName(args) JOB创建的进程要执行的类方法。className不能是$SYSTEM;它可以是%SYSTEM。如果指定…。JOB使用当前类上下文($this类)代替className。以逗号分隔的参数列表是可选的;括号是必需的。不允许省略参数。
process-params 可选-用于设置JOB环境中的各种元素的位置参数的冒号分隔列表。process-params列表包含在圆括号中,括号中的列表前面有冒号。所有过程参数都是可选的;括号是必需的。要指示缺少位置参数,其冒号必须存在,但尾随冒号可能会被省略。只能为本地作业指定process-params参数。
timeout 可选-等待作业进程启动的秒数。小数秒被截断为整数部分。前面的冒号是必需的。只能为本地JOB指定超时参数。如果省略,Caché将无限期等待。
joblocation 可选-用于指定要在其上运行本地或远程JOB的系统和目录的显式或隐式命名空间。隐含的名称空间是目录路径或OpenVMS文件规范,前面有两个脱字符:"^^dir"。用方括号或竖条将接缝块括起来。用方括号或竖条将接缝块括起来。在执行类方法的作业时,不能指定作业块。如果JOBLOCALATION指定远程系统,则不能指定ROUTINE-PARAMSPROCESS-PARAMSTIMEUT。如果joblock ation指定本地作业,则不能指定第一个进程参数(Nspace),因为这将与joblock ation参数冲突。因此,只能指定第二、第三和第四个流程参数,缺少的nspace参数必须用冒号表示。

描述

作业创建称为JOBJOB进程或后台作业的单独进程。创建的进程独立于当前进程在后台运行,通常无需用户交互。JOB进程从调用进程继承其配置环境,但作业命令中明确指定的除外。例如,JOB进程继承父进程的区域设置,而不是系统默认区域设置。

相比之下,使用do命令调用的例程作为当前进程的一部分在前台运行。

JOB可以在本地系统上创建本地进程,也可以调用在另一个系统上创建远程进程。

JOB开始时,Caché可以调用用户编写的JOB^%ZSTART例程。当JOB结束时,Caché可以调用用户编写的JOB^%ZSTOP例程。这些入口点可用于维护JOB活动日志和解决遇到的问题。

注意:仅限OpenVMS:应该使用Cachéjob命令或$ZF(-2)函数从OpenVMS启动Caché进程,而不是使用OpenVMS DCL命令spawn/nowait或管道。为了让Caché正常运行,它需要知道所有Caché进程的正常退出和故障退出。Caché几乎可以检测到所有进程退出。但是,当使用DCL SPOWN/NOWAITPIPE命令启动Caché时,Caché无法检测到可能发生的某些退出条件。如果使用这两种机制中的任何一种启动Caché,则会有一个很小的计时窗口,在此期间父进程的故障可能会导致未检测到的子进程故障。这可能会导致Caché在环境范围内挂起。

参数

pc

可选的后置条件表达式。如果后置条件表达式为TRUE(计算结果为非零数值),则Caché执行JOB。如果后置条件表达式为假(计算结果为零),则Caché不执行该命令。

routine

要启动的进程。它可以采用以下任何形式:

  • label 指定当前例程内的行标签。
  • ^routine 指定驻留在磁盘上的例程。Caché从磁盘加载例程,并从例程内的第一行可执行代码开始执行。
  • label^routine 指定位于磁盘上的命名例程中的行标签。Caché从磁盘加载例程,并从指定的标签开始执行。
  • label+offset^routine 指定距行标签的指定行数的偏移。使用偏移量可能会导致程序维护问题,因此不鼓励使用偏移量。调用CACHESYS%例程时不能指定偏移量。如果尝试这样做,Caché会发出<NOLINE>错误。

如果在过程块内,调用JOB命令将启动过程块范围之外的子进程。因此,它不能解析过程块内的标签引用。因此,对于引用过程内标签的JOB,该过程不能使用过程块。

如果指定的标签不存在,则Caché会发出<NOLINE>错误。如果指定的例程不存在,则Caché会发出<NOROUTINE>错误。

routine-params

值、表达式或现有局部变量名称的逗号分隔列表。括号是必需的。该列表称为实际参数列表。例程必须具有具有相同或更多参数的正式参数列表。如果指定额外的实际参数,则Caché会发出<PARAMETER>错误。请注意,如果调用的例程包含正式参数列表,则即使不传递任何参数,也必须指定括号。 不能从例程参数列表中省略此项。

只能按值传递例程参数,这意味着不能传递数组。这与do命令不同,在do命令中,可以按值和按引用传递参数。此限制的一个特殊后果是不能将数组与JOB命令一起传递,因为它们只能通过引用传递。

不能将对象引用(OREF)传递给JOB进程。 这是因为对调用流程上下文中存在的对象的引用不能在新的JOB流程上下文中引用。尝试传递OREF会导致将空字符串(“”)传递到作业进程。

当例程启动时,Caché计算表达式,并按位置将实际列表中每个参数的值映射到形式列表中的相应变量。如果形式列表中的变量比实际列表中的参数多,则Caché将不定义额外的变量。

例程参数只能传递给本地进程。创建远程JOB时不能指定例程参数。

process-params

用于设置JOB环境中的各种元素的位置参数的冒号分隔列表。前面的冒号和括号是必需的。所有位置参数都是可选的。最多可以为process-params指定七个位置参数。这六个参数是:

(nspace:switch:principal-input:principal-output:priority:os-directory)

由于参数是位置参数,因此必须按显示的顺序指定它们。如果省略指定参数之前的参数,则必须包括冒号作为其占位符。

不能为远程JOB指定进程参数。

下表介绍了参数:

  • nspace 进程的默认命名空间.指定的例程是从此命名空间中提取的。如果省略nspace,则当前默认名称空间是JOB进程的默认名称空间。无效的命名空间会阻止JOB启动。本地JOB不能将joblocation 参数和命名空间都指定为进程参数;必须省略nspace进程参数,保留占位符冒号。
  • switch 由一个或多个下列值之和组成的整数:可以表示零个或多个以下标志的整数位掩码:
    • 1 将符号表传递给派生的JOB
    • 2 请勿使用JOB服务器。
    • 4 使用主体I/O设备($PRINCIPAL)将打开的TCP/IP套接字传递给派生的JOB。(已弃用,请改用16。请参见下面的内容。)
    • 8 将派生JOB的两位数年份的进程特定窗口设置为系统范围的默认滑动窗口定义。否则,派生的JOB将继承发出JOB命令的进程的滑动窗口定义。
    • 16 使用当前I/O设备($IO)将打开的TCP/IP套接字传递给派生的JOB
    • 第128到16384(32的倍数) 一个附加整数值,指定JOB子进程的分区大小(以千字节为单位)。

开关值可以是这些整数的任意组合之和。例如,开关值13(1+4+8)传递符号表(1),传递打开的TCP/IP套接字(4),并建立两位数年份的进程特定窗口,这是系统范围的默认值(8)。

  • principal-input principal主要输入设备。

  • principal-output principal主要输出装置。默认值为主体输入指定的设备。UNIX®:如果没有指定任何一个设备,进程将使用使用JOB命令启动的进程的缺省主设备,即/dev/null。

  • priority UNIX®-指定子进程优先级的整数(受操作系统限制)。如果未指定,子进程将采用父进程的基本优先级加上系统定义的JOB优先级修饰符。可以使用$VIEW函数来确定JOB的当前优先级。Windows的正常优先级为7。Unix®优先级范围为-20到20,正常优先级为0。在UNIX®中,除非以-20到20之间的root.s身份运行,否则进程不能为自己赋予更高的优先级,正常优先级为0。

  • os-directory 文件输入输出的操作系统工作目录。默认情况下,使用从父进程继承的工作目录。在某些系统上可能会忽略此参数。

Switch 4 和 Switch 16

不鼓励使用switch=4,因为这会将传递的TCP设备建立为子JOB的主设备。在这种情况下,子JOB在检测到TCP远程连接断开时可能会暂停,并且不会执行错误捕获。相反,用户应该使用switch=16,然后在子JOB中使用%SYSTEM.INetInfo.TCPName()方法来获取传递的TCP设备名称。在这种情况下,子JOB在检测到TCP远程连接断开时可以继续运行,因为子JOB的主体设备不是传递的TCP设备。

timeout

在超时并中止JOB之前等待JOB进程启动的秒数。前面的冒号是必需的。必须将超时指定为整数值或表达式。如果JOB进程超时,则Caché将中止该进程,并将$test特殊变量设置为0(False)。然后,执行进入调用例程中的下一个命令;不会发出错误消息。如果JOB进程成功,则Caché将$test设置为1(True)。注意,$test也可以由用户设置,或者由锁定、打开或读取超时设置。

只能为本地进程指定超时。

示例

下面的示例在后台启动监视器例程。如果该过程在20秒内没有开始,则Caché将$test设置为false(0)。

/// d ##class(PHA.TEST.Command).TestJOB()
ClassMethod TestJOB()
{
	JOB ^PHA.TEST.Command::20
	WRITE $TEST
}
DHC-APP>d ##class(PHA.TEST.Command).TestJOB()
1

以下示例在名为mainloop的行标签处开始执行监视器例程。

    JOB mainloop^PHA.TEST.Command::20

下面的示例启动Add例程,向其传递变量Num1中的值、值8和表达式a+2产生的值。添加例程必须包含一个形式参数列表,该列表至少包括三个参数。

    JOB ^Add(num1,8,a+2)

下面的示例启动Add例程,该例程有一个正式的参数列表,但不传递任何参数。在这种情况下,Add例程必须包含为其形参分配默认值的代码,因为它们不会从调用例程接收任何值。

    JOB ^Add()

下面的示例创建一个在标签AA处运行当前例程的进程。过程参数将当前符号表传递给例程。它可以使用JOB服务。

    JOB AA:("":1)

下面的示例将例程参数VAL1和字符串"DR."传递给例程^PROG,从当前名称空间中的入口点abc开始。例程需要两个参数。Caché不会将当前符号表传递给该JOB,如果可能,它将使用JOB服务,并使用tta5:作为主要输入和输出设备。

    JOB ABC^PROG(VAL1,"DR."):(:0:"tta5:")

下面的示例显示类方法的JOB,超时为10秒。它们使用tta5:作为主要的输入和输出设备。

下面的示例使用##class语法调用类方法:

    JOB ##class(MyClass).Run():(:0:"tta5:"):10

下面的示例使用$CLASSMETHOD函数调用类方法:

    JOB $CLASSMETHOD(MyClass,Run):(:0:"tta5:"):10

使用JOB $CLASSMETHOD时,$CLASSMETHOD参数必须通过值传递,而不是通过引用传递。

以下示例使用相对点语法(..)。要引用当前对象的方法,请执行以下操作:

    JOB ..CleanUp():(:0:"tta5:"):10

或者简单地说:

    JOB ..CleanUp()::10

注意

Caché分配JOB号和内存分区

启动JOB进程后,Caché会为其分配单独的内存分区,并为其分配唯一的JOB编号(也称为进程ID或PID)。JOB号存储在$JOB特殊变量中。JOB的状态(包括是否由JOB命令启动)存储在$ZJOB特殊变量中。

/// d ##class(PHA.TEST.Command).TestJOB()
ClassMethod TestJOB()
{
	JOB mainloop^PHA.TEST.Command::20
	WRITE $TEST
	w $JOB
}
DHC-APP>d ##class(PHA.TEST.Command).TestJOB()
16388

由于JOB进程具有单独的内存分区,因此它们不与创建它们的进程或彼此共享公共局部变量环境。 启动任务进程时,可以使用参数传递(Routeparams)将值从当前进程传递到任务进程。

如果作业命令失败,通常是因为:

  • 没有空闲分区。
  • 内存不足,无法使用process-params指定的特征创建分区。

JOB进程权限取决于平台

JOB命令创建的进程以Caché服务帐户用户身份运行。这意味着必须确保Caché服务帐户具有访问所有必要资源的显式权限。

衍生的JOB进程可以在与发出JOB命令的进程不同的用户ID下运行。派生的JOB进程的用户ID取决于平台:

  • 在Windows平台上,JOB进程使用 Caché 实例建立的用户ID。
  • 在UNIX®平台上,JOB进程使用发出JOB命令的进程的用户ID。

因此,在派生JOB时,必须确保JOB进程的用户ID具有使用JOB执行期间读取或写入的任何文件的必要权限。

JOB之间的通信

按值传递的参数只能在一个方向上进行,并且只能在JOB启动时进行。为了使进程相互通信,它们必须使用双方同意的全局变量。这类变量通常称为临时全局变量,因为它们的唯一目的是允许进程之间交换信息。

  • 进程可以使用%SYSTEM.Event类方法在JOB之间通信。
  • 通过指定特殊的流程参数,可以将当前流程中的所有局部变量传递给被调用的流程。
  • 进程可以通过IPC(进程间通信)设备(设备号224到255)在作业之间通信,或者在UNIX®操作系统上通过UNIX®管道进行通信。

建立设备所有权

Caché假设调用的例程包括代码(即openuse命令)来处理新进程的设备所有权。默认设备为空设备。除了登录时启动的进程外,Caché不会将默认设备分配给任何进程。

设置JOB优先级

%PRIO实用程序允控制UNIX®JOB进程运行的优先级。可用的选项有正常(使用负载平衡调整CPU使用率)、低和高。具有高优先级的JOB进程在平等的基础上与交互进程竞争CPU资源。

Caché还允许为作业进程建立默认优先级。

可以使用SetBatch()方法将进程设置为在批处理模式下执行。批处理模式进程比非批处理进程具有更低的优先级。

在原始分区中使用JOB命令(UNIX®)

可以通过以下两种方式之一在原始分区中使用JOB命令:

  • 在原始分区中发出JOB命令。
  • 在另一个名称空间中发出JOB命令,并将原始分区指定为JOB命令的nspace进程参数。这里的nspace是一个隐含的名称空间。隐含的名称空间是前面有两个脱字符的目录路径:\“^^dir\”

在原始分区中运行的命令和JOB进程在引用文件名时必须始终指定完整路径名,并且不得使用任何以\“.”\“..\”开头的路径名,因为它们是特殊的UNIX®文件,不存在于原始分区中。违反这两条规则中的任何一条都会导致<directory>错误。

要获取当前命名空间的完整路径名,可以调用NormalizeDirectory()方法,如下例所示:

    WRITE ##class(%Library.File).NormalizeDirectory("")

或者,可以使用UNIX®批处理命令&而不是ObjectScript JOB命令,在原始磁盘分区中以批处理JOB的形式启动例程。

远程JOB

在启动远程JOB之前,必须建立ECP连接并将netjob参数设置为true。这使服务器能够处理来自远程ECP客户端系统的JOB请求。

必须在将接收远程JOB请求的任何系统上配置接收远程JOB请求的功能。

在接收系统上,转到管理门户,选择系统管理、配置、其他设置、高级内存。找到要查看和编辑的netjob。为“true”时,将在此服务器上处理通过ECP传入的远程JOB请求。默认值为“true”。

远程系统上的许可证必须支持足够的用户才能运行远程启动的作业。可以使用%SYSTEM.License类的类方法确定可用Caché许可证的数量.

远程JOB请求的JOB语法

可以使用以下语法将远程JOB从一个 Caché 系统发送到另一个 Caché系统:

    JOB routine[joblocation] 
    JOB routine|joblocation|

这两种形式是等效的;可以使用方括号或竖条来括起联合块参数。远程JOB不能传递例程参数、进程参数或超时。

  • JOBLOCALATION 作业位置的说明。需要使用封闭的方括号或竖条。

Caché采取的操作取决于正在使用的JOB位置语法。

JOB LOBLATION语法 结果
["namespace"] Caché检查此显式名称空间在本地系统或远程系统上是否有其默认数据集。如果默认数据集位于本地系统上,系统将使用指定的参数启动JOB。如果默认数据集位于远程系统上,系统将在命名空间的默认数据集目录中启动远程JOB
["dir","sys"] Caché将此位置转换为隐含的名称空间形式[\“^sys^dir\”]
["^sys^dir"] JOB在指定远程系统上的指定目录中运行。Caché不允许任何例行参数、过程参数或超时规范。
["^^dir"] JOB使用指定的参数在指定的目录(隐含命名空间)中作为当前系统上的本地JOB运行。隐含的名称空间是前面有两个脱字符的目录路径:“^^dir”
["dir",""] Caché 引起 <COMMAND>错误.

使用远程JOB进行全局映射(Windows)

无论请求系统上是否定义了全局映射,Caché都不为远程JOB提供全局映射。
要避免缺少全局映射,请在全局规范中使用指向不在该名称空间中的任何全局变量位置的扩展引用。如果在扩展引用中指定的名称空间没有在指定的系统上定义,则会收到<NAMESPACE>错误。

使用$ZCHILD$ZPARENT特殊变量

  • $ZPARENT包含JOB处理当前进程的进程的PID(进程ID),如果当前进程不是通过JOB命令创建的,则为0。
  • $ZCHILD 包含JOB命令创建的最后一个进程的PID,无论尝试是否成功。

通过使用$ZCHILD,可以通过比较运行JOB命令前后的$ZCHILD值来确定远程JOB的执行状态。如果BEFORE和AFTER值不同,并且AFTER值为非零,则AFTER $ZCHILD值是新创建的远程作业的PID,表示进程已成功创建。如果AFTER值为零,或者AFTER值与BEFE值相同,则不会创建远程作业。

/// d ##class(PHA.TEST.Command).TestJOB()
ClassMethod TestJOB()
{
	w "$ZCHILD:" _ $ZCHILD,!
	w "$ZCHILD:" _ $ZCHILD,!
	JOB mainloop^PHA.TEST.Command::20
	w "$TEST:" _ $TEST,!
	w "$JOB:" _ $JOB,!
	w "$ZPARENT:" _ $ZPARENT,!
	w "$ZCHILD:" _ $ZCHILD,!
	w "$ZCHILD:" _ $ZCHILD,!
}
DHC-APP>d ##class(PHA.TEST.Command).TestJOB()
$ZCHILD:13028
$ZCHILD:13028
$TEST:1
$JOB:6388
$ZPARENT:0
$ZCHILD:8756
$ZCHILD:8756

$ZCHILD只能告诉远程作业已创建;它不会告诉远程作业是否成功运行。确定远程进程是否运行无错误并运行到完成的最佳方法是在正在运行的代码中提供某种类型的日志记录和错误捕获。远程JOB机制不会以任何方式通知父进程远程进程错误或远程进程终止,无论成功与否。在正在运行的代码中捕获错误。

使用JOB服务

作业服务是等待处理作业请求的Caché 进程。附加到JOB服务的JOB进程避免了必须创建新进程的额外开销。每当用户发出将开关参数设置为使用JOB服务(如果可用)的JOB命令时,Caché都会检查是否有JOB服务可用来处理它。如果不是,它将创建一个进程。如果有空闲的JOB服务,则JOB会附加到该JOB服务。任何JOB服务都可以处理它。

JOBJOB服务中运行时暂停时,JOB服务将休眠,直到收到另一个JOB请求。未在JOB服务中运行的JOB进程退出并删除该进程。

JOB服务器环境和JOB进程环境之间存在一些不可避免的差异,这可能是JOB服务器中执行的JOB进程的安全问题。JOB进程具有在Caché级别发出JOB命令的进程的安全属性。

输入和输出设备

一次只能有一个进程拥有一个设备。这意味着在JOB服务中执行的JOB无法向主体I/O设备执行输入或输出,即使可以关闭设备0。

因此,如果希望JOB服务执行输入,则必须指定:

  • 另一种用于它的输入设备
  • 输出设备的空设备(如果不想看到输出)

如果JOB服务中执行的JOB需要从/向主体I/O设备进行任何输入或输出,则如果不遵循这些指导原则,可能会导致JOB服务中执行的JOB挂起。

对无法执行的JOB进行故障排除

如果JOB没有启动,请检查I/O规范。如果Caché无法打开请求的设备,JOB将不会启动。请注意,空设备(UNIX®上的/dev/null)始终可用。

如果JOB开始后立即停止,请确保有足够的交换空间。如果没有足够的交换空间,JOB会收到错误。

如果JOB未启动,请确保在JOB命令中使用了正确的命名空间。可以使用Existes()方法测试是否定义了命名空间:

DHC-APP>WRITE ##class(%SYS.Namespace).Exists("USER"),!
1
 
DHC-APP> WRITE ##class(%SYS.Namespace).Exists("LOSER")
0
DHC-APP> WRITE ##class(%SYS.Namespace).Exists("dhc-app")
1

如果JOB命令仍然不起作用,请尝试以下操作:

  • 使用do命令执行例程。
  • 确保没有超过在Caché中获得许可的进程数量。可以使用%SYSTEM.License类的类方法确定可用Caché许可证的数量。
  • 如果JOB命令中有超时参数,请检查系统速度是否已用完超时时间。

当多个JOB同时执行时,JOB命令可能会在等待例程缓冲区或许可证槽时挂起。可以使用Ctrl-C组合键中断作业命令。

JOB命令完成

JOB进程继续完成,即使创建它的进程在该完成之前注销。

使用TCP设备的JOB命令

可以使用JOB命令来实现TCP并发服务器。TCP并发服务器允许同时为多个客户端提供服务。在此模式下,客户端不必等待服务器完成对其他客户端的服务。相反,每次客户端请求服务器时,它都会为该客户端生成一个单独的子JOB,只要客户端需要,该子JOB就会一直保持打开状态。一旦产生此子JOB(由JOB命令的返回指示),另一个客户端就可以请求服务,并且服务器也将为该客户端创建子JOB

非并发模式和并发模式下的客户端/服务器连接

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rJHyf9Vr-1594689003177)(CE0B946277794EB6958A0535816C90B5)]

并发服务器在开关进程参数位屏蔽位4或位16开启的情况下使用JOB命令,并将输入和输出进程参数传递给产生的进程。

  • 如果指定开关位4,则必须在主体输入和主体输出过程参数中指定TCP设备。必须对主体输入和主体输出使用相同的设备,如下所示:
    JOB child:(:4:tcp:tcp)

然后,派生的进程设置此单个I/O设备,如下所示:

    SET tcp=$IO
  • 如果指定开关位16,则可以为TCP设备、主体输入和主体输出进程参数指定不同的设备,如下所示:
    USE tcp
    JOB child:(:16:input:output)

在JOB命令之前使用TCP将当前设备(而不是主体设备)指定为TCP设备。然后,衍生的进程可以设置这些设备,如下所示:

/// d ##class(PHA.TEST.Command).TestJOB3()
ClassMethod TestJOB3()
{
    SET tcp=##class(%SYSTEM.INetInfo).TCPName()
    SET input=$PRINCIPAL
    SET output=$IO
    WRITE "tcp:"_tcp," input:"_input," output:"_output
}
DHC-APP>d ##class(PHA.TEST.Command).TestJOB3()
tcp: input:|TRM|:|6388 output:|TRM|:|6388

请务必注意,如果设置了4位或16位,JOB命令将把TCP套接字传递给jobbed进程。通过为每个附加特征添加适当的位码,该能力可以与JOB命令的其他特征相结合。例如,当开关包含值为1的位时,传递符号表。要打开并发性并传递符号表,开关的值应为5(4+1)或17(16+1)。

在发出JOB命令之前,TCP设备必须:

  • 开启
  • 监听TCP端口
  • 已接受传入连接

JOB命令之后,派生进程中的设备仍在侦听TCP端口,但不再具有活动连接。应用程序应在发出JOB命令后检查$Za特殊变量,以确保TCP设备状态下的连接位已重置。

衍生的进程从指定的入口点开始,使用指定的设备作为TCP设备、主体输入和主体输出设备。子进程中的TCP设备与父进程中的名称相同。TCP设备有一个连接的套接字。Use命令用于在“M”模式下建立TCP设备,相当于“PSTE”
需要“P”(PAD)选项来用记录终止符填充输出。当设置此模式时,写入!除刷新写入缓冲区外,发送LF(换行符)和WRITE#发送FF(换页符)。

派生进程中的TCP设备处于连接状态:与设备从客户端打开后接收的状态相同。衍生的进程可以通过显式USE语句使用TCP设备。它还可以隐式使用TCP设备。

下面的示例显示了一个非常简单的并发服务器,该服务器在检测到来自客户端的连接时派生子JOB。JOB使用开关值17,由并发服务器位16和符号表位1组成:

/// d ##class(PHA.TEST.Command).TestJOBTCP()
ClassMethod TestJOBTCP()
{
server ;
	SET io = "|TCP|1"
	SET ^serverport = 7001
	OPEN io:(:^serverport:"MA"):20
	IF $TEST = 0 {
		WRITE !,"无法打开服务器端口"
		QUIT 
	}
	ELSE { 
		WRITE !,"服务器端口已打开" 
	}
loop  ;
	USE io READ x   ; 读取以接受
	USE 0  WRITE !,"接受连接"
	USE io 
	JOB child:(:17::)  ; 并发服务器位已启用
	GOTO loop
child ;
	SET io = ##class(%SYSTEM.INetInfo).TCPName()
	SET input = $PRINCIPAL
	SET output = $IO
	USE io:(::"M")  ; 确保使用"M"模式
	WRITE $JOB,!  ; 发送要由客户端读取的TCP设备上的作业ID
	QUIT
client ;
	SET io = "|TCP|2"
	SET host = "127.0.0.1"
	OPEN io:(host:^serverport:"M"):200  ; 连接到服务器
	IF $TEST = 0 {
		WRITE !,"无法打开连接"
		QUIT 
	}
	ELSE { 
		WRITE !,"客户端连接已打开" 
	}
	USE io READ x#3:200  ; 从子JOB读取
	IF x = "" {
		USE 0
		WRITE !,"没有来自子的消息"
		CLOSE io
		QUIT 
	}
	ELSE { 
		USE 0
		WRITE !,"子JOB ",x
		CLOSE io
		QUIT 
	}
}
DHC-APP>d ##class(PHA.TEST.Command).TestJOBTCP()
 
服务器端口已打开
 USE io READ x   ; 读取以接受
        ^
<INTERRUPT>zTestJOBTCP+13^PHA.TEST.Command.1

子进程使用继承的TCP连接将其JOB ID(在本例中假定为3个字符)传递回客户端,之后子进程退出。客户端打开与服务器的连接,并在打开的连接上读取子JOB ID。在此示例中,变量“host”的IPv4值“127.0.0.1”表示到本地主机的环回连接(对应的IPv6环回值为“0:0:0:0:0:0:0:1”或“::1”)。如果将“host”设置为服务器的IP地址或名称,则可以在与服务器不同的计算机上设置客户端。

原则上,子节点和客户端可以进行扩展通信,多个客户端可以同时与各自的服务器子节点进行会话。

指定子进程分区大小

后台JOB的分区大小($ZSTORAGE SIZE)确定如下:

  • 如果JOB服务处于活动状态,则对于任何JOB服务进程,JOB分区大小始终为262144(以千字节为单位)。
  • 如果JOB服务处于非活动状态,则JOB分区大小默认为非后台JOB的默认分区大小(Bbsiz)。这是执行JOB时生效的系统范围默认设置,与从中发出JOB的父进程的分区大小无关。

如果JOB服务已启用,但所有JOB都处于活动状态,且启动了一个新JOB,则该JOB进程将不是JOB服务进程,因此其$ZSTORAGE值将默认为bbsiz。

  • 如果JOB服务处于非活动状态,则可以在JOB语句中指定JOB子进程的分区大小。可以在JOB命令的第二个进程参数中指定JOB进程的分区大小(以千字节为单位)。例如,JOB ^myroutine:(:8192)。指定的值必须是32的倍数,并且范围必须在128到16384之间。它也不能超过默认分区大小;它只能用于指定一个低于默认值的值。

可以选择将分区大小进程参数值与通常放入JOB的第二个进程参数中的其他进程信息结合使用。考虑以下JOB命令: JOB ^myroutine:(:544+1)。该命令指定JOB进程的符号表应该传递给JOB进程,并且JOB进程的分区大小应该是544k。虽然可以指定第二个参数,它将两个值(544和1)传递为545,但544+1更清晰,效果完全相同。

请注意,JOB本身可以使用SET $ZSTORAGE以编程方式设置自己的分区大小。

猜你喜欢

转载自blog.csdn.net/yaoxin521123/article/details/107330565
今日推荐