跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

在 GT4 中使用 IBM Cloudscape/Apache Derby 作为 RFT 数据库

简化网格的 Globus Toolkit 设置

Tom Seelbach (seelbach@us.ibm.com), 资深软件工程师, IBM
Tom Seelbach
Tom Seelbach 作为一名开发人员、测试人员以及 IBM Grid Toolbox 开发组的负责人,已经具有很多年使用 Globus Toolkit 的经验。在过去的几年中,他是 Tivoli Personalized Services Manager(WebSphere Everyplace Suite 产品的一部分)的负责人。他还为 http://movies.excite.com 开发了电影搜索和个性化设置,并为 http://money.excite.com 开发了内容管理。在娱乐方面,他喜欢踢英式足球,并花了一些时间来耕种农作物,并尽量与自己的妻子和 3 个女儿待在一起。

简介: 本文介绍了在使用 Apache Derby 开放源码数据库管理系统(DBMS)作为 Globus Toolkit 4.0(GT4)中的 Reliable File Transfer(RFT)服务的数据库管理系统时,所要对代码和配置进行的修改。GT4 目前可以支持 PostgreSQL 和 MySQL DBMS。由于 Derby 是一个 100% 的 Java™ 技术系统,因此它可以嵌入到 GT4 发行版中,这可以极大地简化网格的安装、配置和操作过程。GT4 中需要 DBMS 的核心组件是 RFT。

发布日期: 2005 年 11 月 14 日
级别: 中级
访问情况 : 1097 次浏览
评论: 


为什么要使用 Derby?

在 GT4 中使用 Derby 有几个原因:

  • Derby 是使用 Java 编程语言编写的,这意味着它不需要对每个支持的平台都进行编译。
  • Derby 设计用来嵌入到大型系统中,例如 GT4。
  • 实际上不需要设置。嵌入式的 Derby DBMS 可以自动启动。
  • Derby 非常小。核心的 jar 文件不到 2MB。
  • Derby 支持大部分 SQL 标准,完全可以用作 RDBMS 系统。如果需要,可以很容易地切换到其他的 DBMS。
  • Derby 和 GT4 都是遵循 Apache 许可证发布的。

修改概述

您需要做的修改主要有 3 类:模式、配置和代码。

  • 在模式中,所支持的数据类型 BOOLEAN/BITTEXT 中存在区别。
  • 在代码中,修改主要是对 null 的处理、可更新的游标以及对模式的修改。
  • 从配置的观点来看,修改更加简单了。我们将 Derby 作为一个嵌入式数据库运行,因此只需要很少的设置。

这些修改在将来的 GT4 发行版中应该就可以使用了。有关 GT4 中对 Derby 支持的可用性的更多信息,请访问 The Globus Alliance。问题和意见可以通过 GT4 Friends 讨论列表提出。


GT4 配置的修改

安装并配置 Derby

注意:我使用了 V10.1.1.0 版本的 Derby,这可以从 Apache.org 上下载。

安装 Globus Toolkit V4.0.1,并将 GLOBUS_LOCATION 环境变量设置为您安装的根目录,然后:

  • 解压 Derby 发行版,并将 derby.jar、derbyclient.jar 和 derbytools.jar 拷贝到 $GLOBUS_LOCATION/lib/ 中
  • 创建一个目录 $GLOBUS_LOCATION/database/
  • 将下面的代码添加到 etc/globus-user-env.sh 中:
    清单 1. globus-user-env.sh 中添加的内容
    						
    #
    #The following statement will set the jvm options for the database
    #
    export GLOBUS_OPTIONS=-Dderby.system.home=$GLOBUS_LOCATION/database/
    #
    export CLASSPATH=$GLOBUS_LOCATION/lib/derby.jar:
    $GLOBUS_LOCATION/lib/derbytools.jar:$GLOBUS_LOCATION/lib/derbyclient.jar
    

  • 导出 GLOBUS_LOCATION 的设置,并引用 globus-user-env.sh 文件。要确保环境变量都正确设置了,请检查 CLASSPATHGLOBUS_* 环境变量。例如:
    清单 2. 检查环境变量
    						
        env | grep CLASS
    CLASSPATH=/opt/gt401f/lib/derby.jar:/opt/gt401f/lib/derbytools.jar:/
    opt/gt401f/lib/derbyclient.jar
    
        env | grep GLOBUS
    GLOBUS_PATH=/opt/gt401f
    GLOBUS_LOCATION=/opt/gt401f
    GLOBUS_OPTIONS=-Dderby.system.home=/opt/gt401f/database
    

  • 要连接到 Derby 而不是其他数据库上,请修改 etc/globus_wsrf_rft/jndi-config.xml 文件中 driverNameconnectionString 的设置:
    org.apache.derby.jdbc.EmbeddedDriver
    
    jdbc:derby:directory:rftDatabase
    


