您可以使用DBMS_PIPE包在连接到相同数据库集群的会话内部或者会话之间传递消息。

下表列出了DBMS_PIPE包允许使用的函数和存储过程。
表 1. DBMS_PIPE函数/存储过程
函数/存储过程 返回类型 描述
CREATE_PIPE(pipename [, maxpipesize ] [, private ]) INTEGER 使用指定的名称显式地创建一个公有或私有管道。
NEXT_ITEM_TYPE INTEGER 返回缓冲区中下一个数据成员的数据类型。
PACK_MESSAGE(item) N/A 将一个数据项放入会话的本地消息缓冲区中。
PURGE(pipename) N/A 从指定的隐式管道中删除未接收到的消息。
RECEIVE_MESSAGE(pipename [, timeout ]) INTEGER 从指定的管道中获取一条消息。
REMOVE_PIPE(pipename) INTEGER 删除一个显式的私有或公有管道。
RESET_BUFFER N/A 清除本地缓冲区的消息。
SEND_MESSAGE(pipename [, timeout ] [, maxpipesize ]) INTEGER 从会话的本地消息缓冲区中将一条消息发送到指定的管道。
UNIQUE_SESSION_NAME VARCHAR2 返回当前会话的一个唯一名称。
UNPACK_MESSAGE(item OUT) N/A 将本地消息缓冲区中消息的数据项复制到程序变量中。
  • 创建管道分为显式创建和隐式创建两种创建方式。
    • 隐式创建:引用一个之前不是由函数CREATE_PIPE创建的管道名称,会隐式地创建一个管道。例如:如果在执行函数SEND_MESSAGE时使用了一个之前不存在的管道名称,那么就用这个名称隐式地创建了一个管道。
      说明 所有隐式创建的管道均为私有管道。
    • 显式创建:将CREATE_PIPE函数的第一个参数指定为新管道的名称,您可以显式地创建一个管道。
  • 您可以将管道分为私有管道和公有管道。
    • 只有创建管道的用户才能访问一个私有管道,超级用户不能访问由其他用户创建的管道。
    • 任何能够访问DBMS_PIPE包的用户均可以访问公有管道。
  • 通过管道发送消息和接受消息。
    • 通过管道发送消息。第一次在本地消息缓冲区创建的单独数据项或者消息文本行,对于当前会话来说是唯一的。您可以使用存储过程PACK_MESSAGE在会话的本地消息缓冲区中创建消息,使用函数SEND_MESSAGE通过管道发送消息。
    • 通过管道接收消息。您首先使用函数RECEIVE_MESSAGE从指定的管道中获得消息,再将消息写到会话的本地缓冲区中。然后使用存储过程UNPACK_MESSAGE将消息的数据成员从消息缓冲区传递给程序变量。如果管道包含多条消息,函数RECEIVE_MESSAGE以先进先出的顺序接收消息。

    存储过程PACK_MESSAGE创建的消息和函数RECEIVE_MESSAGE获取的消息,每一个会话为这两种消息分别保持各自不同的消息缓冲区。可以在相同的会话中创建和接收消息。然而,如果连续执行RECEIVE_MESSAGE函数, 只有最后一次执行RECEIVE_MESSAGE函数所获取的消息会保留在本地消息缓冲区中。

CREATE_PIPE

函数CREATE_PIPE使用指定的名称显式地创建一个公有或私有管道。语法如下:
status INTEGER CREATE_PIPE(pipename VARCHAR2
  [, maxpipesize INTEGER ] [, private BOOLEAN ])
参数
参数名称 参数说明
pipename 管道的名称。
maxpipesize 管道的最大容量,以字节为单位。默认值为8192字节。
private 如果创建公有管道,将此参数值设置为FALSE。如果创建私有管道,将此参数值设定为TRUE。默认值为TRUE。
status 创建管道操作返回的状态代码。0表示成功创建。
示例
  • 创建一个名称为messages的私有管道:
    DECLARE
        v_status        INTEGER;
    BEGIN
        v_status := DBMS_PIPE.CREATE_PIPE('messages');
        DBMS_OUTPUT.PUT_LINE('CREATE_PIPE status: ' || v_status);
    END;
    显示结果如下:
    CREATE_PIPE status: 0
  • 创建一个名称为mailbox的公有管道:
    DECLARE
        v_status        INTEGER;
    BEGIN
        v_status := DBMS_PIPE.CREATE_PIPE('mailbox',8192,FALSE);
        DBMS_OUTPUT.PUT_LINE('CREATE_PIPE status: ' || v_status);
    END;
    显示结果如下:
    CREATE_PIPE status: 0

