IBM DB2 C标量UDF错误SQL0444N(原因代码:5)

时间:2014-05-20 21:22:16

标签: c db2 db2-luw

我目前正在开发一个涉及在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身份登录。

作为一个增加的实验,我从DB2的示例中创建了ScalarUDF函数。 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

谢谢。

2 个答案:

答案 0 :(得分: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.

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

答案 1 :(得分:0)

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

创建两个不同的文件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