# DBE_TASK
#### 接口介绍
高级功能包DBE_TASK支持的接口请参见[表1]。
 表1DBE_TASK 
| 接口名称                                                                                                                                                                       | 描述                                                                                |
|:---|:---|
| [DBE_TASK.SUBMIT](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/gaussdb-08-0491.html#ZH-CN_TOPIC_0000002764309058__zh-cn_topic_0059779362_li1990614111714)  | 提交一个定时任务。作业号由系统自动生成。                                                              |
| [DBE_TASK.JOB_SUBMIT]                                                                                                                              | 功能等同于[DBE_TASK.SUBMIT]，但提供语法兼容参数。 |
| [DBE_TASK.ID_SUBMIT](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/gaussdb-08-0491.html#ZH-CN_TOPIC_0000002764309058__zh-cn_topic_0059779362_li49938144177)   | 提交一个定时任务。作业号由用户指定。                                                             |
| [DBE_TASK.CANCEL](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/gaussdb-08-0491.html#ZH-CN_TOPIC_0000002764309058__zh-cn_topic_0059779362_li13993101401717) | 通过作业号来删除定时任务。                                                                   |
| [DBE_TASK.RUN]                                                                                                                                    | 运行定时任务。                                                                                                 |
| [DBE_TASK.FINISH](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/gaussdb-08-0491.html#ZH-CN_TOPIC_0000002764309058__zh-cn_topic_0059779362_li699414143176)      | 禁用或者启用定时任务。                                                                      |
| [DBE_TASK.UPDATE](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/gaussdb-08-0491.html#ZH-CN_TOPIC_0000002764309058__zh-cn_topic_0059779362_li199617145172)  | 修改定时任务的属性，包括任务内容、下次执行时间和执行间隔。                                                   |
| [DBE_TASK.CHANGE]                                                                                                                                 | 功能等同于[DBE_TASK.UPDATE]，但提供语法兼容参数。 |
| [DBE_TASK.CONTENT](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/gaussdb-08-0491.html#ZH-CN_TOPIC_0000002764309058__zh-cn_topic_0059779362_li11999214161717) | 修改定时任务的内容属性。                                                                      |
| [DBE_TASK.NEXT_TIME](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/gaussdb-08-0491.html#ZH-CN_TOPIC_0000002764309058__zh-cn_topic_0059779362_li5112157173)  | 修改定时任务的下次执行时间属性。                                                                 |
| [DBE_TASK.INTERVAL](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/gaussdb-08-0491.html#ZH-CN_TOPIC_0000002764309058__zh-cn_topic_0059779362_li113115111712)  | 修改定时任务的执行间隔属性。                                                                   |
   
![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
- DBE_TASK任务调度在分布式环境下不保证任务执行态信息的高可靠性。仅在任务提交的节点上可以查询到任务调度的执行态信息，其他节点查询到的信息可能尚未同步。
- GaussDB数据库提供了高可用、高可靠性、并且更灵活的调度系统：DBE_SCHEDULER接口，推荐分布式环境下使用该接口。
 
- DBE_TASK.SUBMIT
  DBE_TASK.SUBMIT提交一个系统提供的定时任务。
  DBE_TASK.SUBMIT原型为：
  ```
  DBE_TASK.SUBMIT(
  what          IN   TEXT,
  next_time     IN   TIMESTAMP DEFAULT sysdate,
  interval_time IN   TEXT  DEFAULT 'null',
  id            OUT  INTEGER
  )RETURN INTEGER;
  ```
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  - 当创建一个定时任务（DBE_TASK）时，系统默认将当前数据库和用户名与当前创建的定时任务（DBE_TASK）绑定起来。
  
  - 该接口函数可以通过CALL或SELECT语句进行调用，如果通过CALL语句调用，需要填写出参，如果通过SELECT语句调用，可以不填写出参。如果在存储过程中则需要用通过PERFORM语句调用该接口函数。
  
  - 如果提交的SQL语句任务使用到非PUBLIC的schema，则需要指定表或者函数的schema，或者在执行SQL语句前先执行SET current_schema = xxx;语句。
   
  表2DBE_TASK.SUBMIT接口参数说明 
  | 参数           | 类型         | 入参/出参  | 是否可以为空 | 描述                                                                                                                                    |
  |:---|:---|:---|:---|:---|
  | what        | text     | IN    | 否      | 要执行的SQL语句。支持一个或多个DDL（不支持DB相关操作）、DML、匿名块、调用存储过程的语句，或这四种类型混合的场景。                                                                        |
  | next_time   | timestamp | IN   | 否      | 下次作业运行时间。默认值为当前系统时间（sysdate）。如果是过去时间，在提交作业时表示立即执行。                                                                                    |
  | interval_time | text       | IN   | 是       | 用来计算下次作业运行时间的时间表达式，可以是interval表达式，也可以是sysdate加上一个numeric值（例如：sysdate+1.0/24）。如果该值为空或字符串"null"，表示只执行一次。执行后，JOB状态STATUS变成'd' ，表示不再执行。 |
  | id           | integer  | OUT | 否      | 作业号。范围为1～3000000。当使用SELECT语句调用时，该参数不能添加；当使用CALL语句调用时，该参数必须添加。                                                                        |
     
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  当在TASK的参数what中创建用户时，日志会记录密码的明文。因此不建议在TASK任务中创建用户。该接口创建的任务不能保证高可用，建议使用[PKG_SERVICE.SUBMIT_ON_NODES](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/gaussdb-08-0468.html#ZH-CN_TOPIC_0000002793707581__li12446850163911)创建任务，并将JOB执行节点指定为CCN。
  示例：
  ```
  gaussdb=# SELECT DBE_TASK.SUBMIT('call pro_xxx();', to_date('20180101','yyyymmdd'),'sysdate+1');
   submit
  --------
    31031
  (1 row)
  gaussdb=# SELECT DBE_TASK.SUBMIT('call pro_xxx();', to_date('20180101','yyyymmdd'),'sysdate+1.0/24');
   submit
  --------
      512
  (1 row)
  gaussdb=# DECLARE
  gaussdb-#     jobid int;
  gaussdb-# BEGIN
  gaussdb$#     PERFORM DBE_TASK.SUBMIT('call pro_xxx();', sysdate, 'interval ''5 minute''', jobid);
  gaussdb$# END;
  gaussdb$# /
  ANONYMOUS BLOCK EXECUTE
  ```
  

- DBE_TASK.JOB_SUBMIT
  DBE_TASK.JOB_SUBMIT提交一个系统提供的定时任务。并提供了额外的兼容性参数。
  DBE_TASK.JOB_SUBMIT原型为：
  ```
  DBE_TASK.JOB_SUBMIT(
  job           OUT  INTEGER,
  what          IN   TEXT,
  next_date     IN   TIMESTAMP  DEFAULT sysdate,
  job_interval  IN   TEXT       DEFAULT 'null',
  no_parse      IN   BOOLEAN    DEFAULT false,
  instance      IN   INTEGER    DEFAULT 0,
  force         IN   BOOLEAN    DEFAULT false
  )RETURN INTEGER;
  ```
  表3DBE_TASK.JOB_SUBMIT接口参数说明 
  | 参数         | 类型        | 入参/出参 | 是否可以为空 | 描述                                                                                                                                 |
  |:---|:---|:---|:---|:---|
  | job        | integer    | OUT  | 否      | 作业号。范围为1～3000000。当使用SELECT语句调用DBE_TASK.JOB_SUBMIT时，该参数可以省略。                                                                         |
  | what          | text    | IN    | 否      | 要执行的SQL语句。支持一个或多个DDL（不支持DB相关操作）、DML、匿名块、"调用存储过程的语句，或这四种类型混合的场景。                                                                   |
  | next_date | timestamp | IN    | 是       | 下次作业运行时间。默认值为当前系统时间（sysdate）。如果是过去时间，在提交作业时表示立即执行。                                                                                 |
  | job_interval  | text       | IN  | 是       | 用来计算下次作业运行时间的时间表达式，可以是interval表达式，也可以是sysdate加上一个numeric值（例如：sysdate+1.0/24）。如果该值为空或字符串"null"，表示只执行一次。执行后，JOB状态STATUS变成'd'，表示不再执行。 |
  | no_parse     | boolean    | IN    | 是      | 默认值false，仅用于语法上的兼容。                                                                                                                |
  | instance    | integer    | IN    | 是      | 默认值0，仅用于语法上的兼容。                                                                                                                      |
  | force       | boolean    | IN  | 是      | 默认值false，仅用于语法上的兼容。                                                                                                                |
     
  示例：
  ```
  gaussdb=# DECLARE
  gaussdb-#     id integer;
  gaussdb-# BEGIN
  gaussdb$#     id = DBE_TASK.JOB_SUBMIT(
  gaussdb$#         what => 'insert into t1 values (1, 2)',
  gaussdb$#         job_interval => 'sysdate + 1' --daily
  gaussdb$#     );
  gaussdb$# END;
  gaussdb$# /
  ANONYMOUS BLOCK EXECUTE
  ```
  
- DBE_TASK.ID_SUBMIT
  DBE_TASK.ID_SUBMIT与DBE_TASK.SUBMIT语法功能相同，DBE_TASK.ID_SUBMIT的所有参数都是入参，第一个参数表示指定的作业号，DBE_TASK.SUBMIT最后一个参数是出参，表示系统自动生成的作业号。
  DBE_TASK.ID_SUBMIT原型为：
  ```
  DBE_TASK.ID_SUBMIT(
  id            IN   BIGINT,
  what          IN   TEXT,
  next_time     IN   TIMESTAMP DEFAULT sysdate,
  interval_time IN   TEXT  DEFAULT 'null');
  ```
  示例：
  ```
  gaussdb=# CALL dbe_task.id_submit(101, 'insert_msg_statistic1;', sysdate, 'sysdate+3.0/24');
   id_submit
  -----------
  (1 row)
  ```
  
- DBE_TASK.CANCEL
  DBE_TASK.CANCEL删除指定的定时任务。
  DBE_TASK.CANCEL原型为：
  ```
  CANCEL(id  IN  INTEGER);
  ```
  表4DBE_TASK.CANCEL接口参数说明 
  | 参数   | 类型     | 入参/出参 | 是否可以为空 | 描述       |
  |:---|:---|:---|:---|:---|
  | id | integer | IN    | 否      | 指定的作业号。 |
     
  示例：
  ```
  gaussdb=# CALL dbe_task.cancel(101);
   cancel
  --------
  (1 row)
  ```
  
- DBE_TASK.RUN
  DBE_TASK.RUN运行定时任务。
  DBE_TASK.RUN原型为：
  ```
  DBE_TASK.RUN(
  job          IN   BIGINT,
  force        IN   BOOLEAN DEFAULT FALSE);
  ```
  表5DBE_TASK.RUN接口参数说明 
  | 参数      | 类型    | 入参/出参 | 是否可以为空 | 描述       |
  |:---|:---|:---|:---|:---|
  | job    | bigint | IN    | 否      | 指定的作业号。  |
  | force | boolean | IN    | 是    | 仅用于语法上的兼容。 |
     
  示例：
  ```
  gaussdb=# BEGIN
  gaussdb$#     DBE_TASK.ID_SUBMIT(12345, 'insert_msg_statistic1;', sysdate, 'sysdate+3.0/24');
  gaussdb$#     DBE_TASK.RUN(12345);
  gaussdb$# END;
  gaussdb$# /
  ANONYMOUS BLOCK EXECUTE
  ```
  
- DBE_TASK.FINISH
  DBE_TASK.FINISH禁用或者启用定时任务。
  DBE_TASK.FINISH原型为：
  ```
  DBE_TASK.FINISH(
  id           IN   INTEGER,
  broken       IN   BOOLEAN,
  next_time    IN   TIMESTAMP  DEFAULT  sysdate);
  ```
  表6DBE_TASK.FINISH接口参数说明 
  | 参数        | 类型       | 入参/出参 | 是否可以为空 | 描述                                                                                                                                                                                                                                                                                                                                                                             |
  |:---|:---|:---|:---|:---|
  | id        | integer | IN   | 否      | 指定的作业号。                                                                                                                                                                                                                                                                                                                                                                         |
  | broken    | boolean | IN    | 否      | 状态标志位。true代表禁用，false代表启用。设置具体true或false值以更新当前JOB；如果值为空，则不改变原有JOB的状态。                                                                                                                                                                                                                                                                                                          |
  | next_time | timestamp  | IN     | 是      | 下次运行时间，默认为当前系统时间。该参数可以省略，为默认值。 - 如果参数broken状态为true，则更新该参数为'4000-1-1'。  - 如果参数broken状态为false，参数next_time不为空值时，更新指定job的next_time值；next_time为空值时，不更新next_time值。   |
     
  示例：
  ```
  gaussdb=# CALL dbe_task.id_submit(101, 'insert_msg_statistic1;', sysdate, 'sysdate+3.0/24');
   id_submit
  -----------
  (1 row)
  gaussdb=# CALL dbe_task.finish(101, true);
   finish
  --------
  (1 row)
  gaussdb=# CALL dbe_task.finish(101, false, sysdate);
   finish
  --------
  (1 row)
  ```
  
- DBE_TASK.UPDATE
  DBE_TASK.UPDATE修改定时任务的属性，包括任务内容、下次执行时间和执行间隔。
  DBE_TASK.UPDATE原型为：
  ```
  dbe_task.UPDATE(
  id              IN     INTEGER,
  content         IN    TEXT,
  next_time       IN     TIMESTAMP,
  interval_time   IN  TEXT);
  ```
  表7DBE_TASK.UPDATE接口参数说明 
  | 参数              | 类型           | 入参/出参 | 是否可以为空 | 描述                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
  |:---|:---|:---|:---|:---|
  | id             | integer     | IN    | 否      | 指定的作业号。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
  | content        | text        | IN      | 是      | 执行的存储过程名或者SQL语句块。如果该参数为空值，则不更新指定JOB的content值，否则更新指定JOB的content值。                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
  | next_time        | timestamp | IN    | 是      | 下次运行时间。如果该参数为空值，则不更新指定JOB的next_time值，否则更新指定JOB的next_time值。                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
  | interval_time | text       | IN      | 是      | 用来计算下次作业运行时间的时间表达式。 - 如果该参数为空值，则不更新指定JOB的interval_time值。  - 如果该参数不为空值，会校验interval_time是否为有效的时间类型或interval类型，若是则更新指定JOB的interval_time值。  - 如果为字符串"null"，表示只执行一次。执行后，JOB状态STATUS变成'd' ，表示不再执行。   |
     
  示例：
  ```
  gaussdb=# CALL dbe_task.update(101, 'call userproc();', sysdate, 'sysdate + 1.0/1440');
   update
  --------
  (1 row)
  gaussdb=# CALL dbe_task.update(101, 'insert into tbl_a values(sysdate);', sysdate, 'sysdate + 1.0/1440');
   update
  --------
  (1 row)
  ```
  
- DBE_TASK.CHANGE
  DBE_TASK.CHANGE修改定时任务的属性，包括任务内容、下次执行时间和执行间隔。
  DBE_TASK.CHANGE原型为：
  ```
  DBE_TASK.CHANGE(
  job             IN    INTEGER,
  what            IN    TEXT       DEFAULT NULL,
  next_date       IN    TIMESTAMP  DEFAULT NULL,
  job_interval    IN    TEXT       DEFAULT NULL,
  instance        IN    INTEGER    DEFAULT NULL,
  force           IN    BOOLEAN    DEFAULT false);
  ```
  表8DBE_TASK.CHANGE接口参数说明 
  | 参数         | 类型      | 入参/出参 | 是否可以为空 | 描述                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
  |:---|:---|:---|:---|:---|
  | job          | integer    | IN      | 否       | 指定的作业号。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
  | what       | text     | IN    | 是         | 执行的存储过程名或者SQL语句块。如果该参数为空值，则不更新指定JOB的what值，否则更新指定JOB的what值。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
  | next_date  | timestamp | IN     | 是        | 下次运行时间。如果该参数为空值，则不更新指定JOB的next_time值，否则更新指定JOB的next_date值。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
  | job_interval | text      | IN     | 是         | 用来计算下次作业运行时间的时间表达式。 - 如果该参数为空值，则不更新指定JOB的job_interval值。  - 如果该参数不为空值，会校验job_interval是否为有效的时间类型或interval类型，若是则更新指定JOB的job_interval值。  - 如果为字符串"null"，表示只执行一次。执行后，JOB状态STATUS变成'd' ，表示不再执行。   |
  | instance   | integer  | IN   | 是      | 仅用于语法上的兼容。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
  | force       | boolean   | IN    | 否     | 仅用于语法上的兼容。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
     
  示例：
  ```
  gaussdb=# BEGIN
  gaussdb$#     DBE_TASK.CHANGE(
  gaussdb$#         job => 101,
  gaussdb$#         what => 'insert into t2 values (2);'
  gaussdb$#     );
  gaussdb$# END;
  gaussdb$# /
  ANONYMOUS BLOCK EXECUTE
  ```
  
- DBE_TASK.CONTENT
  DBE_TASK.CONTENT修改定时任务的任务内容属性。
  DBE_TASK.CONTENT原型为：
  ```
  DBE_TASK.CONTENT(
  id           IN     INTEGER,
  content      IN TEXT);
  ```
  表9DBE_TASK.CONTENT接口参数说明 
  | 参数   | 类型     | 入参/出参 | 是否可以为空 | 描述                  |
  |:---|:---|:---|:---|:---|
  | id    | integer | IN     | 否      | 指定的作业号。                |
  | content | text    | IN     | 否      | 执行的存储过程调用、SQL语句块或程序块。 |
     
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  - 当content参数是一个或多个可以执行成功的SQL语句、程序块或调用存储过程时，该接口函数才能被执行成功，否则会执行失败。
  
  - 若content参数为一个简单的INSERT、UPDATE等语句，需要在表前加模式名。
   
  示例：
  ```
  gaussdb=# CALL dbe_task.content(101, 'call userproc();');
   content
  ---------
  (1 row)
  gaussdb=# CALL dbe_task.content(101, 'insert into tbl_a values(sysdate);');
   content
  ---------
  (1 row)
  ```
  
- DBE_TASK.NEXT_TIME
  DBE_TASK.NEXT_TIME修改定时任务的下次执行时间属性。
  DBE_TASK.NEXT_TIME原型为：
  ```
  DBE_TASK.NEXT_TIME(
  id          IN    BIGINT,
  next_time   IN   TEXT);
  ```
  表10DBE_TASK.NEXT_TIME接口参数说明 
  | 参数          | 类型      | 入参/出参 | 是否可以为空 | 描述     |
  |:---|:---|:---|:---|:---|
  | id         | bigint | IN   | 否      | 指定的作业号。 |
  | next_time | text   | IN    | 否      | 下次运行时间。   |
     
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  如果输入的next_time的值小于当前日期值，该JOB会立即执行一次。
  示例：
  ```
  gaussdb=# CALL dbe_task.next_time(101, sysdate);
   next_time
  -----------
  (1 row)
  ```
  
- DBE_TASK.INTERVAL
  DBE_TASK.INTERVAL修改定时任务的执行间隔属性。
  DBE_TASK.INTERVAL原型为：
  ```
  DBE_TASK.INTERVAL(
  id              IN      INTEGER,
  interval_time      IN   TEXT);
  ```
  表11DBE_TASK.INTERVAL接口参数说明 
  | 参数            | 类型      | 入参/出参 | 是否可以为空 | 描述                                                                                                                                                      |
  |:---|:---|:---|:---|:---|
  | id              | integer | IN     | 否      | 指定的作业号。                                                                                                                                                |
  | interval_time | text     | IN     | 是      | 用来计算下次作业运行时间的时间表达式。作业间隔需要为有效的时间类型或interval类型。 如果为空值或字符串"null"，表示只执行一次。执行后，JOB状态STATUS变成'd' ，表示不再执行。 |
     
  示例：
  ```
  gaussdb=# CALL dbe_task.interval(101, 'sysdate + 1.0/1440');
   interval
  ----------
  (1 row)
  gaussdb=# CALL dbe_task.cancel(101);
   cancel
  --------
  (1 row)
  ```
  ![](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
  对于指定JOB正在运行状态（即job_status为'r'）时，不允许通过CANCEL、UPDATE、NEXT_TIME、CONTENT、INTERVAL等接口删除或修改JOB的参数信息。
  
 
#### 约束说明
- 使用SUMMIT/ID_SUBMIT创建一个新JOB后，该JOB从属于当前COORDINATOR（即该JOB仅在当前COORDINATOR上调度和执行），其他COORDINATOR不会调度和执行该JOB，如果出现COORDINATOR节点故障，将无法保证JOB正常执行。建议使用[PKG_SERVICE.SUBMIT_ON_NODES](https://support.huaweicloud.com/distributed-ref-v10-gaussdb/gaussdb-08-0468.html#ZH-CN_TOPIC_0000002793707581__li12446850163911)接口将JOB执行节点指定为CCN，以保证节点故障时JOB仍然可用。不是所有COORDINATOR都可以查看、修改、删除其他CN创建的JOB。
- JOB只能通过DBE_TASK高级包提供的接口进行创建、更新和删除操作。这是因为高级包的接口会考虑所有CN间JOB信息的同步，以及PG_JOB与PG_JOB_PROC表主键的关联操作。如果通过DML语句对PG_JOB表进行增删改，会导致JOB信息在CN间不一致，以及系统表无法关联变更，从而严重影响JOB内部的管理。
- 由于用户创建的每个任务和CN绑定，当任务运行过程中，该CN发生故障，则该任务的状态无法实时刷新，仍为'r'状态，需要等CN启动正常后才能刷新为's'状态。如果在任务未执行时CN发生故障，则该CN上的任务都得不到正常的调度和执行，需要人为干预让该CN恢复正常，或进行节点删除/替换，JOB才能正常的调度和执行。
- JOB在定时执行过程中，需要在当前JOB所属的CN上实时更新该JOB的运行状态、最近执行开始时间、最近执行结束时间、下次开始时间、失败次数（如果JOB执行失败）等相关参数信息到PG_JOB系统表中，并同步到其他CN，保证JOB信息的一致性。如果其他CN存在节点故障，那么JOB所属CN会同步超时重发的操作，导致JOB执行时间变长，但CN间同步超时失败后，原CN上PG_JOB表中JOB的相关信息仍然能正常更新，且JOB能正常执行成功。当故障CN恢复正常后，可能出现该CN上PG_JOB表中当前JOB的执行时间、运行状态等参数与原CN上不一致的情况，需要原CN上再次执行该JOB后才能保证JOB信息的同步。
- 对于并发同时有多个JOB到达执行时间的场景，由于会为每个JOB创建一个线程来执行JOB，由于系统内部启动每个线程的时间会有延迟，因此会导致同时并发执行的JOB开始时间有延迟，每个JOB的延迟时间在0.1ms左右。
 