NEXT_ITEM_TYPE

函数NEXT_ITEM_TYPE返回一个整数型代码,用于标识消息中下一个数据成员的数据类型。其中,消息应已经送到会话的本地缓冲区中。当您使用存储过程UNPACK_MESSAGE从本地消息缓冲区移出每一个数据成员时,函数NEXT_ITEM_TYPE将返回下一个成员的数据类型代码。当在消息中没有成员的时候,将返回代码0。语法如下:
typecode INTEGER NEXT_ITEM_TYPE
参数
参数名称 参数说明
typecode 标识消息中下一个数据项的数据类型。详情请参见表 2
表 2. NEXT_ITEM_TYPE函数返回代码
返回代码 描述
0 没有数据成员。
9 NUMBER
11 VARCHAR2
13 DATE
23 RAW
说明 表中列出的代码类型与Oracle不兼容。Oracle给数据类型分配了一个不同的编号序列。
示例
以下示例显示了一个管道,这个管道填充了一个NUMBER类型的成员,一个VARCHAR2成员、一个DATE成员和一个RAW成员。
DECLARE
    v_number        NUMBER := 123;
    v_varchar       VARCHAR2(20) := 'Character data';
    v_date          DATE := SYSDATE;
    v_raw           RAW(4) := '21222324';
    v_status        INTEGER;
BEGIN
    DBMS_PIPE.PACK_MESSAGE(v_number);
    DBMS_PIPE.PACK_MESSAGE(v_varchar);
    DBMS_PIPE.PACK_MESSAGE(v_date);
    DBMS_PIPE.PACK_MESSAGE(v_raw);
    v_status := DBMS_PIPE.SEND_MESSAGE('datatypes');
    DBMS_OUTPUT.PUT_LINE('SEND_MESSAGE status: ' || v_status);
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('SQLERRM: ' || SQLERRM);
        DBMS_OUTPUT.PUT_LINE('SQLCODE: ' || SQLCODE);
END;
显示结果如下:
SEND_MESSAGE status: 0
使用函数NEXT_ITEM_TYPE显示上个示例中每个成员的类型代码。
DECLARE
    v_number        NUMBER;
    v_varchar       VARCHAR2(20);
    v_date          DATE;
    v_timestamp     TIMESTAMP;
    v_raw           RAW(4);
    v_status        INTEGER;
BEGIN
    v_status := DBMS_PIPE.RECEIVE_MESSAGE('datatypes');
    DBMS_OUTPUT.PUT_LINE('RECEIVE_MESSAGE status: ' || v_status);
    DBMS_OUTPUT.PUT_LINE('----------------------------------');

    v_status := DBMS_PIPE.NEXT_ITEM_TYPE;
    DBMS_OUTPUT.PUT_LINE('NEXT_ITEM_TYPE: ' || v_status);
    DBMS_PIPE.UNPACK_MESSAGE(v_number);
    DBMS_OUTPUT.PUT_LINE('NUMBER Item   : ' || v_number);
    DBMS_OUTPUT.PUT_LINE('----------------------------------');
    v_status := DBMS_PIPE.NEXT_ITEM_TYPE;
    DBMS_OUTPUT.PUT_LINE('NEXT_ITEM_TYPE: ' || v_status);
    DBMS_PIPE.UNPACK_MESSAGE(v_varchar);
    DBMS_OUTPUT.PUT_LINE('VARCHAR2 Item : ' || v_varchar);
    DBMS_OUTPUT.PUT_LINE('----------------------------------');

    v_status := DBMS_PIPE.NEXT_ITEM_TYPE;
    DBMS_OUTPUT.PUT_LINE('NEXT_ITEM_TYPE: ' || v_status);
    DBMS_PIPE.UNPACK_MESSAGE(v_date);
    DBMS_OUTPUT.PUT_LINE('DATE Item     : ' || v_date);
    DBMS_OUTPUT.PUT_LINE('----------------------------------');

    v_status := DBMS_PIPE.NEXT_ITEM_TYPE;
    DBMS_OUTPUT.PUT_LINE('NEXT_ITEM_TYPE: ' || v_status);
    DBMS_PIPE.UNPACK_MESSAGE(v_raw);
    DBMS_OUTPUT.PUT_LINE('RAW Item      : ' || v_raw);
    DBMS_OUTPUT.PUT_LINE('----------------------------------');

    v_status := DBMS_PIPE.NEXT_ITEM_TYPE;
    DBMS_OUTPUT.PUT_LINE('NEXT_ITEM_TYPE: ' || v_status);
    DBMS_OUTPUT.PUT_LINE('---------------------------------');
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('SQLERRM: ' || SQLERRM);
        DBMS_OUTPUT.PUT_LINE('SQLCODE: ' || SQLCODE);