修改模式,创建数据库

我们首先从 GT4 MySQL 模式开始入手,这可以在文件 GLOBUS_LOCATION/share/globus_wsrf_rft/rft_schema_mysql.sql 中找到,我们将其拷贝到 rft_schema_derby.sql 文件。与 PostgreSQL 模式相比,MySQL 模式的语义与 Derby 更为接近。具体来说,PostgreSQL 模式包含了 TEXT 类型的域。它们可以转换成 MySQL 模式中的标准 SQL VARCHAR 数据类型,因此也可以使用 Derby。

MySQL 模式中有几个使用 BIT 数据类型定义的域。在 Derby 中我们将把这些域重新定义为 CHAR(1)。以下域在 MySQL 模式中被定义为 bit:


清单 3. bit 域
				
started                 bit(1) default 0,
all_or_none             bit(1) default 0,
dcau                    bit(1) default 0,
notpt                   bit(1) default 0,
binary_mode             bit(1) default 1,
ignore_file_perm_errors bit(1) default 0

我们还需要对两处进行修改。首先,权限域被定义为 INT。将其修改为 VARCHAR。(这些修改会反映到将来的 Globus 发行版中)。其次,主键约束名重名了。对于 Derby 来说,主键约束名要求是惟一的。一个完整的 RFT SQL 模式如下所示:


清单 4. Derby 的完整 RFT SQL 模式
				
CREATE TABLE "GLOBUS"."REQUEST" (
        "ID" INTEGER NOT NULL, 
        "CONCURRENCY" INTEGER DEFAULT 1, 
        "TERMINATION_TIME" DOUBLE, 
        "PROXY_LOC" VARCHAR(200), 
        "USERNAME" VARCHAR(200), 
        "STARTED" CHAR(1), 
        "ALL_OR_NONE" CHAR(1), 
        "MAXATTEMPTS" INTEGER DEFAULT 1, 
        "DELEGATED_EPR" VARCHAR(1255), 
        "USER_SUBJECT" VARCHAR(200));
 
CREATE TABLE "GLOBUS"."TRANSFER" (
        "ID" INTEGER NOT NULL, 
        "REQUEST_ID" INTEGER NOT NULL, 
        "SOURCE_URL" VARCHAR(200) NOT NULL, 
        "DEST_URL" VARCHAR(200), 
        "STATUS" INTEGER DEFAULT 4, 
        "ATTEMPTS" INTEGER DEFAULT 0, 
        "USER_NAME" VARCHAR(100) DEFAULT NULL, 
        "DCAU" CHAR(1), 
        "PARALLEL_STREAMS" INTEGER DEFAULT 1, 
        "TCP_BUFFER_SIZE" INTEGER DEFAULT 0, 
        "BLOCK_SIZE" INTEGER DEFAULT 16000, 
        "NOTPT" CHAR(1), 
        "BINARY_MODE" CHAR(1), 
        "SOURCE_SUBJECT" VARCHAR(200), 
        "DEST_SUBJECT" VARCHAR(200), 
        "RETRY_TIME" DOUBLE DEFAULT 0, 
        "SIZE" DOUBLE DEFAULT 0, 
        "FAULT" VARCHAR(255), 
        "PERMISSIONS" VARCHAR(100), 
        "IGNORE_FILE_PERM_ERRORS" CHAR(1)
        );
 
CREATE TABLE "GLOBUS"."TRANSFERID" (
        "TRANSFER_ID" INTEGER NOT NULL
        );
 
