1

我目前正在从事一个项目,该项目涉及用 C 语言为 IBM DB2 v10 开发 UDF。我所有的 C 代码都捆绑在一个名为的文件中rcdudf.c,它具有以下内容:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sqlca.h>
#include <sqludf.h>

typedef unsigned int (*hash_function)(char*, unsigned int len);

unsigned int FNVHash (char* str, unsigned int len);

typedef struct hash_record 
{
    void* value;
    struct hash_record* next;
}hash_record;

typedef struct hash_bucket
{
    void* key;
    hash_record* head_record;
}hash_bucket;

typedef struct hash_table 
{
    int bucket_num;
    hash_bucket** hash_entry;
}hash_table;

int hash_init(hash_table** h_table, int bucket_num);

int hash_destroy(hash_table** h_table);

int hash_contains_key(hash_table** h_table, void* key, unsigned int key_len);

void hash_put_value(hash_table** h_table, void* key, unsigned int key_len, void* value, unsigned int value_len);

void hash_remove_value(hash_table** h_table, void* key, unsigned int key_len, void* value, unsigned int value_len);

void hash_print_contents(hash_table** h_table);

int hash_calculate_data_size(hash_table** h_table);

char* hash_concatenate_data_to_char_array(hash_table** h_table);


struct SCRATCHDATA 
{
    int num_buckets;
    hash_table *h_table;
};

#ifdef __cplusplus
extern "C"
#endif
void SQL_API_FN GatherDistinctValues( SQLUDF_VARCHAR *inputAttrKey, SQLUDF_VARCHAR *inputAttrValue, 
            SQLUDF_INTEGER *out, SQLUDF_SMALLINT *inputAttrKeyNullInd, SQLUDF_SMALLINT *inputAttrValueNullInd, 
        SQLUDF_SMALLINT *outInd, SQLUDF_TRAIL_ARGS_ALL)
{
    struct SCRATCHDATA *sp;
    sp = (struct SCRATCHDATA *) SQLUDF_SCRAT->data;
    switch (SQLUDF_CALLT)
    {
        case SQLUDF_FIRST_CALL:
            hash_init(&(sp->h_table), 7);
            break;
        case SQLUDF_NORMAL_CALL:
            if( *inputAttrKeyNullInd == 0 && *inputAttrValueNullInd  == 0 )
            {
                /**
                 * If the provided value is not NULL and it is not contained in the 
                 * Global hash Table, it is going to be added. Otherwise, 
                 * nothing is done (it already exists).
                 */
                if( hash_contains_key(&(sp->h_table), (void*) inputAttrKey, strlen(inputAttrKey)) == 0 )
                {
                    hash_put_value(&(sp->h_table), (void*) inputAttrKey, strlen(inputAttrKey), 
                            (void*) inputAttrValue, strlen(inputAttrValue));
                }
            }
            break;
        case SQLUDF_FINAL_CALL:
            break;
    }
    *out = 0;
    *outInd = 0;
    return;
}

在文件的其余部分存在已定义方法的主体。为了将此 UDF“安装”到 DB2,我执行提供的脚本bldrtn如下:

~$./bldrtn rcdudf

并且可执行文件存储在~/sqllib/function目录中。接下来,我在 DB2 中执行以下脚本:

CREATE OR REPLACE FUNCTION GatherDistinctVal( VARCHAR(255), VARCHAR(255) )
    RETURNS INTEGER 
    EXTERNAL NAME 'rcdudf!GatherDistinctValues' 
    NOT FENCED 
    CALLED ON NULL INPUT 
    NOT VARIANT 
    NO SQL 
    PARAMETER STYLE SQL 
    LANGUAGE C 
    NO EXTERNAL ACTION;

通过发出命令~$db2 -tvsf create-udf.sql。之后,我尝试在 DB2 的 Sample 数据库上调用该函数,如下所示:

~$ db2 "select gatherdistinctval('job',job) from employee"