END;
显示结果如下:
RECEIVE_MESSAGE status: 0
----------------------------------
NEXT_ITEM_TYPE: 9
NUMBER Item   : 123
----------------------------------
NEXT_ITEM_TYPE: 11
VARCHAR2 Item : Character data
----------------------------------
NEXT_ITEM_TYPE: 13
DATE Item     : 02-OCT-07 11:11:43
----------------------------------
NEXT_ITEM_TYPE: 23
RAW Item      : 21222324
----------------------------------
NEXT_ITEM_TYPE: 0

PACK_MESSAGE

PACK_MESSAGE函数将一个数据项放入会话的本地消息缓冲区中。在使用函数SEND_MESSAGE前,必须至少执行一次函数PACK_MESSAGE。语法如下:
PACK_MESSAGE(item { DATE | NUMBER | VARCHAR2 | RAW })
参数
参数名称 参数说明
item 用于计算任何可接受数据类型的参数。计算完毕后,会将结果值添加到会话的本地消息缓冲区中。

PURGE

存储过程PURGE从指定的隐式管道中删除未接收到的消息。语法如下:
PURGE(pipename VARCHAR2)
参数
参数名称 参数说明
pipename 管道的名称。
示例
在一个管道上发送两条消息:
DECLARE
    v_status        INTEGER;
BEGIN
    DBMS_PIPE.PACK_MESSAGE('Message #1');
    v_status := DBMS_PIPE.SEND_MESSAGE('pipe');
    DBMS_OUTPUT.PUT_LINE('SEND_MESSAGE status: ' || v_status);

    DBMS_PIPE.PACK_MESSAGE('Message #2');
    v_status := DBMS_PIPE.SEND_MESSAGE('pipe');
    DBMS_OUTPUT.PUT_LINE('SEND_MESSAGE status: ' || v_status);
END;
显示结果如下:
SEND_MESSAGE status: 0
SEND_MESSAGE status: 0
接收第一条消息,然后打开:
DECLARE
    v_item          VARCHAR2(80);
    v_status        INTEGER;
BEGIN
    v_status := DBMS_PIPE.RECEIVE_MESSAGE('pipe',1);
    DBMS_OUTPUT.PUT_LINE('RECEIVE_MESSAGE status: ' || v_status);
    DBMS_PIPE.UNPACK_MESSAGE(v_item);
    DBMS_OUTPUT.PUT_LINE('Item: ' || v_item);
END;
显示结果如下:
RECEIVE_MESSAGE status: 0
Item: Message #1
删除管道中的消息:
EXEC DBMS_PIPE.PURGE('pipe');
当您尝试取出下一条消息时,函数RECEIVE_MESSAGE会返回状态代码。
DECLARE
    v_item          VARCHAR2(80);
    v_status        INTEGER;
BEGIN
    v_status := DBMS_PIPE.RECEIVE_MESSAGE('pipe',1);
    DBMS_OUTPUT.PUT_LINE('RECEIVE_MESSAGE status: ' || v_status);
END;
显示结果如下,1表示超时,因为这时在管道中没有消息。
RECEIVE_MESSAGE status: 1

RECEIVE_MESSAGE

函数RECEIVE_MESSAGE从指定的管道中获取一条消息。语法如下:
status INTEGER RECEIVE_MESSAGE(pipename VARCHAR2
  [, timeout INTEGER ])