CREATE TABLE "GLOBUS"."FACTORY" (
        "TOTAL_TRANSFERS" DOUBLE, 
        "TOTAL_BYTES" DOUBLE
        );
 
CREATE TABLE "GLOBUS"."RESTART" (
        "TRANSFER_ID" INTEGER, 
        "MARKER" VARCHAR(200)
        );
 
CREATE TABLE "GLOBUS"."REQUESTID" (
        "REQUEST_ID" INTEGER NOT NULL
        );

-- ----------------------------------------------
-- DDL Statements for keys
-- ----------------------------------------------

-- primary/unique
ALTER TABLE "GLOBUS"."TRANSFER" 
    ADD CONSTRAINT "TRANSFER_PK_CONS" PRIMARY KEY ("ID");

ALTER TABLE "GLOBUS"."REQUEST" 
    ADD CONSTRAINT "REQUEST_PK_CONS" PRIMARY KEY ("ID");

ALTER TABLE "GLOBUS"."TRANSFERID" 
    ADD CONSTRAINT "TRANSFER_ID_PK_CONS" PRIMARY KEY ("TRANSFER_ID");

ALTER TABLE "GLOBUS"."REQUESTID" 
    ADD CONSTRAINT "REQUEST_ID_PK_CONS" PRIMARY KEY ("REQUEST_ID");

使用 IJ 创建数据库,这是 Derby 的交互式 JDBC 脚本工具。


清单 5. 使用 IJ 创建数据库
				
java -classpath $GLOBUS_LOCATION/lib/derby.jar:
    $GLOBUS_LOCATION/lib/derbytools.jar 
    -Dderby.infolog.append=true 
    -Dij.protocol=jdbc:derby:directory:$GLOBUS_LOCATION/database/ 
    -D'ij.database=rftDatabase;create=true' org.apache.derby.tools.ij 
    $GLOBUS_LOCATION/share/globus_wsrf_rft/rft_schema_derby.sql


RFT 代码的修改

所有与数据库有关的代码都包含在两个类中,可以在 src/org/globus/transfer/reliable/service/ 目录中找到这两个类:

  • RFTResourceManager.java
  • ReliableFileTransferDbAdapter.java

对 RFTResourceManager.java 的修改

对 RFTResourceManager 的修改如下:

  • SQL 限制子句 在 Derby 中并不受支持。相反,我们使用 Statement.getMaxRows() 方法。
  • 可更新游标 —— 在撰写本文时,Derby 还不支持可更新的游标。因此我们使用一个新方法来替换 updateInt()updateRow() 调用,这就是 updateTransferJob(),它使用一个新的 PreparedStatement 来实现更新。

它与 1.22.4.5 版本的 RFTResourceManager.java 之间的区别如下:


清单 6. 对 RFTResourceManager.java 的修改
				
 93,96c93
+         + " order by id ";
+ 
+     private static final String updateTransferQuery =
+         "UPDATE transfer set status=? where id=?";
---
-         + " order by id limit ?";
223,255d219
+     public 
+     synchronized void updateTransferJob(int transferId, int status)
+         throws RftDBException {
+             Connection c = null;
+             PreparedStatement preparedStatement = null;
+             try {
+                 c = RFTDatabaseSetup.getDBConnection();
+                 preparedStatement = 
+                       c.prepareStatement(updateTransferQuery);
+                 preparedStatement.setObject(
+                                   1, new Integer(transferId));
+                 preparedStatement.setObject(2,
+                         new Integer(status));
+                 preparedStatement.executeUpdate();
+             } catch (SQLException e) {
+                 logger.error(i18n.getMessage("dbUpdateErr",
+                             "" + requestId), e);
+                 throw new RftDBException(i18n.getMessage(
+                           "dbUpdateErr", "" + requestId), e);
+             } finally {
+                 try {
+                     if (preparedStatement != null) {
+                         preparedStatement.close();
+                     }
+                     if (c != null) {
+                         RFTDatabaseSetup.returnDBConnection(c);
+                     }
+                 } catch (SQLException sql) {
+                     logger.warn(i18n.getMessage(
+                                      "dbStatementErr"), sql);
+                 }
+             }
+         }
269c237
+             statement.setMaxRows(this.cacheSize);
---
-             statement.setObject(3, new Integer(this.cacheSize));
271d238
+             for (int i=0;i<this.cacheSize;i++) {
274,275c241
+                 int tempTransferId = rs.getInt(1);
+                 transfer.setTransferId(new Integer(tempTransferId));
---
-                 transfer.setTransferId(new Integer(rs.getInt(1)));
298,299c264,265
+                 this.updateTransferJob(tempTransferId, 
+                          RFTConstants.STATUS_CACHED);
---
-                 rs.updateInt("status",RFTConstants.STATUS_CACHED);
-                 rs.updateRow();
306d271
+             }