1          
-----------
SQL0444N  Routine "*TINCTVAL" (specific name "SQL140520113052600") is 
implemented with code in library or path "...function/rcdudf", function 
"GatherDistinctValues" which cannot be accessed.  Reason code: "5".  
SQLSTATE=42724

当我定义上述函数时,FENCED我收到以下错误:

~$ db2 "select GatherDistinctVal('Job',job) from Employee"

1          
-----------
SQL1646N  A routine failed because the fenced user ID cannot access required 
files in the sqllib directory or other instance or database directories.

我究竟做错了什么?我很确定该文件rcdudf存在于相应的目录中。此外,当我执行create-udf.sql脚本时,我从 DB2 收到一条成功消息。

当我执行时,~$ls -l ~/sqllib/function/我得到以下信息:

lrwxrwxrwx 1 root     db2iadm1    36 May 15 17:54 db2psmds -> /opt/ibm/db2/V10.1/function/db2psmds
drwxrwsr-t 2 db2inst1 db2iadm1  4096 May 15 17:54 db2rdf
lrwxrwxrwx 1 root     db2iadm1    35 May 15 17:54 db2rtsc -> /opt/ibm/db2/V10.1/function/db2rtsc
lrwxrwxrwx 1 root     db2iadm1    34 May 15 17:54 fpeevm -> /opt/ibm/db2/V10.1/function/fpeevm
-rw-r--r-- 1 db2inst1 db2iadm1  3256 May 20 17:58 GeneralHashFunctions.o
-rw-r--r-- 1 db2inst1 db2iadm1 11688 May 20 17:58 hash_table.o
-rwxr-xr-x 1 db2inst1 db2iadm1 17090 May 21 08:39 hopeless
drwxrwxr-x 3 db2inst1 db2iadm1  4096 May 14 16:07 jar
lrwxrwxrwx 1 root     db2iadm1    37 May 15 17:54 libdb2u.a -> /opt/ibm/db2/V10.1/function/libdb2u.a
-rwxr-xr-x 1 db2inst1 db2iadm1 17144 May 20 18:08 rcdudf
drwxrwsr-t 2 db2inst1 db2iadm1  4096 May  8 21:24 routine
lrwxrwxrwx 1 root     db2iadm1    33 May 15 17:54 tblpd -> /opt/ibm/db2/V10.1/function/tblpd
-rwxr-xr-x 1 db2inst1 db2iadm1 22280 May 20 16:27 testudf
-rwxr-xr-x 1 db2inst1 db2iadm1 34510 May 20 09:49 udfcli
-rwxr-xr-x 1 db2inst1 db2iadm1 13009 May 20 10:42 udfsrv
drwxrwsr-t 2 db2inst1 db2iadm1  4096 May 15 17:54 unfenced

可以看出,rcdudf 可执行文件在那里并且具有读取/执行权限。db2inst1此外,当我执行所有操作时,我以授权用户身份登录。

作为一个附加的实验,我ScalarUDF从 DB2 的样本中创建了这个函数。ScalarUDF的sql创建脚本与仅更改名称完全相同create-udf.sql。在文件夹中创建的可执行文件~/sqllib/function/udfsrv. 当我尝试执行scalarudf它时,它工作得很好。我仍然不明白为什么受保护的用户能够执行scalarudf但他无法执行gatherdistinctvalues

我已经发布了结果以db2 dbm get cfg供将来参考:

~$ db2 get dbm cfg

      Database Manager Configuration

Node type = Enterprise Server Edition with local and remote clients

Database manager configuration release level            = 0x0f00

CPU speed (millisec/instruction)             (CPUSPEED) = 2.637255e-07
Communications bandwidth (MB/sec)      (COMM_BANDWIDTH) = 1.000000e+02

Max number of concurrently active databases     (NUMDB) = 32
Federated Database System Support           (FEDERATED) = NO
Transaction processor monitor name        (TP_MON_NAME) = 

Default charge-back account           (DFT_ACCOUNT_STR) = 

Java Development Kit installation path       (JDK_PATH) = /opt/ibm/java-x86_64-71/