参数
参数名称 参数说明
pipename 管道的名称。
timeout 等待时间。单位:秒。默认为86400000s(表示1000天)。
表 3. RECEIVE_MESSAGE函数返回的状态代码
状态代码 描述
0 成功获取消息。
1 超时。
2 对于缓冲区来说管道中的消息太大。
3 中断。
ORA-23322 您没有权限获取管道中的消息。

REMOVE_PIPE

函数REMOVE_PIPE删除一个显式的私有或公有管道。语法如下:
status INTEGER REMOVE_PIPE(pipename VARCHAR2)
参数
参数名称 参数说明
pipename 管道的名称。
status 函数返回的状态代码。即使命名的管道不存在,也会返回状态代码0。
示例
在管道中发送两条消息:
DECLARE
    v_status        INTEGER;
BEGIN
    v_status := DBMS_PIPE.CREATE_PIPE('pipe');
    DBMS_OUTPUT.PUT_LINE('CREATE_PIPE status : ' || v_status);

    DBMS_PIPE.PACK_MESSAGE('Message #1');
    v_status := DBMS_PIPE.SEND_MESSAGE('pipe');
    DBMS_OUTPUT.PUT_LINE('SEND_MESSAGE status: ' || v_status);

    DBMS_PIPE.PACK_MESSAGE('Message #2');
    v_status := DBMS_PIPE.SEND_MESSAGE('pipe');
    DBMS_OUTPUT.PUT_LINE('SEND_MESSAGE status: ' || v_status);
END;
显示结果如下:
CREATE_PIPE status : 0
SEND_MESSAGE status: 0
SEND_MESSAGE status: 0
接收第一条消息,然后打开:
DECLARE
    v_item          VARCHAR2(80);
    v_status        INTEGER;
BEGIN
    v_status := DBMS_PIPE.RECEIVE_MESSAGE('pipe',1);
    DBMS_OUTPUT.PUT_LINE('RECEIVE_MESSAGE status: ' || v_status);
    DBMS_PIPE.UNPACK_MESSAGE(v_item);
    DBMS_OUTPUT.PUT_LINE('Item: ' || v_item);
END;
显示结果如下:
RECEIVE_MESSAGE status: 0
Item: Message #1
删除管道:
SELECT DBMS_PIPE.REMOVE_PIPE('pipe') FROM DUAL;
显示结果如下:
remove_pipe
-------------
           0
(1 row)
当您尝试取回下一条消息,函数RECEIVE_MESSAGE 将返回状态代码1,表示超时,这是因为已经把管道删除了。
DECLARE
    v_item          VARCHAR2(80);
    v_status        INTEGER;
BEGIN
    v_status := DBMS_PIPE.RECEIVE_MESSAGE('pipe',1);
    DBMS_OUTPUT.PUT_LINE('RECEIVE_MESSAGE status: ' || v_status);
END;
显示结果如下:
RECEIVE_MESSAGE status: 1

RESET_BUFFER

存储过程RESET_BUFFER将会话的本地消息缓冲区中的指针重新设置到缓冲区的开始位置。这样在随后调用PACK_MESSAGE时,将覆盖在调用存储过程RESET_BUFFER前在消息缓冲区中已存在的数据项。语法如下:
RESET_BUFFER
示例
将发给John的消息写到本地消息缓冲区中。调用存储过程RESET_BUFFER后,这条信息被发给Bob的消息覆盖了。
DECLARE
    v_status        INTEGER;
BEGIN
    DBMS_PIPE.PACK_MESSAGE('Hi, John');
    DBMS_PIPE.PACK_MESSAGE('Can you attend a meeting at 3:00, today?');
    DBMS_PIPE.PACK_MESSAGE('If not, is tomorrow at 8:30 ok with you?');
    DBMS_PIPE.RESET_BUFFER;
    DBMS_PIPE.PACK_MESSAGE('Hi, Bob');
    DBMS_PIPE.PACK_MESSAGE('Can you attend a meeting at 9:30, tomorrow?');
    v_status := DBMS_PIPE.SEND_MESSAGE('pipe');
    DBMS_OUTPUT.PUT_LINE('SEND_MESSAGE status: ' || v_status);
END; 
显示结果如下:
SEND_MESSAGE status: 0   
在接收到的消息中出现了发给Bob的消息。
DECLARE
    v_item          VARCHAR2(80);
    v_status        INTEGER;