对 ReliableFileTransferDbAdapter.java 的修改

对 ReliableFileTransferDbAdapter.java 的修改如下:

  • null 的处理 —— 在 Derby 中,需要显式地在 PreparedStatements 中将对象设置成 null,这需要使用一个诸如 pstmt.setObject(5, "null"); 之类的调用。以前,代码允许在处理可为空的域时采用缺省的行为。现在每个可空的域都会进行检查,并设置适当的缺省值。
  • 可更新的游标 —— 与 RFTResourceManager 中的修改类似,但是使用新的语句替换了 updateInt()updateRow() 调用。
  • Boolean 域 —— 回想一下我们将 SQL 模式的某些域从 BIT 修改成了 CHAR。这样,JDBC 调用将 CHAR 域设置成一个 Java Boolean 值,就会导致这个 CHAR 域被设置为 01。在 MySQL 中可以处理 BIT 域的代码依然可以处理 Derby 中的 CHAR 域。例如,pstmt.setObject(6, new Boolean(true)) 会将 CHAR 域在数据库中设置为 1

清单 7. 对 ReliableFileTransferDbAdapter.java 的修改
				
184c184,188
-                 pstmt.setObject(5, request.getMaxAttempts());
---
+                 if (request.getMaxAttempts() == null) {
+                     pstmt.setObject(5, new Integer(1));
+                 } else {
+                     pstmt.setObject(5, request.getMaxAttempts());
+                 }
324a329
+         Statement tempStatement = null;
335c340
-                 Statement tempStatement = c.createStatement();
---
+                 tempStatement = c.createStatement();
348,349c353,357
-                     rs.updateInt("request_id",nextRequestId);
-                     rs.updateRow();
---
+                     String updateQuery = 
+                            "update requestid set request_id=";
+                     updateQuery = updateQuery + nextRequestId;
+                     tempStatement = c.createStatement();
+                     tempStatement.executeUpdate(updateQuery);
402a410
+         Statement tempStatement = null;
416c424
-                 Statement tempStatement = c.createStatement();
---
+                 tempStatement = c.createStatement();
427,428c435,437
-                     rs.updateInt("transfer_id",nextTransferId);
-                     rs.updateRow();
---
+                     tempStatement = c.createStatement();
+                     tempStatement.executeUpdate(
+     "update transferid set " + "transfer_id= "+ nextTransferId);
482c491,495
-                     pstmt.setObject(6, tempUserName);
---
+                     if (tempUserName == null) {
+                         pstmt.setObject(6, "null");
+                     } else {
+                         pstmt.setObject(6, tempUserName);
+                     }
489c502,506
-                     pstmt.setObject(5, tempUserName);
---

+                    if(tempUserName == null) {
+                         pstmt.setObject(5, "null");
+                     } else {
+                         pstmt.setObject(5, tempUserName);
+                     }
852,861c869,918
-                     pstmt.setObject(5, rftOptions.getUserName());
-                     pstmt.setObject(6, rftOptions.getDcau());
-                     pstmt.setObject(7, rftOptions.\
                                         getParallelStreams());
-                     pstmt.setObject(8, rftOptions.\
                                         getTcpBufferSize());
-                     pstmt.setObject(9, rftOptions.getBlockSize());
-                     pstmt.setObject(10, rftOptions.getNotpt());
-                     pstmt.setObject(11, rftOptions.getBinary());
-                     pstmt.setObject(12, rftOptions.\
                                      getSourceSubjectName());
-                     pstmt.setObject(13, rftOptions.\
                                      getDestinationSubjectName());
