2007-02-02

剖析SQL Server数据库扩展存储过程

来源: 本站收集整理 作者:佚名 评论 0 条
 

SQL Server 的扩展存储过程,其实就是一个普通的 Windows DLL,只不过按照某种规则实现了某些函数而已。

近日在写一个扩展存储过程时,发现再写这类动态库时,还是有一些需要非凡注重的地方。之所以会非凡注重,是因为DLL运行于SQL Server的地址空间,而SQL Server到底是怎么进行线程调度的,却不是我们能了解的,即便了解也无法控制。

我们写动态库一般是自己用,即便给别人用,也很少像SQL Server这样,一个动态库很有可能加载多次,并且都是加载到一个进程的地址空间中。我们知道,当一个动态库加载到进程的地址空间时,DLL所有全局与局部变量初始化且仅初始化一次,以后再次调用 LoadLibrary函数时,仅仅增加其引用计数而已,那么很显然,假如有一全局 int ,初始化为0,调用一个函数另其自加,此时其值为1,然后再调用LoadLibray,并利用返回的句柄调用输出函数输出该值,虽然调用者觉得自己加载后立即输出,然后该值确实1而不是0。Windows是进程独立的,而在线程方面,假如不注重,上面的情况很可能会程序员带来麻烦。

介绍一下我的扩展存储过程,该动态库导出了三个函数: Init,work,Final,Init读文件,存储信息于内存,work简单的只是向该内存检索信息,Final回收内存。如上所说,假如不考虑同一进程空间多次加载问题,两次调用Init将造成无谓的浪费,因为我第一次已经读进了内存,要是通过堆分配内存,还会造成内存泄露。

我使用的引用计数解决的该问题,代码很短:


(本文仅表明作者个人观点,不代表本站及其管理员立场.) 推荐 收藏 投稿 打印 返回 关闭
上一篇:专家在线:SQL Server的数据清理技术  
下一篇:为SQL Server构造灵活可靠的安全门
    评论加载中…
#include "stdafx.h"

#include <string>

using namespace std;

extern "C" {

RETCODE __declspec(dllexport) xp_part_init(SRV_PROC *srvproc);

RETCODE __declspec(dllexport) xp_part_process(SRV_PROC *srvproc);

RETCODE __declspec(dllexport) xp_part_finalize(SRV_PROC *srvproc);

}

#define XP_NOERROR 0

#define XP_ERROR 1

HINSTANCE hInst = NULL;

int nRef = 0;

void printError (SRV_PROC *pSrvProc, CHAR* szErrorMsg);

ULONG __GetXpVersion(){ return ODS_VERSION;}

SRVRETCODE xp_part_init(SRV_PROC* pSrvProc){

typedef bool (*Func)();

if(nRef == 0){

hInst = ::LoadLibrary("part.dll");

if(hInst == NULL){

printError(pSrvProc,"不能加载part.dll");

return XP_ERROR;

}

Func theFunc = (Func)::GetProcAddress(hInst,"Init");

if(!theFunc()){

::FreeLibrary(hInst);

printError(pSrvProc,"不能获得分类号与专辑的对应表");

return XP_ERROR;

}

}

   nRef;

return (XP_NOERROR);

}

SRVRETCODE xp_part_process(SRV_PROC* pSrvProc){

typedef bool (*Func)(char*);

if(nRef == 0){

printError(pSrvProc,"函数尚未初始化,请首先调用xp_part_init");

return XP_ERROR;

}

Func theFunc = (Func)::GetProcAddress(hInst,"Get");

BYTE bType;

ULONG cbMaxLen,cbActualLen;

BOOL fNull;

char szInput[256] = {0};

if (srv_paraminfo(pSrvProc, 1, &bType,

(ULONG*)&cbMaxLen, (ULONG*)&cbActualLen, (BYTE*)szInput, &fNull) == FAIL){

printError(pSrvProc,"srv_paraminfo 返回 FAIL");

return XP_ERROR;

}

szInput[cbActualLen] = 0;

string strInput = szInput;

string strOutput = ";";

int cur,old = 0;

while(string::npos != (cur = strInput.find(’;’,old)) ){

strncpy(szInput,strInput.c_str()   old,cur - old);

szInput[cur - old] = 0;

old = cur   1;

theFunc(szInput);

if(string::npos ==strOutput.find((string)";"   szInput))

strOutput  = szInput;

}

strcpy(szInput,strOutput.c_str());

if (FAIL == srv_paramsetoutput(pSrvProc, 1, 

(BYTE*)(szInput   1), strlen(szInput) - 1,FALSE)){

printError (pSrvProc, "srv_paramsetoutput 调用失败");

return XP_ERROR;

}

srv_senddone(pSrvProc, (SRV_DONE_COUNT | SRV_DONE_MORE), 0, 0);

return XP_NOERROR;

}

SRVRETCODE xp_part_finalize(SRV_PROC* pSrvProc){

typedef void (*Func)();

if(nRef == 0)

return XP_NOERROR;

Func theFunc = (Func)::GetProcAddress(hInst,"Fin");

if((--nRef) == 0){

theFunc();

::FreeLibrary(hInst);

hInst = NULL;

}

return (XP_NOERROR);

}
共2页: 上一页 1 [2] 下一页
 推荐文章
     

网站首页  -  网站地图 -   站长论坛  -  网站投稿  -    -  网站管理
Copyright © 2008 芜湖站长站 All Rights Reserved 皖ICP备07500611号