BEGIN
    v_status := DBMS_PIPE.RECEIVE_MESSAGE('pipe',1);
    DBMS_OUTPUT.PUT_LINE('RECEIVE_MESSAGE status: ' || v_status);
    DBMS_PIPE.UNPACK_MESSAGE(v_item);
    DBMS_OUTPUT.PUT_LINE('Item: ' || v_item);
    DBMS_PIPE.UNPACK_MESSAGE(v_item);
    DBMS_OUTPUT.PUT_LINE('Item: ' || v_item);
END;
显示结果如下:
RECEIVE_MESSAGE status: 0
Item: Hi, Bob
Item: Can you attend a meeting at 9:30, tomorrow?

SEND_MESSAGE

函数SEND_MESSAGE从会话的本地消息缓冲区中将一条消息发送到指定的管道。语法如下:
status SEND_MESSAGE(pipename VARCHAR2 [, timeout INTEGER ]
  [, maxpipesize INTEGER ])
参数
参数名称 参数说明
pipename 管道的名称。
timeout 等待时间,以秒为单位。 默认值为86400000s(表示1000天)。
maxpipesize 管道的最大容量,以字节为单位。默认值为8192字节。
表 4. SEND_MESSAGE函数返回的状态代码
状态代码 描述
0 发送消息成功。
1 超时。
3 中断。
ORA-23322 权限不足。
说明 如果存在同名管道且该管道是由不同用户创建的,则Oracle会发出错误信号ORA-23322,指示命名冲突。

UNIQUE_SESSION_NAME

函数UNIQUE_SESSION_NAME返回当前会话的一个唯一名称。语法如下:
name VARCHAR2 UNIQUE_SESSION_NAME
参数
参数名称 参数说明
name 会话的唯一名称。
示例
DECLARE
    v_session       VARCHAR2(30);
BEGIN
    v_session := DBMS_PIPE.UNIQUE_SESSION_NAME;
    DBMS_OUTPUT.PUT_LINE('Session Name: ' || v_session);
END;
显示结果如下:
Session Name: PG$PIPE$5$2752

UNPACK_MESSAGE

存储过程UNPACK_MESSAGE将本地消息缓冲区中消息的数据项复制到程序变量中。使用UNPACK_MESSAGE前,必须先使用函数RECEIVE_MESSAGE将消息放到本地消息缓冲区中。语法如下:
UNPACK_MESSAGE(item OUT { DATE | NUMBER | VARCHAR2 | RAW })
参数
参数名称 参数说明
item 从本地缓冲区中接收数据项的变量,这个变量必须和数据项的类型相兼容。

综合性示例

在下面的示例中,将一个管道作为一个“邮箱”。使用存储过程创建邮箱,然后在邮箱中增加一条含有多个数据项的信息(最多有3个数据项)。最后显示mailbox包中的全部内容。
CREATE OR REPLACE PACKAGE mailbox
IS
    PROCEDURE create_mailbox;
    PROCEDURE add_message (
        p_mailbox   VARCHAR2,
        p_item_1    VARCHAR2,
        p_item_2    VARCHAR2 DEFAULT 'END',
        p_item_3    VARCHAR2 DEFAULT 'END'
    );
    PROCEDURE empty_mailbox (
        p_mailbox   VARCHAR2,
        p_waittime  INTEGER DEFAULT 10
    );
END mailbox;