-                     pstmt.setObject(14, rftOptions.\
                                          getIgnoreFilePermErr());
---
+                     if(rftOptions.getUserName() == null) {
+                         pstmt.setObject(5, "null");
+                     } else {
+                         pstmt.setObject(5,\
                                          rftOptions.getUserName());
+                     }
+                     if(rftOptions.getDcau() == null) {
+                         pstmt.setObject(6, new Boolean(true));
+                     } else {
+                         pstmt.setObject(6, rftOptions.getDcau());
+                     }
+                     if(rftOptions.getParallelStreams() == null) {
+                         pstmt.setObject(7, new Integer(1));
+                     } else {
+                         pstmt.setObject(7, rftOptions.\
                                             getParallelStreams());
+                     }
+                     if(rftOptions.getTcpBufferSize() == null) {
+                         pstmt.setObject(8, new Integer(16384));
+                     } else {
+                         pstmt.setObject(8, rftOptions.\
                                             getTcpBufferSize());
+                     }
+                     if (rftOptions.getBlockSize() == null) {
+                         pstmt.setObject(9, new Integer(16384));
+                     } else {
+                         pstmt.setObject(9,\
                                          rftOptions.getBlockSize());
+                     }
+                     if (rftOptions.getNotpt() == null) {
+                         pstmt.setObject(10, new Boolean(false));
+                     } else {
+                         pstmt.setObject(10, rftOptions.getNotpt());
+                     }
+                     if (rftOptions.getBinary() == null) {
+                         pstmt.setObject(11, new Boolean(true));
+                     } else {
+                         pstmt.setObject(11, rftOptions.getBinary());
+                     }
+                     if (rftOptions.getSourceSubjectName() == null) {
+                         pstmt.setObject(12, "null");
+                     } else {
+                         pstmt.setObject(12, rftOptions.\
                                          getSourceSubjectName());
+                     }
+                if (rftOptions.getDestinationSubjectName() == null) {
+                         pstmt.setObject(13, "null");
+                     } else {
+                         pstmt.setObject(13, rftOptions.\
                                         getDestinationSubjectName());
+                     }
+                     if (rftOptions.getIgnoreFilePermErr() == null) {
+                         pstmt.setObject(14, new Boolean(false));
+                     } else {
+                         pstmt.setObject(14, rftOptions.\
                                              getIgnoreFilePermErr());
+                     }
2070c2127,2128
-                 query.append("' limit 1");
---
+                 query.append("' ");
+                 statement.setMaxRows(1);


运行 RFT 测试工具来验证修改是否有效

可以运行 RFT 测试工具来验证这些修改是否有效。这可以参考 RFT 管理手册中的提示。


致谢

特别感谢 Argonne National Laboratory 的 Ravi Madduri。他是 RFT 的作者,也是本文中介绍的大部分代码的作者。还要感谢 IBM 的 Sneha Varghese 和 Shama Ghulamhussain,他们贡献了 Globus Toolkit 中对早期版本的 Cloudscape 的支持。


参考资料

学习

获得产品和技术

讨论

关于作者

Tom Seelbach

Tom Seelbach 作为一名开发人员、测试人员以及 IBM Grid Toolbox 开发组的负责人,已经具有很多年使用 Globus Toolkit 的经验。在过去的几年中,他是 Tivoli Personalized Services Manager(WebSphere Everyplace Suite 产品的一部分)的负责人。他还为 http://movies.excite.com 开发了电影搜索和个性化设置,并为 http://money.excite.com 开发了内容管理。在娱乐方面,他喜欢踢英式足球,并花了一些时间来耕种农作物,并尽量与自己的妻子和 3 个女儿待在一起。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Grid computing, Open source
ArticleID=161424
ArticleTitle=在 GT4 中使用 IBM Cloudscape/Apache Derby 作为 RFT 数据库
publish-date=11142005
author1-email=seelbach@us.ibm.com
author1-email-cc=

标签

Help
使用 搜索 文本框在 My developerWorks 中查找包含该标签的所有内容。

使用 滑动条 调节标签的数量。

热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。

我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。

使用搜索文本框在 My developerWorks 中查找包含该标签的所有内容。热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。