Database monitor heap size (4KB)          (MON_HEAP_SZ) = AUTOMATIC(90)
Java Virtual Machine heap size (4KB)     (JAVA_HEAP_SZ) = 2048
Audit buffer size (4KB)                  (AUDIT_BUF_SZ) = 0
Size of instance shared memory (4KB)  (INSTANCE_MEMORY) = AUTOMATIC(807642)
Instance memory for restart light (%) (RSTRT_LIGHT_MEM) = AUTOMATIC(10)
Agent stack size                       (AGENT_STACK_SZ) = 1024
Sort heap threshold (4KB)                  (SHEAPTHRES) = 0

Directory cache support                     (DIR_CACHE) = YES

Application support layer heap size (4KB)   (ASLHEAPSZ) = 15
Max requester I/O block size (bytes)         (RQRIOBLK) = 32767
Workload impact by throttled utilities(UTIL_IMPACT_LIM) = 10

Priority of agents                           (AGENTPRI) = SYSTEM
Agent pool size                        (NUM_POOLAGENTS) = AUTOMATIC(100)
Initial number of agents in pool       (NUM_INITAGENTS) = 0
Max number of coordinating agents     (MAX_COORDAGENTS) = AUTOMATIC(200)
Max number of client connections      (MAX_CONNECTIONS) = AUTOMATIC(MAX_COORDAGENTS)

Keep fenced process                        (KEEPFENCED) = YES
Number of pooled fenced processes         (FENCED_POOL) = AUTOMATIC(MAX_COORDAGENTS)
Initial number of fenced processes     (NUM_INITFENCED) = 0

Index re-creation time and redo index build  (INDEXREC) = RESTART

Transaction manager database name         (TM_DATABASE) = 1ST_CONN
Transaction resync interval (sec)     (RESYNC_INTERVAL) = 180

谢谢你。

4

2 回答 2

1

我知道这不是答案,但评论太大了。

SQL0444N RC 5 可以表示以下任何一种情况:

     There is insufficient memory to load the library containing the
     function or one or more symbols could not be resolved. This
     reason code indicates one of the following situations:
     1. One or more symbols might not have been resolved. The
        routine library might be dependent on a shared library that
        cannot be located (using the concatenation of directories
        specified in the LIBPATH environment variable in UNIX-based
        systems, the PATH environment variable in INTEL systems).
     2. The routine has a 64-bit library which is not supported
        within a 32-bit DB2 instance, or, the routine has a 32-bit
        library or DLL within a 64-bit DB2 instance that is
        incompatible with the routine definition.
     3. There was insufficient memory to load the library containing
        the function.

由于您似乎没有使用任何额外的库,因此我会检查目标文件位数与实例位数。

于 2014-05-21T12:22:58.343 回答
0

问题是bldrtnDB2 的脚本不能处理从多个文件中使用代码的情况。此外,似乎在我的文件开头添加用于定义哈希表和哈希函数的代码不起作用。

创建两个不同的文件hash_table.hhash_table.c在其中键入我的结构的代码。hash_table.h另外,在rcdudf.c文件中添加引用。之后更改bldrtn脚本,首先创建每个源文件的目标文件,然后将它们链接在一起。

详细地说,该bldrtn文件将具有以下更改的代码行:

$CC $EXTRA_C_FLAGS  -I$DB2PATH/include -c hash_table.c -D_REENTRANT
$CC $EXTRA_C_FLAGS  -I$DB2PATH/include -c GeneralHashFunctions.c -D_REENTRANT
$CC $EXTRA_C_FLAGS  -I$DB2PATH/include -c rcdudf.c -D_REENTRANT

$CC $LINK_FLAGS -o rcdudf rcdudf.o GeneralHashFunctions.o hash_table.o $EXTRA_LFLAG -L$DB2PATH/$LIB -ldb2 -lpthread

rm -f $DB2PATH/function/hopeless
cp hopeless $DB2PATH/function

这样,我的代码就被捆绑了rcdudf,DB2 可以完全执行它。

注意:好像每次注册一个新的UDF,都需要重启DB2

于 2014-05-21T17:48:50.753 回答