CREATE OR REPLACE PACKAGE BODY mailbox
IS
    PROCEDURE create_mailbox
    IS
        v_mailbox   VARCHAR2(30);
        v_status    INTEGER;
    BEGIN
        v_mailbox := DBMS_PIPE.UNIQUE_SESSION_NAME;
        v_status := DBMS_PIPE.CREATE_PIPE(v_mailbox,1000,FALSE);
        IF v_status = 0 THEN
            DBMS_OUTPUT.PUT_LINE('Created mailbox: ' || v_mailbox);
        ELSE
            DBMS_OUTPUT.PUT_LINE('CREATE_PIPE failed - status: ' ||
                v_status);
        END IF;
    END create_mailbox;

    PROCEDURE add_message (
        p_mailbox   VARCHAR2,
        p_item_1    VARCHAR2,
        p_item_2    VARCHAR2 DEFAULT 'END',
        p_item_3    VARCHAR2 DEFAULT 'END'
    )
    IS
        v_item_cnt  INTEGER := 0;
        v_status    INTEGER;
    BEGIN
        DBMS_PIPE.PACK_MESSAGE(p_item_1);
        v_item_cnt := 1;
        IF p_item_2 != 'END' THEN
            DBMS_PIPE.PACK_MESSAGE(p_item_2);
            v_item_cnt := v_item_cnt + 1;
        END IF;
        IF p_item_3 != 'END' THEN
            DBMS_PIPE.PACK_MESSAGE(p_item_3);
            v_item_cnt := v_item_cnt + 1;
        END IF;
        v_status := DBMS_PIPE.SEND_MESSAGE(p_mailbox);
        IF v_status = 0 THEN
            DBMS_OUTPUT.PUT_LINE('Added message with ' || v_item_cnt ||
                ' item(s) to mailbox ' || p_mailbox);
        ELSE
            DBMS_OUTPUT.PUT_LINE('SEND_MESSAGE in add_message failed - ' ||
                'status: ' || v_status);
        END IF;
    END add_message;

    PROCEDURE empty_mailbox (
        p_mailbox   VARCHAR2,
        p_waittime  INTEGER DEFAULT 10
    )
    IS
        v_msgno     INTEGER DEFAULT 0;
        v_itemno    INTEGER DEFAULT 0;
        v_item      VARCHAR2(100);
        v_status    INTEGER;
    BEGIN
        v_status := DBMS_PIPE.RECEIVE_MESSAGE(p_mailbox,p_waittime);
        WHILE v_status = 0 LOOP
            v_msgno := v_msgno + 1;
            DBMS_OUTPUT.PUT_LINE('****** Start message #' || v_msgno ||
                ' ******');
            BEGIN
                LOOP
                    v_status := DBMS_PIPE.NEXT_ITEM_TYPE;
                    EXIT WHEN v_status = 0;
                    DBMS_PIPE.UNPACK_MESSAGE(v_item);
                    v_itemno := v_itemno + 1;
                    DBMS_OUTPUT.PUT_LINE('Item #' || v_itemno || ': ' ||
                        v_item);
                END LOOP;
                DBMS_OUTPUT.PUT_LINE('******* End message #' || v_msgno ||
                    ' *******');
                DBMS_OUTPUT.PUT_LINE('*');
                v_itemno := 0;
                v_status := DBMS_PIPE.RECEIVE_MESSAGE(p_mailbox,1);
            END;
        END LOOP;
        DBMS_OUTPUT.PUT_LINE('Number of messages received: ' || v_msgno);
        v_status := DBMS_PIPE.REMOVE_PIPE(p_mailbox);
        IF v_status = 0 THEN
            DBMS_OUTPUT.PUT_LINE('Deleted mailbox ' || p_mailbox);
        ELSE
            DBMS_OUTPUT.PUT_LINE('Could not delete mailbox - status: '
                || v_status);
        END IF;
    END empty_mailbox;
END mailbox;
第一个存储过程创建了一个公有管道,这个管道的名称是由函数UNIQUE_SESSION_NAME生成。
EXEC mailbox.create_mailbox;
显示结果如下:
Created mailbox: PG$PIPE$13$3940
在同一数据库中使用邮箱名称,任何访问mailbox包和DBMS_PIPE的用户都能够添加消息。
EXEC mailbox.add_message('PG$PIPE$13$3940','Hi, John','Can you attend a meeting at 3:00, today?','-- Mary');
EXEC mailbox.add_message('PG$PIPE$13$3940','Don''t forget to submit your report','Thanks,','-- Joe');
显示结果如下:
Added message with 3 item(s) to mailbox PG$PIPE$13$3940Added message with 3 item(s) to mailbox PG$PIPE$13$3940
清空mailbox包中的内容:
EXEC mailbox.empty_mailbox('PG$PIPE$13$3940');
显示结果如下:
****** Start message #1 ******
Item #1: Hi, John
Item #2: Can you attend a meeting at 3:00, today?
Item #3: -- Mary
******* End message #1 *******
*
****** Start message #2 ******
Item #1: Don't forget to submit your report
Item #2: Thanks,
Item #3: Joe
******* End message #2 *******
*
Number of messages received: 2
Deleted mailbox PG$PIPE$13$3940