commit 45dedd35948a895e646c486d47b74382b6e676f8 Author: DeffPuzzL Date: Mon Mar 12 15:01:29 2018 +0800 stvm 1.2.2 diff --git a/README b/README new file mode 100644 index 0000000..63b6bda --- /dev/null +++ b/README @@ -0,0 +1,58 @@ +/************************************************************************************************* + STVM 高效缓存数据库 + *************************************************************************************************/ + +启动环境变量 +TVMDBD=/home/stvm/tvmdb 指向stvm工作目录 +TVMCFG=/home/stvm/tvmdb/.tvm.run 启动参数 + +编译项目 +cd stvm-1.2/src目录 + ./make + +在../lib下生成 + libstvm.a + libstvm.so + libstvm.so.1.2 -> ../lib/libstvm.so + +在../bin下生成 + stvm + detvm + +使用方法: +如果不使用多机集群,无需配置域文件,直接 stvm -w 缺省启动单机模式。 + +stvm -s 停止系统 + +STVM也提供一个类型sqlpuls类型简单工具, 输入: +stvm SQL 进入SQL界面,该工具主要用来运维调试使用。 +stvm DOM 进入域的维护 + +关于域的配置,请参见: + stvm.conf + +配置域完成后,可以stvm -c stvm.conf编译到$TVMCFG下 +然后在stvm -w启动即可 + +目前本版本为测试版本,不保证无bug,建议以单机模式64位下运行,将性能发挥在极致。 + +作者:Savens Liu +邮箱:deffpuzzl@qq.com + + + + +====更新日期:20180312==== +1、支持动态创建表语句 +2、新增对表结构导出功能 + +用法: +表创建语法示例: tbl_acct_base.def +在stvm SQL中,利用 create $file来创建表 +提交人:Savens Liu + +下本版本: +1、新增多机资源共享方式。 +2、JAVA接口开发 + +不定时更新 diff --git a/demo/count b/demo/count new file mode 100755 index 0000000..1e9554e Binary files /dev/null and b/demo/count differ diff --git a/demo/count.c b/demo/count.c new file mode 100644 index 0000000..137213f --- /dev/null +++ b/demo/count.c @@ -0,0 +1,51 @@ +#include "tvm.h" +#include "tmain.h" + +#define TBL_USER_INFO 20 + +typedef struct __TBL_USER_INFO +{ + long acct_id; + char user_no[21]; + char user_type[2]; + char user_nm[81]; + char user_addr[161]; + char user_phone[31]; +}dbUser; + +long lCountUserInfo() +{ + dbUser stUser; + size_t lRow = 0; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + /* 初始化TBL_USER_INFO表,每张表都需要初始化一次, 对于表重建后,需要重新初始化一次。*/ + if(RC_SUCC != lInitSATvm(pstSavm, TBL_USER_INFO)) + { + fprintf(stderr, "init failed, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + conditinit(pstSavm, stUser, TBL_USER_INFO); // 绑定变量 + stringset(pstSavm, stUser, user_type, "1"); // 查询条件赋值 + stringset(pstSavm, stUser, user_no, "20180224"); // 查询条件赋值 + + if(RC_SUCC != lCount(pstSavm, (void *)&lRow)) + { + fprintf(stderr, "Count error: (%d) (%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + fprintf(stdout, "Count:%ld\n\n", lRow); + return RC_SUCC; +} + +int main(int argc, char *argv[]) +{ + if(RC_SUCC != lCountUserInfo()) + return RC_FAIL; + + return RC_SUCC; +} + + diff --git a/demo/create b/demo/create new file mode 100755 index 0000000..a74aff3 Binary files /dev/null and b/demo/create differ diff --git a/demo/create.c b/demo/create.c new file mode 100644 index 0000000..b7ce591 --- /dev/null +++ b/demo/create.c @@ -0,0 +1,52 @@ +#include "tvm.h" +#include "tmain.h" + +#define TBL_USER_INFO 20 + +typedef struct __TBL_USER_INFO +{ + long acct_id; + char user_no[21]; + char user_type[2]; + char user_nm[81]; + char user_addr[161]; + char user_phone[31]; +}dbUser; + +CREATE lCreateUserInfo() +{ + DEFINE(TBL_USER_INFO, "TBL_USER_INFO", "", dbUser) + FIELD(dbUser, acct_id, "acct_id", FIELD_LONG) + FIELD(dbUser, user_no, "user_no", FIELD_CHAR) + FIELD(dbUser, user_type, "user_type", FIELD_CHAR) + FIELD(dbUser, user_nm, "user_nm", FIELD_CHAR) + FIELD(dbUser, user_addr, "user_addr", FIELD_CHAR) + FIELD(dbUser, user_phone, "user_phone", FIELD_CHAR) + + CREATE_IDX(NORMAL) // 创建查询索引 + IDX_FIELD(dbUser, acct_id, FIELD_LONG) + + CREATE_IDX(UNQIUE) // 创建唯一索引 + IDX_FIELD(dbUser, user_no, FIELD_CHAR) + IDX_FIELD(dbUser, user_type, FIELD_CHAR) + + FINISH +} + +int main(int argc, char *argv[]) +{ + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + if(RC_SUCC != lCreateTable(pstSavm, TBL_USER_INFO, 1000, lCreateUserInfo)) + { + fprintf(stderr, "create table %d failed, err: %s\n", TBL_USER_INFO, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + fprintf(stdout, "初始化表成功, completed successfully!!!\n"); + fflush(stderr); + + return RC_SUCC; +} + + diff --git a/demo/delete b/demo/delete new file mode 100755 index 0000000..0ece780 Binary files /dev/null and b/demo/delete differ diff --git a/demo/delete.c b/demo/delete.c new file mode 100644 index 0000000..4213e0a --- /dev/null +++ b/demo/delete.c @@ -0,0 +1,50 @@ +#include "tvm.h" +#include "tmain.h" + +#define TBL_USER_INFO 20 + +typedef struct __TBL_USER_INFO +{ + long acct_id; + char user_no[21]; + char user_type[2]; + char user_nm[81]; + char user_addr[161]; + char user_phone[31]; +}dbUser; + +long lDeleteUserInfo() +{ + dbUser stUser; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + /* 初始化TBL_USER_INFO表,每张表都需要初始化一次, 对于表重建后,需要重新初始化一次。*/ + if(RC_SUCC != lInitSATvm(pstSavm, TBL_USER_INFO)) + { + fprintf(stderr, "init failed, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + conditinit(pstSavm, stUser, TBL_USER_INFO); // 绑定变量 + stringset(pstSavm, stUser, user_type, "1"); // 查询条件赋值 + stringset(pstSavm, stUser, user_no, "20180223"); // 查询条件赋值 + + if(RC_SUCC != lDelete(pstSavm)) + { + fprintf(stderr, "Delete error: (%d) (%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + return RC_SUCC; +} + +int main(int argc, char *argv[]) +{ + + if(RC_SUCC != lDeleteUserInfo()) + return RC_FAIL; + + return RC_SUCC; +} + + diff --git a/demo/drop b/demo/drop new file mode 100755 index 0000000..1d121ce Binary files /dev/null and b/demo/drop differ diff --git a/demo/drop.c b/demo/drop.c new file mode 100644 index 0000000..69bf071 --- /dev/null +++ b/demo/drop.c @@ -0,0 +1,46 @@ +#include "tvm.h" +#include "tmain.h" + +#define TBL_USER_INFO 20 + +typedef struct __TBL_USER_INFO +{ + long acct_id; + char user_no[21]; + char user_type[2]; + char user_nm[81]; + char user_addr[161]; + char user_phone[31]; +}dbUser; + +long lDropUserInfo() +{ + dbUser stUser; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + /* 初始化TBL_USER_INFO表,每张表都需要初始化一次, 对于表重建后,需要重新初始化一次。*/ + if(RC_SUCC != lInitSATvm(pstSavm, TBL_USER_INFO)) + { + fprintf(stderr, "init failed, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + if(RC_SUCC != lDropTable(pstSavm, TBL_USER_INFO)) + { + fprintf(stderr, "drop table error:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + return RC_SUCC; +} + +int main(int argc, char *argv[]) +{ + + if(RC_SUCC != lDropUserInfo()) + return RC_FAIL; + + return RC_SUCC; +} + + diff --git a/demo/extreme b/demo/extreme new file mode 100755 index 0000000..492dcb6 Binary files /dev/null and b/demo/extreme differ diff --git a/demo/extreme.c b/demo/extreme.c new file mode 100644 index 0000000..ceef071 --- /dev/null +++ b/demo/extreme.c @@ -0,0 +1,52 @@ +#include "tvm.h" +#include "tmain.h" + +#define TBL_USER_INFO 20 + +typedef struct __TBL_USER_INFO +{ + long acct_id; + char user_no[21]; + char user_type[2]; + char user_nm[81]; + char user_addr[161]; + char user_phone[31]; +}dbUser; + +long lExtremeUserInfo() +{ + dbUser stUser; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + /* 初始化TBL_USER_INFO表,每张表都需要初始化一次, 对于表重建后,需要重新初始化一次。*/ + if(RC_SUCC != lInitSATvm(pstSavm, TBL_USER_INFO)) + { + fprintf(stderr, "init failed, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + conditinit(pstSavm, stUser, TBL_USER_INFO); // 绑定变量 + stringset(pstSavm, stUser, user_type, "1"); // 查询条件赋值 + + decorate(pstSavm, dbUser, user_nm, MATCH_MIN); + decorate(pstSavm, dbUser, user_phone, MATCH_MAX); + if(RC_SUCC != lExtreme(pstSavm, (void *)&stUser)) + { + fprintf(stderr, "Extreme error: (%d) (%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + fprintf(stdout, "user_nm:%s, user_phone:%s\n", stUser.user_nm, stUser.user_phone); + + return RC_SUCC; +} + +int main(int argc, char *argv[]) +{ + if(RC_SUCC != lExtremeUserInfo()) + return RC_FAIL; + + return RC_SUCC; +} + + diff --git a/demo/group b/demo/group new file mode 100755 index 0000000..a824dd0 Binary files /dev/null and b/demo/group differ diff --git a/demo/group.c b/demo/group.c new file mode 100644 index 0000000..c62030b --- /dev/null +++ b/demo/group.c @@ -0,0 +1,56 @@ +#include "tvm.h" +#include "tmain.h" + +#define TBL_USER_INFO 20 + +typedef struct __TBL_USER_INFO +{ + long acct_id; + char user_no[21]; + char user_type[2]; + char user_nm[81]; + char user_addr[161]; + char user_phone[31]; +}dbUser; + +long lGroupUserInfo() +{ + size_t i, lRow = 0; + dbUser stUser, *pstUser = NULL; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + /* 初始化TBL_USER_INFO表,每张表都需要初始化一次, 对于表重建后,需要重新初始化一次。*/ + if(RC_SUCC != lInitSATvm(pstSavm, TBL_USER_INFO)) + { + fprintf(stderr, "init failed, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + conditinit(pstSavm, stUser, TBL_USER_INFO); // 绑定变量 + stringset(pstSavm, stUser, user_type, "1"); // 查询条件赋值 + + decorate(pstSavm, dbUser, user_nm, GROUP_BY | ORDER_ASC); + decorate(pstSavm, dbUser, user_phone, GROUP_BY | ORDER_DESC); + if(RC_SUCC != lGroup(pstSavm, &lRow, (void **)&pstUser)) + { + fprintf(stderr, "Group error: (%d) (%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + for(i = 0; i < lRow; i ++) + fprintf(stdout, "user_nm:%s, user_phone:%s\n", pstUser[i].user_nm, pstUser[i].user_phone); + + TFree(pstUser); + + return RC_SUCC; +} + +int main(int argc, char *argv[]) +{ + if(RC_SUCC != lGroupUserInfo()) + return RC_FAIL; + + return RC_SUCC; +} + + diff --git a/demo/insert b/demo/insert new file mode 100755 index 0000000..cc53418 Binary files /dev/null and b/demo/insert differ diff --git a/demo/insert.c b/demo/insert.c new file mode 100644 index 0000000..87de483 --- /dev/null +++ b/demo/insert.c @@ -0,0 +1,58 @@ +#include "tvm.h" +#include "tmain.h" + +#define TBL_USER_INFO 20 + +typedef struct __TBL_USER_INFO +{ + long acct_id; + char user_no[21]; + char user_type[2]; + char user_nm[81]; + char user_addr[161]; + char user_phone[31]; +}dbUser; + +long lInsertUserInfo() +{ + dbUser stUser; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + /* 初始化TBL_USER_INFO表,每张表都需要初始化一次, 对于表重建后,需要重新初始化一次。*/ + if(RC_SUCC != lInitSATvm(pstSavm, TBL_USER_INFO)) + { + fprintf(stderr, "init failed, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + memset(&stUser, 0, sizeof(dbUser)); + stUser.acct_id = 10021; // 对结构体赋值 + strcpy(stUser.user_no, "20180223"); // 对结构体赋值 + strcpy(stUser.user_type, "1"); // 对结构体赋值 + strcpy(stUser.user_nm, "Savens Liu"); // 对结构体赋值 + strcpy(stUser.user_addr, "China"); // 对结构体赋值 + strcpy(stUser.user_phone, "18672911111"); // 对结构体赋值 + insertinit(pstSavm, stUser, TBL_USER_INFO); // 绑定变量 + + if(RC_SUCC != lInsert(pstSavm)) // 插入记录 + { + fprintf(stderr, "Insert error:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + return RC_SUCC; +} + +int main(int argc, char *argv[]) +{ + + if(RC_SUCC != lInsertUserInfo()) + return RC_FAIL; + + fprintf(stdout, "新增记录成功, completed successfully!!!\n"); + fflush(stderr); + + return RC_SUCC; +} + + diff --git a/demo/makefile b/demo/makefile new file mode 100755 index 0000000..81a50a0 --- /dev/null +++ b/demo/makefile @@ -0,0 +1,57 @@ +INCDIR= -I/usr/include -I$(HOME)/include -I./ -I./include -I../include +LIBDIR= -L$(HOME)/lib -L../lib -lstvm -lm -lc -ldl -lpthread +CC=cc -fPIC +CO=-c -g +OUTLIB=../lib +OUTBIN=../bin + +OBJFILE=tree.o sem.o msg.o tcp.o str.o list.o conf.o +CREATE=create +INSERT=insert +SELECT=select +QUERY=query +DELETE=delete +UPDATE=update +COUNT=count +GROUP=group +EXTREME=extreme +TRUNCATE=truncate +DROP=drop +PRESSURE=press_demo + +all: $(CREATE) $(INSERT) $(SELECT) $(QUERY) $(DELETE) $(UPDATE) $(COUNT) $(GROUP) $(EXTREME) $(TRUNCATE) $(DROP) $(PRESSURE) clean +$(CREATE): create.o + $(CC) -o $@ $< $(LIBDIR) +$(INSERT): insert.o + $(CC) -o $@ $< $(LIBDIR) +$(SELECT): select.o + $(CC) -o $@ $< $(LIBDIR) +$(QUERY): query.o + $(CC) -o $@ $< $(LIBDIR) +$(DELETE): delete.o + $(CC) -o $@ $< $(LIBDIR) +$(UPDATE): update.o + $(CC) -o $@ $< $(LIBDIR) +$(COUNT): count.o + $(CC) -o $@ $< $(LIBDIR) +$(GROUP): group.o + $(CC) -o $@ $< $(LIBDIR) +$(EXTREME): extreme.o + $(CC) -o $@ $< $(LIBDIR) +$(TRUNCATE): truncate.o + $(CC) -o $@ $< $(LIBDIR) +$(DROP): drop.o + $(CC) -o $@ $< $(LIBDIR) +$(PRESSURE): press_demo.o + $(CC) -o $@ $< $(LIBDIR) + +.SUFFIXES: .c .o + +.c.o: + $(CC) $(CO) $*.c $(INCDIR) $(LIBDIR) + +fall: + @touch *c + @make all +clean: + rm -f *.o diff --git a/demo/press_demo b/demo/press_demo new file mode 100755 index 0000000..90a132a Binary files /dev/null and b/demo/press_demo differ diff --git a/demo/press_demo.c b/demo/press_demo.c new file mode 100644 index 0000000..06c5249 --- /dev/null +++ b/demo/press_demo.c @@ -0,0 +1,59 @@ +#include "tvm.h" +#include "tmain.h" + +#define TBL_USER_INFO 20 + +typedef struct __TBL_USER_INFO +{ + long acct_id; + char user_no[21]; + char user_type[2]; + char user_nm[81]; + char user_addr[161]; + char user_phone[31]; +}dbUser; + +long lSelectUserInfo() +{ + dbUser stUser; + int i = 0; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + /* 初始化TBL_USER_INFO表,每张表都需要初始化一次, 对于表重建后,需要重新初始化一次。*/ + vHoldConnect(pstSavm); // 让进程始终与STVM 保持链接,可以大大提高效率 + if(RC_SUCC != lInitSATvm(pstSavm, TBL_USER_INFO)) + { + fprintf(stderr, "init failed, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + conditinit(pstSavm, stUser, TBL_USER_INFO); // 绑定变量 + stringset(pstSavm, stUser, user_type, "1"); // 查询条件赋值 + stringset(pstSavm, stUser, user_no, "20180223"); // 查询条件赋值 + + for(i = 0; i < 2000000; i ++) + { + if(RC_SUCC != lSelect(pstSavm, (void *)&stUser)) + { + fprintf(stderr, "Select error: (%d) (%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + } + + fprintf(stdout, "acct_id:%ld, user_no:%s, user_type:%s, user_nm:%s, user_addr:%s, user_phone:%s\n", + stUser.acct_id, stUser.user_no, stUser.user_type, stUser.user_nm, stUser.user_addr, stUser.user_phone); + + vHoldRelease(pstSavm); // 在进程退出时,断开链接 + return RC_SUCC; +} + +int main(int argc, char *argv[]) +{ + + if(RC_SUCC != lSelectUserInfo()) + return RC_FAIL; + + return RC_SUCC; +} + + diff --git a/demo/query b/demo/query new file mode 100755 index 0000000..0e502aa Binary files /dev/null and b/demo/query differ diff --git a/demo/query.c b/demo/query.c new file mode 100644 index 0000000..7e16fcb --- /dev/null +++ b/demo/query.c @@ -0,0 +1,59 @@ +#include "tvm.h" +#include "tmain.h" + +#define TBL_USER_INFO 20 + +typedef struct __TBL_USER_INFO +{ + long acct_id; + char user_no[21]; + char user_type[2]; + char user_nm[81]; + char user_addr[161]; + char user_phone[31]; +}dbUser; + +long lQueryUserInfo() +{ + size_t i, lRow = 0; + dbUser stUser, *pstUser = NULL; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + /* 初始化TBL_USER_INFO表,每张表都需要初始化一次, 对于表重建后,需要重新初始化一次。*/ + if(RC_SUCC != lInitSATvm(pstSavm, TBL_USER_INFO)) + { + fprintf(stderr, "init failed, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + conditinit(pstSavm, stUser, TBL_USER_INFO); // 绑定变量 + stringset(pstSavm, stUser, user_type, "1"); // 查询条件赋值 + stringset(pstSavm, stUser, user_no, "20180223"); // 查询条件赋值 + + if(RC_SUCC != lQuery(pstSavm, &lRow, (void **)&pstUser)) + { + fprintf(stderr, "Query error:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + for(i = 0; i < lRow; i ++) + { + fprintf(stdout, "acct_id:%ld, user_no:%s, user_type:%s, user_nm:%s, user_addr:%s, user_phone:%s\n", + pstUser[i].acct_id, pstUser[i].user_no, pstUser[i].user_type, pstUser[i].user_nm, pstUser[i].user_addr, + pstUser[i].user_phone); + } + TFree(pstUser); + + return RC_SUCC; +} + +int main(int argc, char *argv[]) +{ + + if(RC_SUCC != lQueryUserInfo()) + return RC_FAIL; + + return RC_SUCC; +} + + diff --git a/demo/select b/demo/select new file mode 100755 index 0000000..f675746 Binary files /dev/null and b/demo/select differ diff --git a/demo/select.c b/demo/select.c new file mode 100644 index 0000000..4f074c8 --- /dev/null +++ b/demo/select.c @@ -0,0 +1,53 @@ +#include "tvm.h" +#include "tmain.h" + +#define TBL_USER_INFO 20 + +typedef struct __TBL_USER_INFO +{ + long acct_id; + char user_no[21]; + char user_type[2]; + char user_nm[81]; + char user_addr[161]; + char user_phone[31]; +}dbUser; + +long lSelectUserInfo() +{ + dbUser stUser; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + /* 初始化TBL_USER_INFO表,每张表都需要初始化一次, 对于表重建后,需要重新初始化一次。*/ + if(RC_SUCC != lInitSATvm(pstSavm, TBL_USER_INFO)) + { + fprintf(stderr, "init failed, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + conditinit(pstSavm, stUser, TBL_USER_INFO); // 绑定变量 + stringset(pstSavm, stUser, user_type, "1"); // 查询条件赋值 + stringset(pstSavm, stUser, user_no, "20180223"); // 查询条件赋值 + + if(RC_SUCC != lSelect(pstSavm, (void *)&stUser)) + { + fprintf(stderr, "Select error: (%d) (%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + fprintf(stdout, "acct_id:%ld, user_no:%s, user_type:%s, user_nm:%s, user_addr:%s, user_phone:%s\n", + stUser.acct_id, stUser.user_no, stUser.user_type, stUser.user_nm, stUser.user_addr, stUser.user_phone); + + return RC_SUCC; +} + +int main(int argc, char *argv[]) +{ + + if(RC_SUCC != lSelectUserInfo()) + return RC_FAIL; + + return RC_SUCC; +} + + diff --git a/demo/truncate b/demo/truncate new file mode 100755 index 0000000..86f2e2b Binary files /dev/null and b/demo/truncate differ diff --git a/demo/truncate.c b/demo/truncate.c new file mode 100644 index 0000000..74a17a2 --- /dev/null +++ b/demo/truncate.c @@ -0,0 +1,47 @@ +#include "tvm.h" +#include "tmain.h" + +#define TBL_USER_INFO 20 + +typedef struct __TBL_USER_INFO +{ + long acct_id; + char user_no[21]; + char user_type[2]; + char user_nm[81]; + char user_addr[161]; + char user_phone[31]; +}dbUser; + +long lTruncateUserInfo() +{ + dbUser stUser; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + /* 初始化TBL_USER_INFO表,每张表都需要初始化一次, 对于表重建后,需要重新初始化一次。*/ + if(RC_SUCC != lInitSATvm(pstSavm, TBL_USER_INFO)) + { + fprintf(stderr, "init failed, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + if(RC_SUCC != lTruncate(pstSavm, TBL_USER_INFO)) + { + fprintf(stderr, "Truncate error: (%d)(%s)\n", pstSavm->m_lEType, pstSavm->m_lErrno, + sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + return RC_SUCC; +} + +int main(int argc, char *argv[]) +{ + + if(RC_SUCC != lTruncateUserInfo()) + return RC_FAIL; + + return RC_SUCC; +} + + diff --git a/demo/update b/demo/update new file mode 100755 index 0000000..2fd3380 Binary files /dev/null and b/demo/update differ diff --git a/demo/update.c b/demo/update.c new file mode 100644 index 0000000..df6ccc2 --- /dev/null +++ b/demo/update.c @@ -0,0 +1,52 @@ +#include "tvm.h" +#include "tmain.h" + +#define TBL_USER_INFO 20 + +typedef struct __TBL_USER_INFO +{ + long acct_id; + char user_no[21]; + char user_type[2]; + char user_nm[81]; + char user_addr[161]; + char user_phone[31]; +}dbUser; + +long lUpdateUserInfo() +{ + dbUser stUser, stUpd; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + /* 初始化TBL_USER_INFO表,每张表都需要初始化一次, 对于表重建后,需要重新初始化一次。*/ + if(RC_SUCC != lInitSATvm(pstSavm, TBL_USER_INFO)) + { + fprintf(stderr, "init failed, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + updateinit(stUpd); + conditinit(pstSavm, stUser, TBL_USER_INFO); // 绑定变量 + stringset(pstSavm, stUser, user_type, "1"); // 查询条件赋值 + stringset(pstSavm, stUser, user_no, "20180224"); // 查询条件赋值 + + stringupd(pstSavm, stUpd, user_phone, "1869112XXXX"); + if(RC_SUCC != lUpdate(pstSavm, (void *)&stUpd)) + { + fprintf(stderr, "Update error: (%d) (%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + return RC_SUCC; +} + +int main(int argc, char *argv[]) +{ + + if(RC_SUCC != lUpdateUserInfo()) + return RC_FAIL; + + return RC_SUCC; +} + + diff --git a/include/tmain.h b/include/tmain.h new file mode 100644 index 0000000..5057813 --- /dev/null +++ b/include/tmain.h @@ -0,0 +1,135 @@ +/* +* Copyright (c) 2018 Savens Liu +* +* The original has been patented, Open source is not equal to open rights. +* Anyone can clone, download, learn and discuss for free. Without the permission +* of the copyright owner or author, it shall not be merged, published, licensed or sold. +* The copyright owner or author has the right to pursue his responsibility. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _HHH_TVM_DOMAIN_HHH__ +#define _HHH_TVM_DOMAIN_HHH__ +#include "tvm.h" + + +typedef struct epoll_event epollevt; +typedef long (*FUNCEXEC)(SATvm *pstSavm, void *arg); + +/************************************************************************************************* + + *************************************************************************************************/ +#define SET_BLOCK 0 +#define SET_UNBLOCK 1 +#define READ_BUFFER 4096 +#define MAX_EVENTS 5000 +#define READ_MAX_LEN 1024 * 10 +#define DATA_MAX_LEN 1048576 // 1024*1024 Maximum self-protection single record 1M +#define MAX_CON_EVENTS 65535 +#define TVM_PORT_LISTEN 1801 +#define TVM_PORT_DOMAIN 1800 +#define TVM_LOCAL_SERV "LIS.tvm" +#define TVM_REMOTE_DOM "RDS.tvm" +#define LOCAL_HOST_IP "127.0.0.1" + + +/************************************************************************************************* + 表结构&索引定义区 + *************************************************************************************************/ +typedef struct __SOCK_CONNECT +{ + char m_szCltIp[16]; + int m_lCltPort; + BSock m_skSock; + int m_isListen; + BOOL m_bWork; + ulong m_uWorker; + CMList *m_pstWork; +}SKCon; + +typedef struct __TVM_INTERFACE +{ + Benum m_enum; + Uenum m_lFind; + TABLE m_table; + uint m_lDLen; + uint m_lErrno; + size_t m_lRows; +}TFace; + +/************************************************************************************************* + macro + *************************************************************************************************/ + +/************************************************************************************************* + function + *************************************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif + +extern void lInitTitle(int argc, char **argv, char **envp); +extern void vSetTitile(const char *name); +extern void vDeleteRowgrp(Rowgrp *pstNode); +extern Rowgrp* pFindRowList(Rowgrp *root, long idx); +extern void vSortRowgrp(Rowgrp **pproot, TblKey *pstKey, Benum em); +extern long lCountRowgrp(Rowgrp *pstRoot, void *psvData, long lLen, size_t lCount); +extern long lSortRowList(SATvm *, size_t lRow, void *pvData, size_t lTruck); +extern long lConvRowList(SATvm *pstSavm, Rowgrp *root, size_t *plOut, void **ppsvOut); +extern long lParsRowList(SATvm *pstSavm, void *pszBuffer, long lData, Rowgrp **root); +extern Rowgrp* pInsertRowgrp(SATvm *, Rowgrp *, Rowgrp *, Rowgrp *, void *, long , size_t ); +extern bool bRepeatLstgrp(FdCond *pstRrp, void *pvData, TABLE t, size_t lOut, void *psvOut); +extern long lInsertLstgrp(SATvm *, FdCond *, void *, TABLE , size_t *, void **ppsvOut); + +extern bool bExistProcess(long lPid); +extern void vInitTitle(int argc, char **argv, char **envp); +extern long lBootLocal(SATvm *pstSavm, TBoot *pstBoot, Benum eMode); +extern long lBootDomain(SATvm *pstSavm, TBoot *pstBoot, long lMode); +extern long lMultListen(SATvm *pstSavm, long lPort, long , FUNCEXEC , void *arg, FUNCEXEC ); +extern long lOfflineNotify(SATvm *pstSavm, long lPort); +extern long lRefreshNotify(SATvm *pstSavm, long lPort); +extern long lPullNotify(SATvm *pstSavm, TDomain *pstDom, size_t lCount); +extern long lConnectNotify(SATvm *pstSavm, TDomain *pstDom, long lPort); +extern long lTvmGetTblIndex(SATvm *pstSavm, char *pszTable, char *pszPart, TIndex *pstIndex); +extern long lTvmGetTblField(SATvm *pstSavm, TABLE t, size_t *plOut, TField **ppstField); + + + +extern long lTvmBeginWork(SATvm *pstSavm); +extern long lTvmRollbackWork(SATvm *pstSavm); +extern long lTvmCommitWork(SATvm *pstSavm); +extern long lTvmEndWork(SATvm *pstSavm); +extern void vTvmDisconnect(SATvm *pstSavm); +extern long lTvmConnect(SATvm *pstSavm, char *pszIp, long lPort, int times); +extern long lTvmTruncate(SATvm *pstSavm, TABLE t); +extern long lTvmGroup(SATvm *pstSavm, size_t *plOut, void **ppvOut); +extern long lTvmCount(SATvm *pstSavm, size_t *plCount); +extern long lTvmInsert(SATvm *pstSavm); +extern long lTvmSelect(SATvm *pstSavm, void *pvOut); +extern long lTvmQuery(SATvm *pstSavm, size_t *plOut, void **ppvOut); +extern long lTvmUpdate(SATvm *pstSavm, void *pvData); +extern long lTvmDelete(SATvm *pstSavm); +extern long lTvmExtreme(SATvm *pstSavm, void *pvOut); +extern long lTvmDropTable(SATvm *pstSavm, TABLE t); +extern long lTvmRenameTable(SATvm *pstSavm, TABLE to, TABLE tn); +extern long lTvmSelectSeque(SATvm *pstSavm, char *pszSQName, ulong *pulNumber); +extern long lTvmSetSequence(SATvm *pstSavm, char *pszSQName, ulong uStart); +extern long lTvmRebuildIndex(SATvm *pstSavm, TABLE t); +extern long lTvmResetLock(SATvm *pstSavm, TABLE t); + +#ifdef __cplusplus +} +#endif + +#endif // _HHH_TVM_DOMAIN_HHH__ diff --git a/include/tstr.h b/include/tstr.h new file mode 100644 index 0000000..fe0f108 --- /dev/null +++ b/include/tstr.h @@ -0,0 +1,174 @@ +/* +* Copyright (c) 2018 Savens Liu +* +* The original has been patented, Open source is not equal to open rights. +* Anyone can clone, download, learn and discuss for free. Without the permission +* of the copyright owner or author, it shall not be merged, published, licensed or sold. +* The copyright owner or author has the right to pursue his responsibility. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef _HHH_TVM_BASE_STR_HHH__ +#define _HHH_TVM_BASE_STR_HHH__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef short int sint; +typedef unsigned int uint; +typedef unsigned long ulong; +typedef long long llong; +typedef unsigned char ushar; +typedef unsigned short ushort; +typedef unsigned char Byte; +typedef long int Benum; +typedef unsigned int Uenum; +typedef int BSock; + +#ifndef BOOL +typedef unsigned int BOOL; +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef __cplusplus +#ifndef bool +typedef unsigned char bool; +#endif + +#ifndef true +#define true 1 +#endif + +#ifndef false +#define false 0 +#endif + +#endif // __cplusplus + + +#define RC_NOTFOUND 24 +#define RC_MATCH 2 +#define RC_MISMA 1 +#define RC_SUCC 0 +#define RC_FAIL -1 +#define RC_CONTU -5 +#define RC_CLOSE -9 + +#define LOG_DEFU_SIZE 20480000 +#define LOG_DEFU_NAME "tvm.log" + +typedef pthread_mutex_t pmutex; +/************************************************************************************************* + function + *************************************************************************************************/ +typedef struct __COMLIST +{ + long m_lSize; + void *m_psvData; + struct __COMLIST *pstNext; + struct __COMLIST *pstLast; +}CMList; + +typedef struct __ROWGROUP +{ + long lIdx; + long lLen; + size_t lCount; + pmutex lock; + void *psvData; + struct __ROWGROUP *pstSSet; + struct __ROWGROUP *pstFset; + struct __ROWGROUP *pstNext; + struct __ROWGROUP *pstLast; +}Rowgrp; + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) > (b) ? (b) : (a)) +#define bool(x) (x == 0 ? false : true) +#define BOOL(x) (x == 0 ? false : true) + +extern CMList* pGetCMTail(CMList *pstRoot); +extern CMList* pSearchNode(CMList *pstRoot, void *psvData, long lSize); +extern CMList* pInsertList(CMList *pstRoot, void *pszData, long lSize); +extern CMList* pDeleteNode(CMList *pstRoot, void *psvData, long lSize); +extern void vDestroyList(CMList *pstRoot); + +extern char* supper(char *s); +extern char* slower(char *s); +extern char* strimcrlf(char *p); +extern char* sltrim(char *p); +extern char* srtrim(char *p); +extern char* strimall(char *p); +extern char* strimfield(char *s); +extern char* strimcpy(char *d, char *s, int l); +extern char* strimabout(char *s, char *o, char *d); +extern long lfieldnum(char *p, char *k); +extern char* sfieldvalue(char *p, char *k, int id); +extern long lgetstrnum(char *p, char *s); +extern char* sgetvalue(char *p, char *s, int id); +extern char* sfieldreplace(char *p, char o, char d); + +#ifdef __cplusplus +} +#endif + +#endif // _HHH_TVM_BASE_STR_HHH__ diff --git a/include/tvm.h b/include/tvm.h new file mode 100644 index 0000000..a6d83ba --- /dev/null +++ b/include/tvm.h @@ -0,0 +1,747 @@ +/* +* Copyright (c) 2018 Savens Liu +* +* The original has been patented, Open source is not equal to open rights. +* Anyone can clone, download, learn and discuss for free. Without the permission +* of the copyright owner or author, it shall not be merged, published, licensed or sold. +* The copyright owner or author has the right to pursue his responsibility. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __TVM_DEFIND_HHHH___ +#define __TVM_DEFIND_HHHH___ +#include "tstr.h" + +typedef pthread_rwlock_t RWLock; +typedef pthread_rwlockattr_t RWAttr; +typedef unsigned int TABLE; +typedef long long llSEQ; +typedef long (*TCREATE)(TABLE t); +typedef long CREATE; + +//#pragma pack(4) + +#define TVM_VKERNEL "1.2.0.0" +#define TVM_VERSION "1.2.2.0" +/************************************************************************************************* + custom macro + *************************************************************************************************/ +#define PROT_JAVA 512 +#define FIRST_ROW 256 +#define ORDER_DESC 128 +#define ORDER_ASC 64 +#define ORDER_BY 64 +#define GROUP_BY 32 +#define MATCH_MAX 16 +#define MATCH_MIN 8 + +#define FIELD_DOUB 4 +#define FIELD_LONG 2 +#define FIELD_CHAR 1 + +// execution plan +#define EXE_PLAN_ALL 0 +#define EXE_PLAN_IDX 1 +#define EXE_PLAN_GRP 2 + +#define CHK_SELECT 0 +#define IDX_SELECT 1 +#define RCD_SELECT 2 +#define NIL_IGNORE 8 + +#define OPERATE_NULL 0 +#define OPERATE_INSERT 1 +#define OPERATE_DELETE 2 +#define OPERATE_UPDATE 4 +#define OPERATE_SELECT 8 +#define OPERATE_TRCATE 14 +#define OPERATE_COUNT 15 +#define OPERATE_GROUP 16 +#define OPERATE_QUERY 17 +#define OPERATE_EXTREM 18 +#define OPERATE_TBDROP 19 +#define OPERATE_RENAME 20 +#define OPERATE_SELSEQ 21 +#define OPERATE_SETSEQ 22 +#define OPERATE_RBDIDX 23 +#define OPERATE_RETLOK 24 +#define OPERATE_DMKEEP 25 +#define OPERATE_DOMPUL 26 +#define OPERATE_DOMPSH 27 +#define OPERATE_DMRECN 28 +#define OPERATE_REFRESH 29 +#define OPERATE_DOMLOFF 30 +#define OPERATE_DOMROFF 31 +#define OPERATE_PULTBL 32 +#define OPERATE_BEGWORK 33 +#define OPERATE_ROLWORK 34 +#define OPERATE_CMTWORK 35 +#define OPERATE_ENDWORK 36 +#define OPERATE_EXEEXIT 99 + +#define OPERATE_DEFAULT (OPERATE_SELECT | OPERATE_UPDATE | OPERATE_DELETE | OPERATE_INSERT) +/************************************************************************************************* + Internal definition + *************************************************************************************************/ +#define SYS_TVM_INDEX 0x01 +#define SYS_TVM_FIELD 0x02 // field table +#define SYS_TVM_DOMAIN 0x03 // domain table +#define SYS_TVM_SEQUE 0x04 +#define TVM_MAX_TABLE 0xFF // maximum number of creation of the system + +#define MAX_STRIG_LEN 256 + +#ifndef MAX_INDEX_LEN +#define MAX_INDEX_LEN 64 +#endif + +#define MAX_FIELD_LEN 32 // maxinum length of Field name + +#ifndef MAX_FILED_NUM +#define MAX_FILED_NUM 32 // maximum number of fields in a table +#endif + +#define MAX_REMOTE_IP 20 +#define MAX_TIMESTAMP 20 +#define MAX_FILED_IDX 8 + +// resource flag +#define RES_LOCAL_SID 1 +#define RES_REMOT_SID 2 +#define RESOURCE_ROFF 5 +#define RESOURCE_AUTH 4 +#define RESOURCE_EXCP 3 +#define RESOURCE_ABLE 2 +#define RESOURCE_STOP 1 +#define RESOURCE_INIT 0 + +#define IPC_MSG 0x01 +#define IPC_SEM 0x02 +#define IPC_SHM 0x03 + +#define SEM_INIT 1 +#define SEM_O_V 1 // Semaphore V operation +#define SEM_O_P -1 // Semaphore P operation +#define SEM_RD 0 +#define SEM_WD 1 + +#define UNQIUE 1 +#define NORMAL 16 +#define HASHID 32 + +#define TYPE_SYSTEM 0x01 +#define TYPE_INCORE 0x02 +#define TYPE_CLIENT 0x03 // custom +#define TYPE_KEYVAL 0x04 +#define TVM_NODE_INFO "localhost" +#define TVM_RUNCFG_TAG "\x01\x33\xC8\x48" + +#define TVM_BOOT_CLUSTER 2 +#define TVM_BOOT_LOCAL 1 +#define TVM_BOOT_SIMPLE 0 + + +#define HAVE_INDEX(t) (((TblDef *)pGetTblDef(t))->m_lIType != 0) +#define HAVE_UNIQ_IDX(t) (((TblDef *)pGetTblDef(t))->m_lIType & UNQIUE) +#define HAVE_NORL_IDX(t) (((TblDef *)pGetTblDef(t))->m_lIType & NORMAL) +#define HAVE_HASH_IDX(t) (((TblDef *)pGetTblDef(t))->m_lIType & HASHID) + +#define IS_RED(x) (x->m_eColor == COLOR_RED) +#define FPOS(t, f) ((size_t)&((t *)0)->f) +#define FLEN(t, f) (sizeof(((t *)0)->f)) +#define NODE_NULL g_lNilOfs +#define ReField(t, f) (FPOS(t, f) << 16 | FLEN(t, f)) +#define REFrom(t) (t >> 16) +#define REFLen(t) (t & 0xffff) + +#define WORK_ERROR_LOG "work.err" +#define STVM_SQL_LINE ".stvmrc" +#define COLOR_BLK 0 +#define COLOR_RED 1 +#define SELF_POS_UNUSE 0 +#define DATA_TRUCK_NULL 0x00 +#define DATA_TRUCK_NRML 0x01 +#define DATA_TRUCK_LOCK 0x02 +#define TABLE_LOCK_READ 1 +#define TABLE_LOCK_WRITE 2 +#define IS_TRUCK_NULL(p) ((p)->m_chTag == DATA_TRUCK_NULL) +#define IS_TRUCK_NRML(p) ((p)->m_chTag == DATA_TRUCK_NRML) +#define IS_TRUCK_LOCK(p) ((p)->m_chTag == DATA_TRUCK_LOCK) +#define SET_DATA_TRUCK(p, type) ((p)->m_chTag = type) +#define TFree(p) if(p) { free(p); p = NULL; } +#define TFgrp(p) do{vDeleteRowgrp(p);p = NULL;}while(0); +#define TFlst(p) do{vDestroyList(p);p = NULL;}while(0); +#define TClose(f) if(f) { fclose(f); f = NULL; } + +/************************************************************************************************* + 错误码定义区 + *************************************************************************************************/ +#define TVM_DONE_SUCC 0 // completed successfully +#define SVR_EXCEPTION 1 // sever exception +#define IDX_FIELD_NIL 2 // index field values is null +#define CONDIT_IS_NIL 3 // condition is null +#define DATA_SPC_FULL 4 // no space for create data +#define GENER_KEY_ERR 5 // generate shm key failure +#define SHM_ERR_INVAL 6 // Invalid parameter or shm has disappeared +#define SHM_ERR_EXIST 7 // shared memory already exists +#define SHM_ERR_EIDRM 8 // shared memory has been deleted +#define SHM_ERR_ACCES 9 // Permission denied +#define SHM_ERR_NOMEM 10 // Insufficient(shm) core memory +#define VER_NOT_MATCH 11 // data truck version mismatch +#define BLCK_SIZE_ERR 12 // size is error to creat data block +#define IDX_DEF_SPILL 13 // unique Index definition overflow +#define IDX_LEN_SPILL 14 // unique Index length overflow +#define GRP_DEF_SPILL 15 // normal Index definition overflow +#define GRP_LEN_SPILL 16 // normal Index length overflow +#define IDX_TYP_NODEF 17 // index type not define +#define FLD_DEF_SPILL 18 // field define overflow +#define IDX_DATA_MISM 19 // index data mismatch +#define FTYPE_NOT_DEF 20 // field type not define +#define SHMT_NOT_INIT 21 // memory has not been initialized +#define UNIQ_IDX_REPT 22 // unique index repeat +#define IDX_SPC_SPILL 23 // no space for create index +#define NO_DATA_FOUND 24 // no data be found +#define MORE_ROWS_SEL 25 // more then one records be selected +#define MALLC_MEM_ERR 26 // malloc memory error +#define CURS_IS_INVAL 27 // cursor invalid +#define TABLE_NOT_DEF 28 // table not define +#define FIL_NOT_EXIST 29 // file not exist +#define SEM_CDIT_NULL 30 // semget condition is null +#define SEM_ERR_INVAL 31 // Invalid parameter or sem has disappeared +#define SEM_ERR_EXIST 32 // semaphore already exists +#define SEM_ERR_EIDRM 33 // semaphore has been deleted +#define SEM_ERR_ACCES 34 // Permission denied(sem) +#define SEM_ERR_NOMEM 35 // Insufficient(sem) core memory +#define SEM_ERR_LIMIT 36 // Semaphore value out of limit +#define SQL_SYNTX_ERR 37 // SQL syntax is error +#define SQL_NOT_SUPPT 38 // SQL operation not be supported +#define SQL_TABLE_NIL 39 // SQL no table name be inputted +#define SQL_FIELD_NIL 40 // SQL field is not selected +#define SQL_WHERE_NIL 41 // SQL conditional syntax error +#define SQL_ERR_FIELD 42 // SQL field syntax error +#define SQL_ERR_WHERE 43 // SQL where syntax error +#define TBL_NOT_FOUND 44 // table not found +#define SQL_FAV_MATCH 45 // SQL fields does not match the value +#define LOCK_DORD_ERR 46 // set the read lock failure +#define LOCK_UNRD_ERR 47 // unlock read lock failure +#define LOCK_DOWR_ERR 48 // set the write lock failure +#define LOCK_UNWR_ERR 49 // unlock write lock failure +#define SOCK_CONN_ERR 50 // socket connect failure +#define SOCK_CONN_TMO 51 // socket connect timeout +#define SOCK_ERR_CRTE 52 // create socket failure +#define SOCK_READ_ERR 53 // socket recv failure +#define SOCK_SEND_ERR 54 // socket send failure +#define SOCK_BIND_ERR 55 // socket bind failure +#define SOCK_LSEN_ERR 56 // socket listen failure +#define SOCK_SEND_TMO 57 // socket send timeout +#define SOCK_READ_TMO 58 // socket read timeout +#define SOCK_IO_RESET 59 // socket reset +#define SOCK_COM_EXCP 60 // Socket communication anomaly +#define EPOLL_ADD_ERR 61 // epoll add fd error +#define EPOLL_CRT_ERR 62 // create epoll fd failure +#define EPOLL_DEL_ERR 63 // delete epoll fd failure +#define SOCK_ACPT_ERR 64 // socket accept failure +#define RMT_NOT_SUPPT 65 // SQL remote does not support +#define FILE_NOTFOUND 66 // file not found +#define BOOT_PARM_ERR 67 // boot parameters error +#define BOOT_RELA_ERR 68 // parameters table related error +#define BOOT_VER_ICMP 69 // Incompatible version +#define DOM_NOT_REGST 70 // domain not register +#define DMWORK_NOTSUP 71 // domain work does not support +#define SEQ_NOT_FOUND 72 // sequence does not exist +#define FILE_NOT_RSET 73 // file is not set +#define RECD_TOO_LONG 74 // record data too long +#define RESOU_DISABLE 75 // Resource unavailable +#define MSG_ERR_EXIST 76 // message queue already exists +#define MSG_ERR_ACCES 77 // Permission denied .msg +#define MSG_ERR_NOMEM 78 // Insufficient(msg) core memory +#define MSG_ERR_INVAL 79 // Invalid parameter or msg has disappeared +#define MSG_ERR_FAULT 80 // msg Invalid address +#define MSG_ERR_EIDRM 81 // message queue has been deleted +#define MSG_ERR_E2BIG 82 // message text length is greater than msgsz +#define MSG_ERR_EINTR 83 // Interrupted by signal +#define MSG_ERR_SNDEG 84 // msgsnd queue overrun +#define INI_ERR_CHLDP 85 // initial child process failed +#define FLD_NOT_EXIST 86 // field not exist +#define TBL_ARD_EXIST 87 // table already exist +#define WORK_NOT_OPEN 88 // The transaction has not been opened yet +#define WORK_NOT_REGT 89 // The transaction has not been register +#define DOM_NOT_INITL 90 // domain not initail +#define FIELD_NOT_DEF 91 // table field not define +#define FIELD_NOT_SET 92 // field not set +#define UPDFD_NOT_SET 93 // update field not set +#define EXTRE_SET_ERR 94 // extreme set decorate error +#define GROUP_SET_ERR 95 // group set decorate error + +/************************************************************************************************* + 创建表宏函数 + *************************************************************************************************/ +#define DEFINE(t, n, p, s) TABLE tbl = t; long type = 0; \ + ((TblDef *)pGetTblDef(t))->m_table = t; \ + ((TblDef *)pGetTblDef(t))->m_lReSize = sizeof(s); \ + strncpy(((TblDef *)pGetTblDef(t))->m_szPart, p, MAX_FIELD_LEN); \ + strncpy(((TblDef *)pGetTblDef(t))->m_szTable, n, MAX_FIELD_LEN); \ + ((TblDef *)pGetTblDef(t))->m_lTruck = sizeof(s) + sizeof(SHTruck); + +#define CREATE_IDX(t) type = t; +#define IDX_FIELD(t, f, a) if(RC_SUCC != lAddIdxField(tbl, type, FPOS(t, f), FLEN(t, f), a)) \ + return RC_FAIL; +#define FIELD(t, f, d, a) if(RC_SUCC != lSetTableIdx(tbl, FPOS(t, f), FLEN(t, f), d, a, CHK_SELECT)) \ + return RC_FAIL; +#define FIELU(t, f, d, a) if(RC_SUCC != lSetTableIdx(tbl, FPOS(t, f), FLEN(t, f), d, a, IDX_SELECT)) \ + return RC_FAIL; +#define FIELR(t, f, d, a) if(RC_SUCC != lSetTableIdx(tbl, FPOS(t, f), FLEN(t, f), d, a, RCD_SELECT)) \ + return RC_FAIL; +#define FINISH return RC_SUCC; + +/************************************************************************************************* + Field assignment + *************************************************************************************************/ +#define defineinit(p,s,t) do{ \ + p->stCond.uFldcmp = 0; \ + p->stUpdt.uFldcmp = 0; \ + p->lSize = sizeof(s); \ + p->tblName = t; \ + p->pstVoid = (void *)&(s); \ + }while(0); + +#define insertinit(p,s,t) do{ \ + p->lSize = sizeof(s); \ + p->tblName = t; \ + p->pstVoid = (void *)&(s); \ + }while(0); + +#define conditinit(p,s,t) do{ \ + p->stCond.uFldcmp = 0; \ + p->stUpdt.uFldcmp = 0; \ + p->lSize = sizeof(s); \ + p->tblName = t; \ + p->lFind = 0; \ + memset(&(s), 0, p->lSize); \ + p->pstVoid = (void *)&(s); \ + }while(0); + +#define conditnull(p,d,t) do{ \ + p->stCond.uFldcmp = 0; \ + p->stUpdt.uFldcmp = 0; \ + p->lFind = 0; \ + p->lSize = sizeof(d); \ + p->tblName = t; \ + p->pstVoid = NULL; \ + }while(0); + +#define stringsetv(p,s,f,...) vSetCodField(&p->stCond, sizeof((s).f), (void *)(s).f - (void *)&(s)); \ + snprintf((s).f, sizeof((s).f), __VA_ARGS__); + +#define stringset(p,s,f,v) vSetCodField(&p->stCond, sizeof((s).f), (void *)(s).f - (void *)&(s)); \ + strncpy((s).f, v, sizeof((s).f)); + +#define stringcpy(p,s,f,v) vSetCodField(&p->stCond, sizeof((s).f), (void *)(s).f - (void *)&(s)); \ + memcpy(&(s) + ((void *)(s).f - (void *)&(s)), (void *)v, sizeof((s).f)); + +#define numberset(p,s,f,v) vSetCodField(&p->stCond, sizeof((s).f), (void *)&(s).f - (void *)&(s)); \ + (s).f = v; + +#define decorate(p,d,f,v) vSetDecorate(&p->stUpdt, FLEN(d, f), FPOS(d, f), v); \ + p->lFind = (v) & FIRST_ROW; + +#define stringreset(s,f,v) strncpy((s).f, v, sizeof((s).f)); +#define stringresetv(s,f,...) snprintf((s).f, sizeof((s).f), __VA_ARGS__); +#define stringrecpy(s,f,v) memcpy((s).f, v, sizeof((s).f)); +#define numberreset(s,f,v) (s).f = v; + +// UPDATE Field assignment +#define updateinit(s) memset(&(s), 0, sizeof(s)); + +#define stringupd(p,s,f,v) vSetCodField(&p->stUpdt, sizeof((s).f), (void *)(s).f - (void *)&(s)); \ + strncpy((s).f, v, sizeof((s).f)); + +#define stringupy(p,s,f,v) vSetCodField(&p->stUpdt, sizeof((s).f), (void *)(s).f - (void *)&(s)); \ + memcpy(&(s) + ((void *)(s).f - (void *)&(s)), (void *)v, sizeof((s).f)); + +#define numberupd(p,s,f,v) vSetCodField(&p->stUpdt, sizeof((s).f), (void *)&(s).f - (void *)&(s)); \ + (s).f = v; + +/************************************************************************************************* + Table structure & index definition area + *************************************************************************************************/ +typedef struct __SH_DATA_TRUCK +{ + ulong m_lTimes; + char m_chTag; + char m_pvData[0]; +}SHTruck, *PSHTruck; + +typedef struct __SH_RBTREE +{ + size_t m_lSePos; + char m_szIdx[MAX_INDEX_LEN]; + long m_lIdx; + size_t m_lData; + long m_eColor; + size_t m_lParent; + size_t m_lLeft; + size_t m_lRight; +}SHTree; + +typedef struct __SH_LIST +{ + size_t m_lPos; + size_t m_lNode; + size_t m_lData; + size_t m_lNext; + size_t m_lLast; +}SHList; + +typedef struct __TBL_COM_KEY +{ + long m_lFrom; + long m_lLen; + long m_lAttr; + long m_lIsPk; + char m_szField[MAX_FIELD_LEN]; +}TblKey; + +typedef struct __TBL_HEAD_DEF +{ + RWLock m_rwlock; // rwlock + long m_lGroup; // index group + size_t m_lMaxRow; // maximum support + size_t m_lValid; // number of valid + long m_lIdxLen; // unique index length + size_t m_lNodeNil; // NIL + size_t m_lTreePos; // unique tree position + size_t m_lTreeRoot; // unique tree root + long m_lGrpLen; // index length + size_t m_lGroupPos; // index position + size_t m_lGroupRoot; // index root + size_t m_lListPos; // list position + size_t m_lListOfs; // list offset + size_t m_lData; // data offset + uint m_lIType; // index type + uint m_lIdxUp; // unique index field + TblKey m_stIdxUp[MAX_FILED_IDX]; // unique index + uint m_lGrpUp; // index field + TblKey m_stGrpUp[MAX_FILED_IDX]; // index + size_t m_lTable; // table size + long m_lReSize; // row size + size_t m_lTruck; // truck size + llSEQ m_lExSeQ; // extern sequence + long m_lExtern; // extern table space(standby) + long m_lIdxNum; // Number of fields + TblKey m_stKey[MAX_FILED_NUM]; // fields + TABLE m_table; // table + char m_szTable[MAX_FIELD_LEN]; // table name + char m_szPart[MAX_FIELD_LEN]; // + SHTree m_stNil; +}TblDef; + +static long g_lNilOfs = FPOS(TblDef, m_stNil); + +typedef struct __SQL_FIELD +{ + TblKey m_stKey; + struct __SQL_FIELD *pstNext; +}SQLFld; + +/************************************************************************************************* + TVM engine starts the required table (do not move) + *************************************************************************************************/ +typedef struct __SYS_TVM_INDEX +{ + TABLE m_table; // table + long m_lType; // table type + char m_szTable[MAX_FIELD_LEN]; // table name + char m_szPart[MAX_FIELD_LEN]; // partition name + char m_szOwner[MAX_FIELD_LEN]; // owner + key_t m_yKey; + long m_shmID; // Memory Key + long m_semID; // semaphore key + long m_lPid; // pid + long m_lValid; // valid + long m_lMaxRows; // Table maximum support record number. + long m_lRowSize; // truck size + long m_lLocal; // Local/remote + uint m_lState; // available + long m_lPers; // permissions + char m_szTime[MAX_TIMESTAMP]; // create time +}TIndex; + +typedef struct __SYS_TVM_FIELD +{ + TABLE m_table; // table + long m_lSeq; // filed seq + char m_szOwner[MAX_FIELD_LEN]; // owner + char m_szTable[MAX_FIELD_LEN]; // table name + char m_szField[MAX_FIELD_LEN]; // field name + long m_lAttr; // attr + long m_lFrom; // field from + long m_lLen; // field length + long m_lIsPk; +}TField; + +typedef struct __SYS_TVM_DOMAIN +{ + BSock m_skSock; + TABLE m_table; + TABLE m_mtable; + long m_lLock; + long m_lGroup; + long m_lKeepLive; + long m_lLastTime; + long m_lTimeOut; + long m_lTryMax; + long m_lTryTimes; + long m_lRowSize; + long m_lStatus; // remote domain state + long m_lPers; // perms + long m_lPort; + long m_lRelia; + char m_szIp[MAX_REMOTE_IP]; + char m_szTable[MAX_FIELD_LEN]; + char m_szPart[MAX_FIELD_LEN]; + char m_szOwner[MAX_FIELD_LEN]; +}TDomain; + +typedef struct __SYS_TVM_SEQUE +{ + char m_szSQName[MAX_INDEX_LEN]; // Name of sequence + uint m_uIncrement; +}TSeque; + +/************************************************************************************************* + Operating handle + *************************************************************************************************/ +typedef struct __TBL_FILED_KEY +{ + Uenum uDecorate; + uint uFldpos; + uint uFldlen; +}FdKey; + +typedef struct __TBL_CONDIT_FLD +{ + uint uFldcmp; + FdKey stFdKey[MAX_FILED_NUM]; +}FdCond; + +typedef struct __TVM_WORK +{ + TABLE m_table; + long m_lRowSize; + long m_lOperate; + FdCond m_stCond; + FdCond m_stUpdt; + void *m_pvData; + void *m_pvNew; +}TWork; + +typedef struct __TVM_RUNTIME +{ + void *pstVoid; + uint m_lState; + uint m_lLocal; + long m_shmID; // Memory Key + long m_semID; // semaphore key + long m_lRowSize; // Record block size + bool m_bAttch; // Does it initialize + void *m_pvAddr; + long m_lCurLine; // cursor line + long m_lCurType; // cursor type + void *m_pvCurAddr; // cursor address +}RunTime; + +typedef struct __TVM_OPERATE +{ + size_t lSize; // struck size + Uenum lFind; // find type + Uenum bSearch; // find table type + TABLE tblName; // table + void *pstVoid; // condition + FdCond stCond; + FdCond stUpdt; + + bool m_bWork; // work + bool m_bPrew; // work on or off + bool m_bHold; // memory hold + bool m_bCreat; + CMList *m_pstWork; // work list + uint m_lTimes; + BSock m_skSock; + Uenum m_lEType; + key_t m_yKey; + key_t m_ySey; + key_t m_yMey; + Uenum m_lErrno; + size_t m_lEffect; // effect record line + bool m_bCache; + char m_szMsg[256]; // Custom message + char m_szNode[MAX_FIELD_LEN]; + RunTime stRunTime[TVM_MAX_TABLE]; // table handle +}SATvm; + +typedef struct __TVM_BOOT_PARAM +{ + long m_lMaxTable; + long m_lMaxField; + long m_lMaxDomain; + long m_lMaxSeque; + long m_lBootExec; + long m_lBootPort; + long m_lBootType; + char m_szNode[MAX_FIELD_LEN]; + char m_szLog[MAX_STRIG_LEN]; +}TBoot; + +/************************************************************************************************* + 内部函数 + *************************************************************************************************/ +#ifdef __cplusplus +extern "C" { +#endif +extern char* sGetLog(); +extern char* sGetNode(); +extern void* pGetBoot(); +extern void* pGetSATvm(); +extern long lDefaultBoot(); +extern TBoot* pBootInitial(); +extern size_t lGetTblRow(TABLE t); +extern long lGetPermit(TABLE t); +extern long lGetRowSize(TABLE t); +extern TblDef* pGetTblDef(TABLE t); +extern TblKey* pGetTblIdx(TABLE t); +extern uint lGetIdxNum(TABLE t); +extern uint lGetGrpNum(TABLE t); +extern size_t lGetTblData(TABLE t); +extern size_t lGetListOfs(TABLE t); +extern size_t lGetRowTruck(TABLE t); +extern size_t lGetIdxPos(TABLE t); +extern size_t lGetGrpPos(TABLE t); +extern long lGetFldNum(TABLE t); +extern size_t lGetIdxRoot(TABLE t); +extern long lGetTblGroup(TABLE t); +extern size_t lGetTblValid(TABLE t); +extern TblKey* pGetTblGrp(TABLE t); +extern TblKey* pGetTblKey(TABLE t); +extern RWLock* pGetRWLock(char* pvAddr); +extern void vRedeError(long err, char *s); +extern void* pGetAddr(SATvm *pstSavm, TABLE t); +extern RunTime* pGetRunTime(SATvm *pstSavm, TABLE t); +extern void* pGetNode(void *pvData, size_t lOfs); +extern void* pInitMemTable(SATvm *pstSavm, TABLE t); +extern void* pInitHitTest(SATvm *pstSavm, TABLE t); +extern long lTableMaxRow(SATvm *pstSavm, TABLE t); +extern key_t yGetIPCPath(SATvm *pstSavm, Benum em); +extern long lGetBootConfig(SATvm *pstSavm, TBoot *pstBoot); +extern long lAddIdxField(TABLE, long, long, long, long); +extern long lSetTableIdx(TABLE, long, long, char*, long, long); +extern long lUpdIndexPart(SATvm *pstSavm, TABLE t, char *pszPart); +extern TblKey* pFindField(TblKey *pstIdx, long lNum, char *pszField); +extern long lGetTblField(TABLE t, size_t *plOut, TField **ppstField); +extern void vSetCodField(FdCond *pstCond, uint ulen, uint uPos); +extern bool bSetCondAttr(FdCond *pstCond, TABLE t, Uenum eCheck); +extern void vSetDecorate(FdCond *pstCond, uint ulen, uint uPos, Uenum em); +extern long lGetDomainIndex(SATvm *pstSavm, long *plOut, TIndex **ppstIndex); +extern long lGetDomainTable(SATvm *pstSavm, long *plOut, TDomain **ppstDomain); +extern long lGetLocalIndex(SATvm *pstSavm, long *plOut, TIndex **ppstIndex); +extern long lGetTblIndex(SATvm *pstSavm, char *pszTable, char *pszPart, TIndex *pstIndex); + +/************************************************************************************************* + config make&unmake + *************************************************************************************************/ +extern long lUnmakeConfig(char *pszFile); +extern long lMakeConfig(char *pszFile); + +/************************************************************************************************* + IPC Message and semaphore + *************************************************************************************************/ +extern long lGetQueueNum(SATvm *pstSavm, long lQid); +extern long lQueueMaxByte(SATvm *pstSavm, long lQid); +extern long lQueueRcvTime(SATvm *pstSavm, long lQid); +extern long lCreateQueue(SATvm *pstSavm, bool bCreate); +extern long lOperateSems(SATvm *pstSavm, long semID, long lSems, Benum evp); +extern long lEventWrite(SATvm *pstSavm, long lQid, void *psvData, long lSize); +extern long lCreateSems(SATvm *pstSavm, RunTime *pstRun, long lSems, long lValue); +extern long lEventRead(SATvm *pstSavm, long lQid, void *pstVoid, long lSize, long lMType); +extern long lReadNoWait(SATvm *pstSavm, long lQid, void *psvVoid, long lSize, long lMType); + +/************************************************************************************************* + api + *************************************************************************************************/ +extern long lShutdownTvm(); +extern long lStartupTvm(TBoot *pstBoot); + +extern char* sGetUpdTime(); +extern long lGetTErrno(); +extern void vSetTvmMsg(SATvm *pstSavm, char *fmt, ...); +extern char* sGetTvmMsg(SATvm *pstSavm); +extern void vSetTErrno(long err); +extern char* sGetTError(long err); +extern size_t lGetEffect(); +extern bool bIsTvmBoot(); +extern void* pInitSATvm(TABLE t); +extern long lInitSvCache(SATvm *pstSavm); +extern void vInitSATvm(SATvm *pstSavm); +extern bool bTableIsExist(TABLE t); +extern bool bPartIsExist(char *pszTable, char *pszPart); +extern long lInitSATvm(SATvm *pstSavm, TABLE t); +extern void* pPartSatvm(SATvm *pstSavm, char *pszTable, char *pszPart); + +extern long lResetLock(SATvm *pstSavm, TABLE t); +extern long lRebuildIndex(SATvm *pstSavm, TABLE t); +extern void vHoldConnect(SATvm *pstSavm); +extern void vHoldRelease(SATvm *pstSavm); +extern void vTblDisconnect(SATvm *pstSamo, TABLE t); +extern void vForceDisconnect(SATvm *pstSamo, TABLE t); +extern void vBeginWork(SATvm *pstSavm); +extern void vEndWork(SATvm *pstSavm); +extern long lCommitWork(SATvm *pstSavm); +extern long lRollbackWork(SATvm *pstSavm); +extern long lDropTable(SATvm *pstSavm, TABLE t); +extern long lImportFile(TABLE t, char *pszFile, char *pszFlag); +extern long lExportFile(TABLE t, char *pszFile, char *pszFlag); +extern long lImportTable(TABLE t, size_t lCount, void *psvOut); +extern long lExportTable(TABLE t, size_t *plOut, void **ppsvOut); + +extern long lRenameTable(SATvm *pstSavm, TABLE to, TABLE tn); +extern long lCreateSeque(SATvm *pstSavm, char *pszSQName, uint uIncre); +extern long lSelectSeque(SATvm *pstSavm, char *pszSQName, ulong *pulNumber); +extern long lSetSequence(SATvm *pstSavm, char *pszSQName, ulong uStart); +extern long lCustomTable(SATvm *pstSavm, TABLE t, size_t lRow, TblDef *pstDef); +extern long lCreateTable(SATvm *pstSavm, TABLE t, size_t lRow, TCREATE pfCreateFunc); +extern long lInsertTrans(SATvm *pstSavm, size_t *plOffset, llSEQ *pllSeq); + + +extern long lDelete(SATvm *pstSavm); +extern long lInsert(SATvm *pstSavm); +extern long lTruncate(SATvm *pstSavm, TABLE t); +extern long lSelect(SATvm *pstSavm, void *psvOut); +extern long lUpdate(SATvm *pstSavm, void *psvUpd); +extern long lCount(SATvm *pstSavm, size_t *plCount); +extern long lExtreme(SATvm *pstSavm, void *psvOut); +extern long lGroup(SATvm *pstSavm, size_t *plOut, void **ppsvOut); +extern long lQuery(SATvm *pstSavm, size_t *plOut, void **ppsvOut); + +extern long lTableDeclare(SATvm *pstSavm); +extern long lTableFetch(SATvm *pstSavm, void *psvOut); +extern long lNextFetch(SATvm *pstSavm, void **ppvOAddr); +extern void vTableClose(SATvm *pstSavm); +#ifdef __cplusplus +} +#endif + +/************************************************************************************************* + code end + *************************************************************************************************/ +#endif // __TVM_DEFIND_HHHH___ diff --git a/src/conf.c b/src/conf.c new file mode 100644 index 0000000..e9faaf3 --- /dev/null +++ b/src/conf.c @@ -0,0 +1,1271 @@ +/* +* Copyright (c) 2018 Savens Liu +* +* The original has been patented, Open source is not equal to open rights. +* Anyone can clone, download, learn and discuss for free. Without the permission +* of the copyright owner or author, it shall not be merged, published, licensed or sold. +* The copyright owner or author has the right to pursue his responsibility. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "tvm.h" +#include "tmain.h" + +/************************************************************************************************* + global + *************************************************************************************************/ +TBoot g_stBoot = {0}; + +/************************************************************************************************* + description:get the config of boot + parameters: + return: + void* + *************************************************************************************************/ +void* pGetBoot() +{ + return &g_stBoot; +} + +/************************************************************************************************* + description:get log file + parameters: + return: + void* + *************************************************************************************************/ +char* pGetLog() +{ + return g_stBoot.m_szLog; +} + +/************************************************************************************************* + description:Get the current node + parameters: + return: + void* + *************************************************************************************************/ +char* sGetNode() +{ + return g_stBoot.m_szNode; +} + +/************************************************************************************************* + description:Set the current node + parameters: + return: + *************************************************************************************************/ +void vSetNode(char *s) +{ + if(!s) return ; + strncpy(g_stBoot.m_szNode, s, sizeof(g_stBoot.m_szNode)); +} + +/************************************************************************************************* + description:Set STVM boot type + parameters: + return: + *************************************************************************************************/ +void vSetBootType(long lType) +{ + g_stBoot.m_lBootType = lType; +} + +/************************************************************************************************* + description:Get current type of boot + parameters: + return: + lBootType + *************************************************************************************************/ +long lGetBootType() +{ + return g_stBoot.m_lBootType; +} + +/************************************************************************************************* + 函数说明:获取配置日志名称 + 参数说明: + 返回值: + void --日志名 + *************************************************************************************************/ +char* sGetLog() +{ + return g_stBoot.m_szLog; +} + +/************************************************************************************************* + description:create default config + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lDefaultBoot() +{ + FILE *fp = NULL; + char szPath[512]; + TBoot *pstBoot = (TBoot *)pGetBoot(); + + memset(szPath, 0, sizeof(szPath)); + memset(pstBoot, 0, sizeof(TBoot)); + snprintf(szPath, sizeof(szPath), "%s", getenv("TVMCFG")); + + pstBoot->m_lMaxTable = 255; + pstBoot->m_lMaxField = 3000; + pstBoot->m_lMaxDomain = 1024; + pstBoot->m_lMaxSeque = 1024; + pstBoot->m_lBootExec = get_nprocs(); + pstBoot->m_lBootPort = 2000; + pstBoot->m_lBootType = TVM_BOOT_SIMPLE; + strcpy(pstBoot->m_szNode, "STVM"); + strcpy(pstBoot->m_szLog, "stvm.log"); + + if(NULL == (fp = fopen(szPath, "wb"))) + { + fprintf(stderr, "create default param failed, %s\n", strerror(errno)); + return RC_FAIL; + } + + fwrite(TVM_RUNCFG_TAG, 4, 1, fp); + fwrite(pstBoot, sizeof(TBoot), 1, fp); + fclose(fp); + + return RC_SUCC; +} + +/************************************************************************************************* + description:from the config to boot system + parameters: + pstSavm --stvm handle + pstBoot --boot paramer + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lGetBootConfig(SATvm *pstSavm, TBoot *pstBoot) +{ + FILE *fp = NULL; + char szPath[512], szVersion[10]; + + if(!pstSavm || !pstBoot) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + memset(szPath, 0, sizeof(szPath)); + memset(szVersion, 0, sizeof(szVersion)); + snprintf(szPath, sizeof(szPath), "%s", getenv("TVMCFG")); + if(NULL == (fp = fopen(szPath, "rb"))) + { + pstSavm->m_lErrno = FILE_NOTFOUND; + return RC_FAIL; + } + + fread(szVersion, 4, 1, fp); + if(memcmp(szVersion, TVM_RUNCFG_TAG, 4)) + { + fclose(fp); + pstSavm->m_lErrno = BOOT_VER_ICMP; + return RC_FAIL; + } + + fread(pstBoot, sizeof(TBoot), 1, fp); + fclose(fp); + + return RC_SUCC; +} + +/************************************************************************************************* + description: Startup initialization + parameters: + return: + void * + *************************************************************************************************/ +TBoot* pBootInitial() +{ + static int i = 0; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + if(1 == i ++) return &g_stBoot; + + memset(&g_stBoot, 0, sizeof(TBoot)); + + pstSavm->m_lErrno = TVM_DONE_SUCC; + lGetBootConfig(pstSavm, &g_stBoot); + + return &g_stBoot; +} + +/************************************************************************************************* + description:from the config to initial table index + parameters: + pstSavm --stvm handle + plOut --number + ppstIndex --out of index group + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lGetLocalIndex(SATvm *pstSavm, long *plOut, TIndex **ppstIndex) +{ + FILE *fp = NULL; + char szPath[512], szVersion[10]; + + if(!pstSavm || !ppstIndex || !plOut) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + memset(szPath, 0, sizeof(szPath)); + memset(szVersion, 0, sizeof(szVersion)); + snprintf(szPath, sizeof(szPath), "%s", getenv("TVMCFG")); + if(NULL == (fp = fopen(szPath, "rb"))) + { + pstSavm->m_lErrno = FILE_NOTFOUND; + return RC_FAIL; + } + + fread(szVersion, 4, 1, fp); + if(memcmp(szVersion, TVM_RUNCFG_TAG, 4)) + { + fclose(fp); + pstSavm->m_lErrno = BOOT_VER_ICMP; + return RC_FAIL; + } + + fseek(fp, sizeof(TBoot), SEEK_CUR); + fread((void *)plOut, sizeof(long), 1, fp); + if(*plOut <= 0) + { + fclose(fp); + return RC_SUCC; + } + + if(NULL == (*ppstIndex = (void *)calloc(*plOut, sizeof(TIndex)))) + { + fclose(fp); + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + fread(*ppstIndex, (*plOut) * sizeof(TIndex), 1, fp); + fclose(fp); + + return RC_SUCC; +} + +/************************************************************************************************* + description:from the config to initial domain + parameters: + pstSavm --stvm handle + plOut --number + ppstIndex --out of index group + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lGetDomainIndex(SATvm *pstSavm, long *plOut, TIndex **ppstIndex) +{ + FILE *fp = NULL; + char szPath[512], szVersion[10]; + + if(!pstSavm || !ppstIndex || !plOut) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + memset(szPath, 0, sizeof(szPath)); + memset(szVersion, 0, sizeof(szVersion)); + snprintf(szPath, sizeof(szPath), "%s", getenv("TVMCFG")); + if(NULL == (fp = fopen(szPath, "rb"))) + { + pstSavm->m_lErrno = FILE_NOTFOUND; + return RC_FAIL; + } + + fread(szVersion, 4, 1, fp); + if(memcmp(szVersion, TVM_RUNCFG_TAG, 4)) + { + fclose(fp); + pstSavm->m_lErrno = BOOT_VER_ICMP; + return RC_FAIL; + } + + fseek(fp, sizeof(TBoot), SEEK_CUR); + fread((void *)plOut, sizeof(long), 1, fp); + if(*plOut <= 0) + { + fclose(fp); + return RC_SUCC; + } + + fseek(fp, (*plOut) * sizeof(TIndex), SEEK_CUR); + fread((void *)plOut, sizeof(long), 1, fp); + if(NULL == (*ppstIndex = (void *)calloc(*plOut, sizeof(TIndex)))) + { + fclose(fp); + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + fread(*ppstIndex, (*plOut) * sizeof(TIndex), 1, fp); + fclose(fp); + + return RC_SUCC; +} + +/************************************************************************************************* + description:from the config to initial table of domain + parameters: + pstSavm --stvm handle + plOut --number + ppstIndex --out of index group + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lGetDomainTable(SATvm *pstSavm, long *plOut, TDomain **ppstDomain) +{ + FILE *fp = NULL; + char szPath[512], szVersion[10]; + + if(!pstSavm || !ppstDomain || !plOut) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + memset(szPath, 0, sizeof(szPath)); + memset(szVersion, 0, sizeof(szVersion)); + snprintf(szPath, sizeof(szPath), "%s", getenv("TVMCFG")); + if(NULL == (fp = fopen(szPath, "rb"))) + { + pstSavm->m_lErrno = FILE_NOTFOUND; + return RC_FAIL; + } + + fread(szVersion, 4, 1, fp); + if(memcmp(szVersion, TVM_RUNCFG_TAG, 4)) + { + fclose(fp); + pstSavm->m_lErrno = BOOT_VER_ICMP; + return RC_FAIL; + } + + fseek(fp, sizeof(TBoot), SEEK_CUR); + fread((void *)plOut, sizeof(long), 1, fp); + fseek(fp, (*plOut) * sizeof(TIndex), SEEK_CUR); + fread((void *)plOut, sizeof(long), 1, fp); + fseek(fp, (*plOut) * sizeof(TIndex), SEEK_CUR); + fread((void *)plOut, sizeof(long), 1, fp); + if(*plOut <= 0) + { + fclose(fp); + return RC_SUCC; + } + + if(NULL == (*ppstDomain = (void *)calloc(*plOut, sizeof(TDomain)))) + { + fclose(fp); + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + fread(*ppstDomain, (*plOut) * sizeof(TDomain), 1, fp); + fclose(fp); + + return RC_SUCC; +} + +/************************************************************************************************* + description:parse config field + parameters: + pszBuffer --file content + pszTarg --target + nTarg --target length + pszValue --The label value + nValue --value max length + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lPraseField(char *pszBuffer, char *pszTarg, long nTarg, char *pszValue, long nValue) +{ + char szAttr[512]; + + memset(szAttr, 0, sizeof(szAttr)); + strncpy(szAttr, pszBuffer, sizeof(szAttr)); + if(!strstr(szAttr, "=")) + { + fprintf(stdout, "%s\n*may be lost '='\n", szAttr); + return RC_FAIL; + } + + strncpy(pszTarg, sgetvalue(szAttr, "=", 1), nTarg); + strncpy(pszValue, sgetvalue(szAttr, "=", 2), nValue); + srtrim(pszTarg); + sltrim(pszValue); + strimabout(pszValue, "\"", "\""); + if(!strlen(pszValue)) + { + fprintf(stdout, "%s\n*config error, The initial value is not set\n", szAttr); + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:from the config to initial table index + parameters: + pstSavm --stvm handle + ppstRoot --content list + pszFile --config file + pszTarge --target + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lParseFile(SATvm *pstSavm, CMList **ppstRoot, char *pszFile, const char *pszTarget) +{ + FILE *fp = NULL; + char szLine[4098]; + BOOL bFlag = FALSE; + CMList *pstList = NULL; + + if(NULL == (fp = fopen(pszFile, "rb"))) + { + pstSavm->m_lErrno = FILE_NOTFOUND; + return RC_FAIL; + } + + memset(szLine, 0, sizeof(szLine)); + while(fgets(szLine, sizeof(szLine), fp)) + { + strimcrlf(szLine); + sltrim(szLine); + srtrim(szLine); + if(!strlen(szLine)) + continue; + + if('#' == szLine[0] || !memcmp("//", szLine, 2) || !memcmp("/*", szLine, 2) || + !memcmp("#", szLine, 2) || !memcmp("--", szLine, 2)) + continue; + + if(!strcmp(pszTarget, szLine) && !bFlag) + { + bFlag = TRUE; + memset(szLine, 0, sizeof(szLine)); + continue; + } + else if(szLine[0] == '*' && bFlag) + break; + + if(!bFlag) + { + memset(szLine, 0, sizeof(szLine)); + continue; + } + + if(NULL == (pstList = pInsertList(pstList, (void *)szLine, sizeof(szLine)))) + { + fclose(fp); + vDestroyList(pstList); + return RC_FAIL; + } + } + + fclose(fp); + *ppstRoot = pstList; + + return RC_SUCC; +} + +/************************************************************************************************* + description:parse STVM boot parameter + parameters: + pstSavm --stvm handle + pszFile --config file + pstBoot --target + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lParseBoot(SATvm *pstSavm, char *pszFile, TBoot *pstBoot) +{ + char szTarg[128], szValue[64]; + CMList *pstNode = NULL, *pstRoot = NULL; + + if(RC_SUCC != _lParseFile(pstSavm, &pstRoot, pszFile, "*GLOBLE")) + { + fprintf(stderr, "parse file, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + for(pstNode = pstRoot; pstNode; pstNode = pstNode->pstNext) + { + memset(szTarg, 0, sizeof(szTarg)); + memset(szValue, 0, sizeof(szValue)); + if(RC_SUCC != lPraseField((char *)pstNode->m_psvData, szTarg, sizeof(szTarg), szValue, + sizeof(szValue))) + goto PBOOT_ERROR; + + if(!strcasecmp(szTarg, "MACHINE")) + strncpy(pstBoot->m_szNode, szValue, sizeof(pstBoot->m_szNode)); + else if(!strcasecmp(szTarg, "LOGNAME")) + strncpy(pstBoot->m_szLog, szValue, sizeof(pstBoot->m_szLog)); + else if(!strcasecmp(szTarg, "DEPLOY")) + { + if(!strcasecmp(szValue, "cluster")) + pstBoot->m_lBootType = TVM_BOOT_CLUSTER; + else if(!strcasecmp(szValue, "local")) + pstBoot->m_lBootType = TVM_BOOT_LOCAL; + else // local + pstBoot->m_lBootType = TVM_BOOT_SIMPLE; + } + else if(!strcasecmp(szTarg, "MAXTABLE")) + { + pstBoot->m_lMaxTable = atol(szValue); + if(pstBoot->m_lMaxTable <= 5) + { + fprintf(stdout, "%s\n*Set STVM maximum support table number error\n", + (char *)pstNode->m_psvData); + } + else if(pstBoot->m_lMaxTable > 255) + { + fprintf(stdout, "%s\n*STVM maximum support table 255\n", + (char *)pstNode->m_psvData); + goto PBOOT_ERROR; + } + } + else if(!strcasecmp(szTarg, "MAXFILED")) + { + pstBoot->m_lMaxField = atol(szValue); + if(pstBoot->m_lMaxField <= 100) + { + fprintf(stdout, "%s\n*Set the number of STVM field details error\n", + (char *)pstNode->m_psvData); + goto PBOOT_ERROR; + } + } + else if(!strcasecmp(szTarg, "MAXDOMAIN")) + { + pstBoot->m_lMaxDomain = atol(szValue); + if(pstBoot->m_lMaxDomain <= 0) + { + fprintf(stdout, "%s\n*Error in setting maximum number of domain\n", + (char *)pstNode->m_psvData); + goto PBOOT_ERROR; + } + } + else if(!strcasecmp(szTarg, "MAXSEQUE")) + { + pstBoot->m_lMaxSeque = atol(szValue); + if(pstBoot->m_lMaxSeque <= 0) + { + fprintf(stdout, "%s\n*Error in setting maximum number of sequences\n", + (char *)pstNode->m_psvData); + goto PBOOT_ERROR; + } + } + else if(!strcasecmp(szTarg, "SERVER_EXEC")) + { + pstBoot->m_lBootExec = atol(szValue); + if(pstBoot->m_lBootExec <= 0) + { + fprintf(stdout, "%s\n*LIS.tvm: startup number set error", + (char *)pstNode->m_psvData); + goto PBOOT_ERROR; + } + } + else if(!strcasecmp(szTarg, "SERVER_PORT")) + { + pstBoot->m_lBootPort = atol(szValue); + if(pstBoot->m_lBootPort <= 0) + { + fprintf(stdout, "%s\n*LIS.tvm: Error starting port setting\n", + (char *)pstNode->m_psvData); + goto PBOOT_ERROR; + } + } + else + { + fprintf(stdout, "%s\n*Invalid parameter\n", (char *)pstNode->m_psvData); + goto PBOOT_ERROR; + } + } + + if(!strlen(pstBoot->m_szNode)) + { + fprintf(stdout, "MACHINE\n*The local node is not set\n"); + goto PBOOT_ERROR; + } + + if(pstBoot->m_lMaxTable <= 0) + pstBoot->m_lMaxTable = TVM_MAX_TABLE; + if(pstBoot->m_lMaxField <= 0) + pstBoot->m_lMaxField = 3000; + if(pstBoot->m_lMaxDomain <= 0) + pstBoot->m_lMaxDomain = 500; + if(pstBoot->m_lMaxSeque <= 0) + pstBoot->m_lMaxSeque = 500; + if(pstBoot->m_lBootExec <= 0) + pstBoot->m_lBootExec = get_nprocs() > 0 ? get_nprocs() : 1; + if(pstBoot->m_lBootPort <= 0) + pstBoot->m_lBootPort = TVM_PORT_LISTEN; + + vDestroyList(pstRoot); + + return RC_SUCC; + +PBOOT_ERROR: + vDestroyList(pstRoot); + return RC_FAIL; +} + +/************************************************************************************************* + description:get config domain resource + parameters: + lDomain --number of domain + pstDomain --domain group + pszDomain --domain + return: + void* --domain + *************************************************************************************************/ +TDomain* pGetResourse(long lDomain, TDomain *pstDomain, char *pszDomain) +{ + long i = 0; + + for(i = 0; i < lDomain; i ++) + { + if(!strcmp(pstDomain[i].m_szOwner, pszDomain)) + return &pstDomain[i]; + } + + return NULL; +} + +/************************************************************************************************* + description:parse local table config + parameters: + pstSavm --stvm handle + pszFile --config + plOut --number + ppstIndex --out of index group + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lParseIndex(SATvm *pstSavm, char *pszFile, long *plOut, TIndex **ppstIndex) +{ + long i, j, n; + TIndex *pstIndex = NULL; + CMList *pstNode = NULL, *pstRoot = NULL; + char szTarg[128], szValue[64], szAttr[1024]; + + memset(szTarg, 0, sizeof(szTarg)); + memset(szAttr, 0, sizeof(szAttr)); + memset(szValue, 0, sizeof(szValue)); + if(RC_SUCC != _lParseFile(pstSavm, &pstRoot, pszFile, "*LOCAL_RESOURCE")) + { + fprintf(stderr, "parse file, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + for(pstNode = pstRoot, j = 0; pstNode; pstNode = pstNode->pstNext) + { + sfieldreplace((char *)pstNode->m_psvData, '\t', ' '); + if(!strlen((char *)pstNode->m_psvData)) continue; + + if(NULL == (pstIndex = (TIndex *)realloc(pstIndex, (++ j) * sizeof(TIndex)))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + memset(&pstIndex[j - 1], 0, sizeof(TIndex)); + for(i = 0, n = lfieldnum((char *)pstNode->m_psvData, " "); i < n; i ++) + { + memset(szTarg, 0, sizeof(szTarg)); + memset(szValue, 0, sizeof(szValue)); + if(RC_SUCC != lPraseField(sfieldvalue((char *)pstNode->m_psvData, " ", i + 1), + szTarg, sizeof(szTarg), szValue, sizeof(szValue))) + goto PINDEX_ERROR; + + if(!strcasecmp(szTarg, "TABLE")) + pstIndex[j - 1].m_table = atol(szValue); + else if(!strcasecmp(szTarg, "PERMIT")) + pstIndex[j - 1].m_lPers = atol(szValue); + else + { + fprintf(stdout, "%s\n*Invalid parameter\n", (char *)pstNode->m_psvData); + goto PINDEX_ERROR; + } + } + + if(pstIndex[j - 1].m_table <= 0) + { + fprintf(stdout, "%s\n*Table setting error\n", (char *)pstNode->m_psvData); + goto PINDEX_ERROR; + } + + if(pstIndex[j - 1].m_lPers <= 0) + pstIndex[j - 1].m_lPers = OPERATE_DEFAULT; + } + *plOut = j; + *ppstIndex = pstIndex; + + vDestroyList(pstRoot); + return RC_SUCC; + +PINDEX_ERROR: + TFree(*ppstIndex); + vDestroyList(pstRoot); + return RC_FAIL; +} + +/************************************************************************************************* + description:parse domain + parameters: + pstSavm --stvm handle + pszFile --config + plCount --number + ppstDom --out of domain group + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lParseResouce(SATvm *pstSavm, char *pszFile, long *plCout, TDomain **ppstDom) +{ + TDomain *pv; + long i, n; + char szTarg[128], szValue[64]; + CMList *pstNode = NULL, *pstRoot = NULL; + + if(RC_SUCC != _lParseFile(pstSavm, &pstRoot, pszFile, "*REMOTE_DOMAIN")) + { + fprintf(stderr, "parse file, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + for(pstNode = pstRoot, *plCout = 0; pstNode; pstNode = pstNode->pstNext) + { + sfieldreplace((char *)pstNode->m_psvData, '\t', ' '); + if(!strlen((char *)pstNode->m_psvData)) continue; + + if(NULL == (*ppstDom = (TDomain *)realloc(*ppstDom, (++ (*plCout)) * sizeof(TDomain)))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + pv = &(*ppstDom)[(*plCout) - 1]; + memset(pv, 0, sizeof(TDomain)); + for(i = 0, n = lfieldnum((char *)pstNode->m_psvData, " "); i < n; i ++) + { + memset(szTarg, 0, sizeof(szTarg)); + memset(szValue, 0, sizeof(szValue)); + if(RC_SUCC != lPraseField(sfieldvalue((char *)pstNode->m_psvData, " ", i + 1), + szTarg, sizeof(szTarg), szValue, sizeof(szValue))) + goto PDOMAIN_ERROR; + + if(!strcasecmp(szTarg, "DOMAINID")) + strncpy(pv->m_szOwner, szValue, sizeof(pv->m_szOwner)); + else if(!strcasecmp(szTarg, "GROUP")) + pv->m_lGroup = atol(szValue); + else if(!strcasecmp(szTarg, "WSADDR")) + { + strncpy(pv->m_szIp, sgetvalue(szValue, ":", 1), sizeof(pv->m_szIp)); + pv->m_lPort = atol(sgetvalue(szValue, ":", 2)); + } + else if(!strcasecmp(szTarg, "TIMTOUT")) + pv->m_lTimeOut = atol(szValue); + else if(!strcasecmp(szTarg, "MAXTRY")) + pv->m_lTryMax = atol(szValue); + else if(!strcasecmp(szTarg, "KEEPALIVE")) + pv->m_lKeepLive = atol(szValue); + } + + if(!strlen(pv->m_szOwner)) + { + fprintf(stdout, "%s\n*域名未设置\n", (char *)pstNode->m_psvData); + goto PDOMAIN_ERROR; + } + + if(!strlen(pv->m_szIp)) + { + fprintf(stdout, "%s\n*域地址未设置\n", (char *)pstNode->m_psvData); + goto PDOMAIN_ERROR; + } + + if(pv->m_lPort <= 0) + { + fprintf(stdout, "%s\n*The domain port is set incorrectly or unset\n", + (char *)pstNode->m_psvData); + goto PDOMAIN_ERROR; + } + + pv->m_lGroup = pv->m_lGroup > 0 ? pv->m_lGroup : 1; + pv->m_lTimeOut = pv->m_lTimeOut > 0 ? pv->m_lTimeOut : 5; + pv->m_lTryMax = pv->m_lTryMax > 0 ? pv->m_lTryMax : 3; + pv->m_lKeepLive= pv->m_lKeepLive > 0 ? pv->m_lKeepLive : 30; + } + TFlst(pstRoot); + return RC_SUCC; + +PDOMAIN_ERROR: + TFree(*ppstDom); + TFlst(pstRoot); + return RC_FAIL; +} + +/************************************************************************************************* + description:parse the table of domain + parameters: + pszNode --node + pszBuffer --content + plOut --number + ppIndx --out of index + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lParseTable(char *pszNode, char *pszBuffer, long *plOut, TIndex **ppIndx) +{ + long i, n; + TIndex *pv = NULL; + char szTarg[128], szValue[64]; + + if(NULL == (*ppIndx = (TIndex *)realloc(*ppIndx, (++ (*plOut)) * sizeof(TIndex)))) + return RC_FAIL; + + pv = &(*ppIndx)[(*plOut) - 1]; + memset(pv, 0, sizeof(TIndex)); + sfieldreplace(pszBuffer, '\t', ' '); + for(i = 0, n = lfieldnum(pszBuffer, " "); i < n; i ++) + { + memset(szTarg, 0, sizeof(szTarg)); + memset(szValue, 0, sizeof(szValue)); + if(RC_SUCC != lPraseField(sfieldvalue(pszBuffer, " ", i + 1), szTarg, sizeof(szTarg), + szValue, sizeof(szValue))) + return RC_FAIL; + + if(!strcasecmp(szTarg, "TABLE")) + pv->m_table = atol(szValue); + else if(!strcasecmp(szTarg, "TABLENAME")) + strncpy(pv->m_szTable, szValue, sizeof(pv->m_szTable)); + else if(!strcasecmp(szTarg, "PART")) + strncpy(pv->m_szPart, szValue, sizeof(pv->m_szPart)); + + if(!strlen(pv->m_szPart)) + strcpy(pv->m_szPart, pszNode); + strcpy(pv->m_szOwner, pszNode); + } + pv->m_lLocal = RES_REMOT_SID; + pv->m_lPers = OPERATE_NULL; + pv->m_lType = TYPE_CLIENT; + strncpy(pv->m_szTime, sGetUpdTime(), sizeof(pv->m_szTime)); + + return RC_SUCC; +} + +/************************************************************************************************* + description:parse domain resource + parameters: + pszBuffer --content + pstIndex --index + pstDom --domain + plDom --number + ppstDom --domain list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lParseDomain(char *pszBuffer, TIndex *pstIndex, TDomain *pstDom, long *plDom, + TDomain **ppstDom) +{ + long i, n; + TDomain *pv = NULL; + char szTarg[128], szValue[64]; + + if(NULL == (*ppstDom = (TDomain *)realloc(*ppstDom, (++ (*plDom)) * sizeof(TDomain)))) + return RC_FAIL; + + pv = &(*ppstDom)[(*plDom) - 1]; + memset(pv, 0, sizeof(TDomain)); + for(i = 0, n = lfieldnum(pszBuffer, " "); i < n; i ++) + { + memset(szTarg, 0, sizeof(szTarg)); + memset(szValue, 0, sizeof(szValue)); + if(RC_SUCC != lPraseField(sfieldvalue(pszBuffer, " ", i + 1), szTarg, sizeof(szTarg), + szValue, sizeof(szValue))) + return RC_FAIL; + + if(!strcasecmp(szTarg, "MTABLE")) + pv->m_mtable = atol(szValue); + else if(!strcasecmp(szTarg, "DOMAINID")) + strncpy(pv->m_szOwner, szValue, sizeof(pv->m_szOwner)); + else + { + fprintf(stdout, "%s\n*Invalid parameter\n", pszBuffer); + return RC_FAIL; + } + } + + pv->m_lTryMax = 0; + pv->m_lLastTime = 0; + pv->m_lStatus = RESOURCE_INIT; + pv->m_table = pstIndex->m_table; + pv->m_lPort = pstDom->m_lPort; + pv->m_lGroup = pstDom->m_lGroup; + pv->m_lKeepLive = pstDom->m_lKeepLive; + pv->m_lTimeOut = pstDom->m_lTimeOut; + pv->m_lTryMax = pstDom->m_lTryMax; + strcpy(pv->m_szIp, pstDom->m_szIp); + strcpy(pv->m_szTable, pstIndex->m_szTable); + strcpy(pv->m_szOwner, pstDom->m_szOwner); + if(!strlen(pv->m_szPart)) + strcpy(pv->m_szPart, pstDom->m_szOwner); + + return RC_SUCC; +} + +/************************************************************************************************* + description:parse domain table of remote + parameters: + pstSavm --stvm handle + pszFile --config + pstBoot --boot paramter + plOut --number of index + ppstIndex --out of index list + plDom --number of domain + ppstDom --out of domain list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lParseRemote(SATvm *pstSavm, char *pszFile, TBoot *pstBoot, long *plOut, TIndex **ppstIndex, + long *plDom, TDomain **ppstDom) +{ + long i, lResource; + TIndex *pv = NULL; + CMList *pstNode = NULL, *pstRoot = NULL; + TDomain *pstRes = NULL, *pstResouce = NULL; + char szTarg[128], szValue[64], *p = NULL; + + if(RC_SUCC != lParseResouce(pstSavm, pszFile, &lResource, &pstResouce)) + return RC_FAIL; + + if(RC_SUCC != _lParseFile(pstSavm, &pstRoot, pszFile, "*REMOTE_TABLE")) + { + fprintf(stderr, "parse file, err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + if(!pstRoot) + { + for(i = 0; i < lResource; i ++) + { + pstResouce[i].m_table = SYS_TVM_INDEX; + pstResouce[i].m_mtable = SYS_TVM_INDEX; + strcpy(pstResouce[i].m_szTable, "SYS_TVM_INDEX"); + strcpy(pstResouce[i].m_szPart, pstResouce[i].m_szOwner); + } + + *plOut = 0; + *ppstIndex = NULL; + *plDom = lResource; + *ppstDom = pstResouce; + return RC_SUCC; + } + else + { + for(pstNode = pstRoot, *plDom = 0, *plOut = 0; pstNode; pstNode = pstNode->pstNext) + { + sfieldreplace((char *)pstNode->m_psvData, '\t', ' '); + if(!strncmp((char *)pstNode->m_psvData, "TABLE", 5)) + { + if(RC_SUCC != lParseTable(pstBoot->m_szNode, (char *)pstNode->m_psvData, + plOut, ppstIndex)) + goto PREMOTE_ERROR; + pv = &(*ppstIndex)[(*plOut) - 1]; + continue; + } + + if(NULL == (p = strstr((char *)pstNode->m_psvData, "DOMAINID"))) + { + fprintf(stderr, "set error:%s\n", (char *)pstNode->m_psvData); + goto PREMOTE_ERROR; + } + + if(NULL == (pstRes = pGetResourse(lResource, pstResouce, + strimabout(sfieldvalue(p, "=", 2), "\"", "\"")))) + { + fprintf(stderr, "No domain (%s) is found\n", sfieldvalue(p, "=", 2)); + goto PREMOTE_ERROR; + } + + if(RC_SUCC != lParseDomain((char *)pstNode->m_psvData, pv, pstRes, plDom, ppstDom)) + { + TFlst(pstRoot); + return RC_FAIL; + } + } + } + TFree(pstResouce); + TFlst(pstRoot); + + return RC_SUCC; + +PREMOTE_ERROR: + TFlst(pstRoot); + TFree(*ppstIndex); + TFree(pstResouce); + return RC_FAIL; +} + +/************************************************************************************************* + description:Domain uniqueness checks + parameters: + lCount --number + pstDomain --domain list + return: + true --repeat + false + *************************************************************************************************/ +BOOL bDomIsRepeat(long lCount, TDomain *pstDomain) +{ + int i, j; + + for(i = 0; i < lCount; i ++) + { + for(j = 0; j < lCount; j ++) + { + if(i == j) continue; + + if(pstDomain[i].m_lPort == pstDomain[j].m_lPort && + !strcmp(pstDomain[i].m_szIp, pstDomain[j].m_szIp) && + !strcmp(pstDomain[i].m_szPart, pstDomain[j].m_szPart) && + !strcmp(pstDomain[i].m_szTable, pstDomain[j].m_szTable)) + { + if(SYS_TVM_INDEX == pstDomain[i].m_table) + { + fprintf(stderr, "*domain(%s)(%s:%ld)repeate\n", pstDomain[i].m_szOwner, + pstDomain[i].m_szIp, pstDomain[i].m_lPort); + } + else + { + fprintf(stderr, "*table(%s)(%s)repeate\n", pstDomain[i].m_szTable, + pstDomain[i].m_szPart); + } + return true; + } + } + } + + return false; +} + +/************************************************************************************************* + description:Compile configuration file + parameters: + pszFile --config file + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lMakeConfig(char *pszFile) +{ + TBoot stBoot; + FILE *fp = NULL; + TIndex *pstIndex = NULL; + TDomain *pstDomain = NULL; + long i, lOut = 0, lCount = 0; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + if(!pszFile || !strlen(pszFile)) + { + fprintf(stderr, "The configuration file is not set\n"); + return RC_FAIL; + } + + if(RC_SUCC != access(pszFile, R_OK | F_OK )) + { + fprintf(stderr, "Insufficient authority(%s), please confirm!!!\n\n", pszFile); + return RC_FAIL; + } + + memset(&stBoot, 0, sizeof(TBoot)); + if(NULL == (fp = fopen(getenv("TVMCFG"), "wb"))) + { + fprintf(stderr, "open (%s) failure, err:(%d)(%s)", getenv("TVMCFG"), + errno, strerror(errno)); + return RC_FAIL; + } + + fwrite(TVM_RUNCFG_TAG, 4, 1, fp); + if(RC_SUCC != lParseBoot(pstSavm, pszFile, &stBoot)) + goto CREATE_ERROR; + + fwrite(&stBoot, sizeof(stBoot), 1, fp); + if(TVM_BOOT_CLUSTER != stBoot.m_lBootType) // 单机部署 + { + fclose(fp); + fprintf(stdout, "create completed successfully!!!\n"); + return RC_FAIL; + } + + if(RC_SUCC != lParseIndex(pstSavm, pszFile, &lOut, &pstIndex)) + goto CREATE_ERROR; + + fwrite(&lOut, sizeof(long), 1, fp); + fwrite(pstIndex, sizeof(TIndex), lOut, fp); + TFree(pstIndex); + + if(RC_SUCC != lParseRemote(pstSavm, pszFile, &stBoot, &lOut, &pstIndex, + &lCount, &pstDomain)) + goto CREATE_ERROR; + + if(bDomIsRepeat(lCount, pstDomain)) + goto CREATE_ERROR; + + fwrite(&lOut, sizeof(long), 1, fp); + if(lOut > 0) + { + fwrite(pstIndex, sizeof(TIndex), lOut, fp); + TFree(pstIndex); + } + + fwrite(&lCount, sizeof(long), 1, fp); + if(lCount > 0) + { + fwrite(pstDomain, sizeof(TDomain), lCount, fp); + TFree(pstDomain); + } + fclose(fp); + + fprintf(stdout, "create completed successfully!!!\n"); + + return RC_SUCC; + +CREATE_ERROR: + TFree(pstDomain); + TFree(pstIndex); + fclose(fp); + return RC_FAIL; +} + +/************************************************************************************************* + description:Decompilate compilation configuration + parameters: + pszFile --config file + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lUnmakeConfig(char *pszFile) +{ + char ch; + TBoot stBoot; + FILE *fp = NULL; + BOOL bf = false; + TIndex *pstIndex = NULL; + TDomain *pstDomain = NULL; + long i, j, lOut = 0, lCount = 0; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + if(RC_SUCC == access(pszFile, F_OK)) + { + fprintf(stderr, "The configuration already exists, Confirm the cover(Y/N)?:"); + ch = getchar(); + if(ch != 'y' && 'Y' != ch) + return RC_SUCC; + } + + if(NULL == (fp = fopen(pszFile, "w"))) + { + fprintf(stderr, "open file error, %s\n", strerror(errno)); + return RC_FAIL; + } + + if(RC_SUCC != lGetBootConfig(pstSavm, &stBoot)) + goto UNMAKE_ERR; + + fprintf(fp, "*GLOBLE\n"); + fprintf(fp, "MACHINE=\"%s\"\n", stBoot.m_szNode); + fprintf(fp, "MAXTABLE=%ld\n", stBoot.m_lMaxTable); + fprintf(fp, "MAXFILED=%ld\n", stBoot.m_lMaxField); + fprintf(fp, "MAXDOMAIN=%ld\n", stBoot.m_lMaxDomain); + fprintf(fp, "MAXSEQUE=%ld\n", stBoot.m_lMaxSeque); + fprintf(fp, "SERVER_EXEC=%ld\n", stBoot.m_lBootExec); + fprintf(fp, "SERVER_PORT=%ld\n", stBoot.m_lBootPort); + fprintf(fp, "LOGNAME=\"%s\"\n\n", stBoot.m_szLog); + + fprintf(fp, "*LOCAL_RESOURCE\n"); + if(RC_SUCC != lGetLocalIndex(pstSavm, &lCount, (void *)&pstIndex)) + goto UNMAKE_ERR; + + for(i = 0; i < lCount; i ++) + fprintf(fp, "TABLE=%d PERMIT=%ld\n", pstIndex[i].m_table, pstIndex[i].m_lPers); + TFree(pstIndex); + + fprintf(fp, "\n*REMOTE_DOMAIN"); + if(RC_SUCC != lGetDomainIndex(pstSavm, &lCount, &pstIndex)) + goto UNMAKE_ERR; + + if(RC_SUCC != lGetDomainTable(pstSavm, &lOut, &pstDomain)) + goto UNMAKE_ERR; + + for(i = 0; i < lCount; i ++) + { + fprintf(fp, "\nTABLE=%d TABLENAME=\"%s\" PART=\"%s\" ", pstIndex[i].m_table, + pstIndex[i].m_szTable, pstIndex[i].m_szPart); + for(j = 0, bf = false; j < lOut; j ++) + { + if(strcmp(pstDomain[j].m_szTable, pstIndex[i].m_szTable) || + strcmp(pstDomain[j].m_szPart, pstIndex[i].m_szPart)) + continue; + + if(!bf) + { + bf = !bf; + fprintf(fp, "GROUP=%ld TIMTOUT=%ld MAXTRY=%ld KEEPALIVE=%ld\n", + pstDomain[j].m_lGroup, pstDomain[j].m_lTimeOut, pstDomain[j].m_lTryMax, + pstDomain[j].m_lKeepLive); + } + + fprintf(fp, "\tDOMAINID=\"%s\" WSADDR=\"%s:%ld\"\n", pstDomain[j].m_szOwner, + pstDomain[j].m_szIp, pstDomain[j].m_lPort); + } + } + TFree(pstIndex); + TFree(pstDomain); + + fclose(fp); + fprintf(stdout, "导出文件(%s)成功,completed successfully!!!\n", pszFile); + + return RC_SUCC; +UNMAKE_ERR: + fclose(fp); + TFree(pstIndex); + TFree(pstDomain); + fprintf(stderr, "get config err:(%d)(%s)\n", pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; +} + +/************************************************************************************************** + code end + **************************************************************************************************/ diff --git a/src/detvm.c b/src/detvm.c new file mode 100644 index 0000000..654dbd1 --- /dev/null +++ b/src/detvm.c @@ -0,0 +1,404 @@ +/* +* Copyright (c) 2018 Savens Liu +* +* The original has been patented, Open source is not equal to open rights. +* Anyone can clone, download, learn and discuss for free. Without the permission +* of the copyright owner or author, it shall not be merged, published, licensed or sold. +* The copyright owner or author has the right to pursue his responsibility. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "tvm.h" + +/************************************************************************************************* + macro + *************************************************************************************************/ +#define DEBUG_HEAD_INFO 1 +#define DEBUG_UNIQ_IDEX 2 +#define DEBUG_GROP_IDEX 4 +#define DEBUG_GROP_LIST 8 +#define DEBUG_DATA_LIST 16 +#define DEBUG_IDEX_TREE 32 +#define DEBUG_IDEX_DATA 64 +#define DEBUG_IDEX_DALL 128 +#define DEBUG_ALLD_INFO (DEBUG_HEAD_INFO|DEBUG_UNIQ_IDEX|DEBUG_GROP_IDEX|DEBUG_GROP_LIST|DEBUG_DATA_LIST) + +/************************************************************************************************* + function + *************************************************************************************************/ +extern void vPrintHex(char *s, long lIdx, bool bf); + +/************************************************************************************************* + description:debug tree node + parameters: + pvData --memory address + pstTree --tree node + return: + *************************************************************************************************/ +void vDebugTree(void *pvData, SHTree *pstTree) +{ + + if(!pvData || !pstTree) return ; + + fprintf(stderr, "DugTree:%p-SePos:[%8ld], Idx(%ld):[%15s](%2ld), Color[%ld], lSePos:[%4ld], " + "lParent[%4ld], left[%4ld], right[%4ld]\n" , (char *)pstTree, (void *)pstTree - pvData, + pstTree->m_lIdx, pstTree->m_szIdx, pstTree->m_lData, pstTree->m_eColor, pstTree->m_lSePos, + pstTree->m_lParent, pstTree->m_lLeft, pstTree->m_lRight); + + if(SELF_POS_UNUSE == pstTree->m_lSePos || NODE_NULL == pstTree->m_lSePos) + return ; + + if(NODE_NULL != pstTree->m_lLeft) + vDebugTree(pvData, (SHTree *)pGetNode(pvData, pstTree->m_lLeft)); + + if(NODE_NULL != pstTree->m_lRight) + vDebugTree(pvData, (SHTree *)pGetNode(pvData, pstTree->m_lRight)); +} + +/************************************************************************************************* + description:debug table + parameters: + pvData --memory address + pstTree --tree node + return: + *************************************************************************************************/ +void vDebugTable(TABLE t, long eType) +{ + long i = 0, j = 0; + RunTime *pstRun = NULL; + TblKey *pstKey = NULL; + SHTree *pstTree = NULL; + SHList *pstList = NULL; + SHTruck *pstTruck = NULL; + TIndex *pstIndex = NULL; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + if(NULL == (pstSavm = (SATvm *)pInitSATvm(t))) + { + fprintf(stderr, "initial table (%d) failed\n", t); + return ; + } + + if(NULL == (pstRun = pInitHitTest(pstSavm, pstSavm->tblName))) + { + fprintf(stderr, "hit test table (%d) failed, err:(%d)(%s)\n", t,pstSavm->m_lErrno, + sGetTError(pstSavm->m_lErrno)); + return ; + } + + if(eType & DEBUG_HEAD_INFO) + { + fprintf(stdout, "\n==========================================TABLE HEAND INFO=============" + "============================\n"); + fprintf(stdout, "TABLE:%d, NAME:%s\tSHTree(%ld),SHList(%ld),TblDef(%ld)\n" + "extern:%ld, Group:%ld, MaxRow:%ld, Valid:%ld, lNodeNil:%ld, lIType:%d, " + "Table:%ld\nIdxLen:%ld, TreePos:%ld, TreeRoot:%ld, GrpLen:%ld, GroupPos:%ld, " + "GroupRoot:%ld\nListPos:%ld, ListOfs:%ld, Data:%ld, ReSize:%ld, Truck:%ld\n", + ((TblDef *)pGetTblDef(t))->m_table, ((TblDef *)pGetTblDef(t))->m_szTable, + sizeof(SHTree), sizeof(SHList), sizeof(TblDef), ((TblDef *)pGetTblDef(t))->m_lExtern, + ((TblDef *)pGetTblDef(t))->m_lGroup, ((TblDef *)pGetTblDef(t))->m_lMaxRow, + ((TblDef *)pGetTblDef(t))->m_lValid, ((TblDef *)pGetTblDef(t))->m_lNodeNil, + ((TblDef *)pGetTblDef(t))->m_lIType, + ((TblDef *)pGetTblDef(t))->m_lTable, ((TblDef *)pGetTblDef(t))->m_lIdxLen, + ((TblDef *)pGetTblDef(t))->m_lTreePos, ((TblDef *)pGetTblDef(t))->m_lTreeRoot, + ((TblDef *)pGetTblDef(t))->m_lGrpLen, ((TblDef *)pGetTblDef(t))->m_lGroupPos, + ((TblDef *)pGetTblDef(t))->m_lGroupRoot, ((TblDef *)pGetTblDef(t))->m_lListPos, + ((TblDef *)pGetTblDef(t))->m_lListOfs, ((TblDef *)pGetTblDef(t))->m_lData, + ((TblDef *)pGetTblDef(t))->m_lReSize, ((TblDef *)pGetTblDef(t))->m_lTruck); + + pstTree = &((TblDef *)pGetTblDef(t))->m_stNil; + fprintf(stdout, ">>NODE_NULL POS:[%8ld], Idx:[%s](%ld)(%ld), Color[%ld], lSePos:[%4ld], lParent[%4ld]" + ", left[%4ld], right[%4ld]\n" , (void *)pstTree - (void *)pGetTblDef(t), pstTree->m_szIdx, + pstTree->m_lIdx, pstTree->m_lData, pstTree->m_eColor, pstTree->m_lSePos, pstTree->m_lParent, + pstTree->m_lLeft, pstTree->m_lRight); + + fprintf(stdout, "==========UNIQ INDEX FIELD=========\n"); + for(i = 0, pstKey = pGetTblIdx(t); i < lGetIdxNum(t); i ++) + { + fprintf(stdout, "From:%4ld, len:%3ld, attr:%ld, IsPk:%ld, field:%s\n", pstKey[i].m_lFrom, + pstKey[i].m_lLen, pstKey[i].m_lAttr, pstKey[i].m_lIsPk, pstKey[i].m_szField); + } + + fprintf(stdout, "==========GROUP INDEX FIELD========\n"); + for(i = 0, pstKey = pGetTblGrp(t); i < lGetGrpNum(t); i ++) + { + fprintf(stdout, "From:%4ld, len:%3ld, attr:%ld, IsPk:%ld, field:%s\n", pstKey[i].m_lFrom, + pstKey[i].m_lLen, pstKey[i].m_lAttr, pstKey[i].m_lIsPk, pstKey[i].m_szField); + } + + fprintf(stdout, "==================== TABLE FIELD ====================\n"); + for(i = 0, pstKey = pGetTblKey(t); i < lGetFldNum(t); i ++) + { + fprintf(stdout, "From:%4ld, len:%3ld, attr:%ld, IsPk:%ld, field:%s\n", pstKey[i].m_lFrom, + pstKey[i].m_lLen, pstKey[i].m_lAttr, pstKey[i].m_lIsPk, pstKey[i].m_szField); + } + } + + if(eType & DEBUG_UNIQ_IDEX) + { + fprintf(stdout, "\n===================================UNIQUE_INDEX=====================" + "==============lValid(%ld)=========================\n", lGetTblValid(t)); + if(eType & DEBUG_IDEX_DALL) + { + for(i = 0; i < lGetTblRow(t); i ++) + { + pstTree = (SHTree *)(pstRun->m_pvAddr + lGetIdxPos(t) + i * sizeof(SHTree)); + vPrintHex(pstTree->m_szIdx, pstTree->m_lIdx, 0); + fprintf(stdout, "NODE:[%ld](%02ld), Idx:[%4s](%ld)(%2ld), Color[%ld], lSePos:[%4ld], " + "lParent[%4ld], left[%4ld], right[%4ld]\n" , (void *)pstTree - pstRun->m_pvAddr, + i, pstTree->m_szIdx, pstTree->m_lIdx, pstTree->m_lData, pstTree->m_eColor, + pstTree->m_lSePos, pstTree->m_lParent, pstTree->m_lLeft, pstTree->m_lRight); + } + } + else + { + for(i = 0; i < lGetTblValid(t); i ++) + { + pstTree = (SHTree *)(pstRun->m_pvAddr + lGetIdxPos(t) + i * sizeof(SHTree)); + if(SELF_POS_UNUSE == pstTree->m_lSePos || NODE_NULL == pstTree->m_lSePos) + continue; + + vPrintHex(pstTree->m_szIdx, pstTree->m_lIdx, 0); + fprintf(stdout, "NODE:[%6ld]->(%02ld), Idx:[%15s](%6ld), Color[%ld], lSePos:[%4ld], " + "lParent[%4ld], left[%4ld], right[%4ld]\n" , (void *)pstTree - pstRun->m_pvAddr, i, + pstTree->m_szIdx, pstTree->m_lData, pstTree->m_eColor, pstTree->m_lSePos, + pstTree->m_lParent, pstTree->m_lLeft, pstTree->m_lRight); + } + } + } + + if(eType & DEBUG_GROP_IDEX) + { + fprintf(stdout, "\n===================================INDEX_GROUP=====================" + "==============Valid:%ld, Group:%ld================\n", lGetTblValid(t), lGetTblGroup(t)); + if(eType & DEBUG_IDEX_DALL) + { + for(i = 0; i < lGetTblRow(t); i ++) + { + pstTree = (SHTree *)(pstRun->m_pvAddr + lGetGrpPos(t) + i * sizeof(SHTree)); + vPrintHex(pstTree->m_szIdx, pstTree->m_lIdx, 0); + fprintf(stdout, "NODE:[%ld](%02ld), Idx:[%4s](%ld)(%2ld), Color[%ld], lSePos:[%4ld]," + " lParent[%4ld], left[%4ld], right[%4ld]\n" , (void *)pstTree - pstRun->m_pvAddr, + i, pstTree->m_szIdx, pstTree->m_lIdx, pstTree->m_lData, pstTree->m_eColor, + pstTree->m_lSePos, pstTree->m_lParent, pstTree->m_lLeft, pstTree->m_lRight); + } + } + else + { + for(i = 0; i < lGetTblValid(t); i ++) + { + pstTree = (SHTree *)(pstRun->m_pvAddr + lGetGrpPos(t) + i * sizeof(SHTree)); + if(SELF_POS_UNUSE == pstTree->m_lSePos || NODE_NULL == pstTree->m_lSePos) + continue; + + vPrintHex(pstTree->m_szIdx, pstTree->m_lIdx, 0); + fprintf(stdout, "NODE:[%ld](%02ld), Idx:[%4s](%ld)(%2ld), Color[%ld], lSePos:[%4ld]," + " lParent[%4ld], left[%4ld], right[%4ld]\n" , (void *)pstTree - pstRun->m_pvAddr, + i, pstTree->m_szIdx, pstTree->m_lIdx, pstTree->m_lData, pstTree->m_eColor, + pstTree->m_lSePos, pstTree->m_lParent, pstTree->m_lLeft, pstTree->m_lRight); + } + } + } + + if(eType & DEBUG_GROP_LIST) + { + fprintf(stdout, "\n=================================INDEX_LIST========================" + "==============Valid(%ld)=============\n", lGetTblValid(t)); + if(eType & DEBUG_IDEX_DALL) + { + for(i = 0, j = lGetListOfs(t); i < lGetTblRow(t); i ++) + { + pstList = (SHList *)(pstRun->m_pvAddr + j + i * sizeof(SHList)); + fprintf(stdout, "LIST:[%8ld][%02ld], lSePos:[%4ld], lData[%8ld], Node[%8ld], " + "Next[%8ld], Last[%8ld]\n" , (void *)pstList - pstRun->m_pvAddr, i, + pstList->m_lPos, pstList->m_lData, pstList->m_lNode, pstList->m_lNext, + pstList->m_lLast); + } + } + else + { + for(i = 0, j = lGetListOfs(t); i < lGetTblValid(t); i ++) + { + pstList = (SHList *)(pstRun->m_pvAddr + j + i * sizeof(SHList)); + if(SELF_POS_UNUSE == pstList->m_lPos) + continue; + + fprintf(stdout, "LIST:[%8ld][%02ld], lSePos:[%4ld], lData[%8ld], Node[%8ld], " + "Next[%8ld], Last[%8ld]\n" , (void *)pstList - pstRun->m_pvAddr, i, + pstList->m_lPos, pstList->m_lData, pstList->m_lNode, + pstList->m_lNext, pstList->m_lLast); + } + } + } + + if(eType & DEBUG_IDEX_TREE) + { + fprintf(stdout, "\n=================================TREE DEUBG========================" + "==============Valid(%ld)=============\n", lGetTblValid(t)); + vDebugTree(pstRun->m_pvAddr, pGetNode(pstRun->m_pvAddr, lGetIdxRoot(t))); + } + + if(eType & DEBUG_IDEX_DATA) + { + fprintf(stdout, "\n===================================UNIQUE_INDEX=====================" + "==============lValid(%ld)=========================\n", lGetTblValid(t)); + for(i = 0; i < lGetTblRow(t); i ++) + { + pstTruck = (void *)(pstRun->m_pvAddr + lGetTblData(t) + i * lGetRowTruck(t)); + fprintf(stdout, "SePos[%ld]\n", (void *)pstTruck - pstRun->m_pvAddr); + vPrintHex(pstTruck->m_pvData, lGetRowSize(t), 0); + } + } + + vTblDisconnect(pstSavm, pstSavm->tblName); + fprintf(stdout, "==========================================================================" + "===================================\n"); +} + +/************************************************************************************************* + description:get action + parameters: + return: + *************************************************************************************************/ +void vGetAction(char *s, long *plAction) +{ + int i, nLen; + + if(!s) return ; + + for(i = 0, nLen = strlen(s); i < nLen; i ++) + { + switch(s[i]) + { + case 'h': + *plAction |= DEBUG_HEAD_INFO; + break; + case 'u': + *plAction |= DEBUG_UNIQ_IDEX; + break; + case 'g': + *plAction |= DEBUG_GROP_IDEX; + break; + case 'l': + *plAction |= DEBUG_GROP_LIST; + break; + case 'd': + *plAction |= DEBUG_DATA_LIST; + break; + case 't': + *plAction |= DEBUG_IDEX_TREE; + break; + case 'e': + *plAction |= DEBUG_IDEX_DALL; + break; + case 'a': + *plAction |= DEBUG_IDEX_DATA; + break; + default: + break; + } + } +} + +/************************************************************************************************* + description:print func + parameters: + return: + *************************************************************************************************/ +void vPrintFunc(char *s) +{ + fprintf(stdout, "\nUsage:\t%s -[tpu][hugldtui]\n", s); + fprintf(stdout, "\t-t\t\t--table\n"); + fprintf(stdout, "\t-p[hugldta]\t--debug\n"); + fprintf(stdout, "\t-u(ui)\t\t--reset lock\n"); + fprintf(stdout, "\n"); +} + +/************************************************************************************************* + description:debug action + parameters: + return: + *************************************************************************************************/ +void vDebugAction(TABLE t, int iAction, char *pszApp, char *pszParam) +{ + long lRet, lDebug = 0; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + if(3 == iAction) + { + if(RC_SUCC != lResetLock((SATvm *)pGetSATvm(), t)) + { + fprintf(stderr, "reset the table lock (%d) failed, err:(%d)(%s)\n", t, + pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return ; + } + } + else if(5 == iAction) + { + vGetAction(pszParam, &lDebug); + vDebugTable(t, lDebug); + } + else + vPrintFunc(pszApp); + + return ; +} + +/************************************************************************************************* + description:main + parameters: + return: + *************************************************************************************************/ +int main(int argc, char *argv[]) +{ + TABLE t; + char szCom[256]; + int iChoose = 0, iAction = 0; + + memset(szCom, 0, sizeof(szCom)); + while(-1 != (iChoose = getopt(argc, argv, "t:p:u::v?::"))) + { + switch(iChoose) + { + case 't': + iAction |= 1; + t = atol(optarg); + break; + case 'u': + if(!optarg) + strcpy(szCom, "u"); + else + strcpy(szCom, optarg); + iAction |= 2; + break; + case 'p': + iAction |= 4; + strcpy(szCom, optarg); + break; + case 'v': + case '?': + default: + vPrintFunc(basename(argv[0])); + return RC_FAIL; + } + } + + vDebugAction(t, iAction, basename(argv[0]), szCom); + + return RC_SUCC; +} + +/************************************************************************************************* + code end + *************************************************************************************************/ diff --git a/src/list.c b/src/list.c new file mode 100644 index 0000000..33e00e9 --- /dev/null +++ b/src/list.c @@ -0,0 +1,1099 @@ +/* +* Copyright (c) 2018 Savens Liu +* +* The original has been patented, Open source is not equal to open rights. +* Anyone can clone, download, learn and discuss for free. Without the permission +* of the copyright owner or author, it shall not be merged, published, licensed or sold. +* The copyright owner or author has the right to pursue his responsibility. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "tmain.h" + +/************************************************************************************************ + function + ************************************************************************************************/ +/************************************************************************************************* + description:get the tailf of list + parameters: + root --list of root + return: + void* + *************************************************************************************************/ +CMList* pGetCMTail(CMList *root) +{ + CMList *list = root; + + if(!list) return NULL; + + while(list->pstNext) + list = list->pstNext; + + return list; +} + +/************************************************************************************************* + description:insert to list + parameters: + return: + root -root node + *************************************************************************************************/ +CMList* pInsertList(CMList *root, void *pszData, long lSize) +{ + CMList *node = NULL, *tail = pGetCMTail(root); + + if(NULL == (node = (CMList *)malloc(sizeof(CMList)))) + { + vSetTErrno(MALLC_MEM_ERR); + return root; + } + + node->m_lSize = lSize; + if(NULL == (node->m_psvData = (char *)malloc(node->m_lSize))) + { + vSetTErrno(MALLC_MEM_ERR); + return root; + } + + node->pstNext = NULL; + node->pstLast = NULL; + memcpy(node->m_psvData, pszData, node->m_lSize); + + if(!root) + root = node; + else + { + node->pstLast = tail; + tail->pstNext = node; + } + + return root; +} + +/************************************************************************************************* + description:find node from the list + parameters: + return: + node --list node + *************************************************************************************************/ +CMList* pSearchNode(CMList *root, void *pv, long n) +{ + CMList *node; + + for(node = root; node; node = node->pstNext) + { + if(!memcmp(node->m_psvData, pv, n)) + return node; + } + + return NULL; +} + +/************************************************************************************************* + description:destroy list + parameters: + root --list root + return: + void* + *************************************************************************************************/ +void vDestroyList(CMList *root) +{ + CMList *node = root, *list = NULL; + + while(node) + { + list = node; + node = node->pstNext; + TFree(list->m_psvData); + TFree(list); + } + + root = NULL; +} + +/************************************************************************************************* + description:delete node + parameters: + root --root node + psvData --node value + lSize --length of value + return: + root --root node + *************************************************************************************************/ +CMList* pDeleteNode(CMList *root, void *psvData, long lSize) +{ + CMList *node = root; + + while(node) + { + if(!memcmp(node->m_psvData, psvData, lSize)) + break; + node = node->pstNext; + } + if(!node) return root; + + if(node->pstNext) + node->pstNext->pstLast = node->pstLast; + + if(!node->pstLast) + root = node->pstNext; + else + node->pstLast->pstNext = node->pstNext; + + TFree(node->m_psvData); + TFree(node); + + return root; +} + +/************************************************************************************************* + description:node number + parameters: + root --root node + return: + long --count the number of list + *************************************************************************************************/ +long lListNodeCount(CMList *root) +{ + long lCount = 0; + CMList *node = root; + + while(node) + { + ++ lCount; + node = node->pstNext; + } + + return lCount; +} + +/************************************************************************************************* + description:Check if rowgrp is repeated + parameters: + pstRrp --field index list + pvData --check data + t --table + lOut --number + psvOut --truck list + return: + true --repeate + false + *************************************************************************************************/ +bool bRepeatLstgrp(FdCond *pstRrp, void *pvData, TABLE t, size_t lOut, void *psvOut) +{ + uint i, j; + FdKey *pstFd; + bool bRepeat = false; + + if(!psvOut || 0 == lOut) return false; + + for(i = 0; i < lOut; i ++) + { + for(j = 0, bRepeat = true; j < pstRrp->uFldcmp; j ++) + { + pstFd = &pstRrp->stFdKey[j]; + if(0 == (GROUP_BY & pstFd->uDecorate)) + continue; + + if(memcmp(psvOut + (i * lGetRowSize(t)) + pstFd->uFldpos, pvData + pstFd->uFldpos, + pstFd->uFldlen)) + bRepeat = false; + } + + if(bRepeat) return bRepeat; + } + + return bRepeat; +} + +/************************************************************************************************* + description:insert group node + parameters: + pstSavm --stvm handle + pstRrp --field index list + pvData --insert data + lOut --number + psvOut --truck list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lInsertLstgrp(SATvm *pstSavm, FdCond *pstRrp, void *pvData, TABLE t, size_t *plOut, + void **ppsvOut) +{ + FdKey *pstFd; + size_t i, lOffset = (*plOut) * lGetRowSize(t); + + if(NULL == (*ppsvOut = (char *)realloc(*ppsvOut, lOffset + lGetRowSize(t)))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + memset(*ppsvOut + lOffset, 0, lGetRowSize(t)); + for(i = 0; i < pstRrp->uFldcmp; i ++) + { + pstFd = &pstRrp->stFdKey[i]; + if(0 == (GROUP_BY & pstFd->uDecorate)) + continue; + + memcpy(*ppsvOut + lOffset + pstFd->uFldpos, pvData + pstFd->uFldpos, pstFd->uFldlen); + } + + (*plOut) ++; + return RC_SUCC; +} + +/************************************************************************************************* + Rowgrp + *************************************************************************************************/ +/************************************************************************************************* + description:get rowgrp tail + parameters: + root --root of rowgrp + return: + void* --tailf of rowgrp + *************************************************************************************************/ +Rowgrp* pRowgrpTail(Rowgrp *root) +{ + Rowgrp *node = root; + + if(!node) return NULL; + + while(node->pstNext) + node = node->pstNext; + + return node; +} + +/************************************************************************************************* + description:free rowgrp list + parameters: + root --root of rowgrp + return: + *************************************************************************************************/ +void vDeleteRowgrp(Rowgrp *root) +{ + Rowgrp *list, *node; + + for(list = root, node = root; NULL != list; node = list) + { + list = list->pstNext; + vDeleteRowgrp(node->pstSSet); + TFree(node->psvData); + TFree(node); + } + + return ; +} + +/************************************************************************************************* + description:delete node from rowgrp + parameters: + root --root of rowgrp + delete --delete node + return: + *************************************************************************************************/ +void vDropNodegrp(Rowgrp **root, Rowgrp *delete) +{ + Rowgrp *list, *node; + + if(!root) return ; + + for(list = *root; NULL != list; ) + { + if(list != delete) + { + list = list->pstNext; + continue; + } + + if(list->pstLast) + list->pstLast->pstNext = list->pstNext; + else + *root = list->pstNext; + + if(list->pstNext) + list->pstNext->pstLast = list->pstLast; + node = list; + list = list->pstNext; + vDeleteRowgrp(node->pstSSet); + TFree(node->psvData); + TFree(node); + } + + return ; +} + +/************************************************************************************************* + description:count rowgrp + parameters: + root --root of rowgrp + pv --data + lLen --data length + lCount --count + return: + long --number of count + *************************************************************************************************/ +long lCountRowgrp(Rowgrp *root, void *pv, long lLen, size_t lCount) +{ + long n; + Rowgrp *node, *list; + + for(node = root; NULL != node; node = node->pstNext) + { + if(!memcmp(node->psvData, pv, lLen)) + { + node->lCount += lCount; + return node->lCount; + } + + if(0 != (n = lCountRowgrp(node->pstSSet, pv, lLen, lCount))) + return n; + } + + return 0; +} + +/************************************************************************************************* + description:insert node from rowgrp + parameters: + pstSavm --stvm handle + root --root of rowgrp + pstFSet --parent node + pstSSet --child node + pv --data + n --length + lCount --count + return: + void* --root of rowgrp + *************************************************************************************************/ +Rowgrp* pInsertRowgrp(SATvm *pstSavm, Rowgrp *root, Rowgrp *pstFset, Rowgrp *pstSSet, void *pv, + long n, size_t lCount) +{ + Rowgrp *node = NULL, *tail = (Rowgrp *)pRowgrpTail(root); + + if(NULL == (node = (Rowgrp *)calloc(1, sizeof(Rowgrp)))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return root; + } + + if(NULL == (node->psvData = (char *)calloc(n + 1, sizeof(char)))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return root; + } + + node->lLen = n; + if(0 == lCount) + node->lCount ++; + else + node->lCount = lCount; + node->pstFset = pstFset; + node->pstSSet = pstSSet; + memcpy(node->psvData, pv, node->lLen); + + if(!root) + { + root = node; + tail = node; + root->lIdx = 0; + return root; + } + + node->lIdx = tail->lIdx + 1; + node->pstLast = tail; + tail->pstNext = node; + tail = node; + + return root; +} + +/************************************************************************************************* + description:get middle of rowgrp + parameters: + root --root of rowgrp + return: + void* --root of rowgrp + *************************************************************************************************/ +Rowgrp* pGetListMid(Rowgrp *root) +{ + Rowgrp *fast = NULL, *slow = NULL; + + if(root == NULL || root->pstNext == NULL) + return NULL; + + for(slow = root, fast = root->pstNext; fast; slow = slow->pstNext) + { + fast = fast->pstNext; + if(NULL == fast) + break; + fast = fast->pstNext; + } + + fast = slow->pstNext; + slow->pstNext = NULL; + return fast; +} + +/************************************************************************************************* + description:Sort list with ASC. + parameters: + root --root of rowgrp + return: + void* --root of rowgrp + *************************************************************************************************/ +Rowgrp* pSortMergeAsc(Rowgrp *pa, Rowgrp *pb, FdKey *pstKey) +{ + Rowgrp *pstRes = NULL; + + if(pa == NULL) + return pb; + else if(pb == NULL) + return pa; + + switch(pstKey->uDecorate & 0x0f) + { + case FIELD_DOUB: + switch(pstKey->uFldlen) + { + case 4: + if(*((float *)(pa->psvData)) < *((float *)(pb->psvData))) + { + pstRes = pa; + pstRes->pstNext = pSortMergeAsc(pa->pstNext, pb, pstKey); + } + else + { + pstRes = pb; + pstRes->pstNext = pSortMergeAsc(pa, pb->pstNext, pstKey); + } + break; + case 8: + if(*((double *)(pa->psvData)) < *((double *)(pb->psvData))) + { + pstRes = pa; + pstRes->pstNext = pSortMergeAsc(pa->pstNext, pb, pstKey); + } + else + { + pstRes = pb; + pstRes->pstNext = pSortMergeAsc(pa, pb->pstNext, pstKey); + } + break; + default: + break; + } + break; + case FIELD_LONG: + switch(pstKey->uFldlen) + { + case 2: + if(*((sint *)(pa->psvData)) < *((sint *)(pb->psvData))) + { + pstRes = pa; + pstRes->pstNext = pSortMergeAsc(pa->pstNext, pb, pstKey); + } + else + { + pstRes = pb; + pstRes->pstNext = pSortMergeAsc(pa, pb->pstNext, pstKey); + } + break; + case 4: + if(*((int *)(pa->psvData)) < *((int *)(pb->psvData))) + { + pstRes = pa; + pstRes->pstNext = pSortMergeAsc(pa->pstNext, pb, pstKey); + } + else + { + pstRes = pb; + pstRes->pstNext = pSortMergeAsc(pa, pb->pstNext, pstKey); + } + break; + case 8: + if(*((llong *)(pa->psvData)) < *((llong *)(pb->psvData))) + { + pstRes = pa; + pstRes->pstNext = pSortMergeAsc(pa->pstNext, pb, pstKey); + } + else + { + pstRes = pb; + pstRes->pstNext = pSortMergeAsc(pa, pb->pstNext, pstKey); + } + break; + default: + break; + } + break; + case FIELD_CHAR: + if(0 < memcmp(pb->psvData, pa->psvData, pstKey->uFldlen)) + { + pstRes = pa; + pstRes->pstNext = pSortMergeAsc(pa->pstNext, pb, pstKey); + } + else + { + pstRes = pb; + pstRes->pstNext = pSortMergeAsc(pa, pb->pstNext, pstKey); + } + break; + default: + break; + } + + if(pstRes->pstNext) pstRes->pstNext->pstLast = pstRes; + + return pstRes; +} + +/************************************************************************************************* + description:Sort list with DESC. + parameters: + root --root of rowgrp + return: + void* --root of rowgrp + *************************************************************************************************/ +Rowgrp* pSortMergeDes(Rowgrp *pa, Rowgrp *pb, FdKey *pstKey) +{ + Rowgrp *pstRes = NULL; + + if(pa == NULL) + return pb; + else if(pb == NULL) + return pa; + + switch(pstKey->uDecorate & 0x0f) + { + case FIELD_DOUB: + switch(pstKey->uFldlen) + { + case 4: + if(*((float *)(pa->psvData)) > *((float *)(pb->psvData))) + { + pstRes = pa; + pstRes->pstNext = pSortMergeDes(pa->pstNext, pb, pstKey); + } + else + { + pstRes = pb; + pstRes->pstNext = pSortMergeDes(pa, pb->pstNext, pstKey); + } + break; + case 8: + if(*((double *)(pa->psvData)) > *((double *)(pb->psvData))) + { + pstRes = pa; + pstRes->pstNext = pSortMergeDes(pa->pstNext, pb, pstKey); + } + else + { + pstRes = pb; + pstRes->pstNext = pSortMergeDes(pa, pb->pstNext, pstKey); + } + break; + default: + break; + } + break; + case FIELD_LONG: + switch(pstKey->uFldlen) + { + case 2: + if(*((sint *)(pa->psvData)) > *((sint *)(pb->psvData))) + { + pstRes = pa; + pstRes->pstNext = pSortMergeDes(pa->pstNext, pb, pstKey); + } + else + { + pstRes = pb; + pstRes->pstNext = pSortMergeDes(pa, pb->pstNext, pstKey); + } + break; + case 4: + if(*((int *)(pa->psvData)) > *((int *)(pb->psvData))) + { + pstRes = pa; + pstRes->pstNext = pSortMergeDes(pa->pstNext, pb, pstKey); + } + else + { + pstRes = pb; + pstRes->pstNext = pSortMergeDes(pa, pb->pstNext, pstKey); + } + break; + case 8: + if(*((llong *)(pa->psvData)) > *((llong *)(pb->psvData))) + { + pstRes = pa; + pstRes->pstNext = pSortMergeDes(pa->pstNext, pb, pstKey); + } + else + { + pstRes = pb; + pstRes->pstNext = pSortMergeDes(pa, pb->pstNext, pstKey); + } + break; + default: + break; + } + break; + case FIELD_CHAR: + if(0 > memcmp(pb->psvData, pa->psvData, pstKey->uFldlen)) + { + pstRes = pa; + pstRes->pstNext = pSortMergeDes(pa->pstNext, pb, pstKey); + } + else + { + pstRes = pb; + pstRes->pstNext = pSortMergeDes(pa, pb->pstNext, pstKey); + } + break; + default: + break; + } + + if(pstRes->pstNext) pstRes->pstNext->pstLast = pstRes; + + return pstRes; +} + +/************************************************************************************************* + description:Sort list by field + parameters: + root --root + pstFd --field + return: + *************************************************************************************************/ +void _vSortField(Rowgrp **root, FdKey *pstFd) +{ + Rowgrp *slow = NULL; + + if(NULL == *root || NULL == (*root)->pstNext) + return; + + slow = pGetListMid(*root); + _vSortField(root, pstFd); + _vSortField(&slow, pstFd); + + if(ORDER_DESC & pstFd->uDecorate) + *root = pSortMergeDes(*root, slow, pstFd); + else + *root = pSortMergeAsc(*root, slow, pstFd); + return ; +} + +/************************************************************************************************* + description:Sort subset + parameters: + root --root + pstFd --field + return: + *************************************************************************************************/ +void vSubsetSort(Rowgrp *root, FdCond *pstExm, uint ug) +{ + Rowgrp *node; + FdKey *pstFd; + + for(node = root, pstFd = &pstExm->stFdKey[ug]; node; node = node->pstNext) + { + if(0 == (pstFd->uDecorate & (ORDER_ASC | ORDER_DESC))) + continue; + + _vSortField(&node->pstSSet, pstFd); + vSubsetSort(node->pstSSet, pstExm, ++ ug); + } + + return ; +} + +/************************************************************************************************* + description:Sort Rowgrp + parameters: + root --root + pstFd --field + t --t + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lSortRowgrp(Rowgrp **root, FdCond *pstExm, TABLE t) +{ + FdKey *pstFd = &pstExm->stFdKey[0]; + + if(!bSetCondAttr(pstExm, t, ORDER_ASC | ORDER_DESC)) + return RC_SUCC; + + if(pstFd->uDecorate & (ORDER_ASC | ORDER_DESC)) + _vSortField(root, pstFd); + vSubsetSort(*root, pstExm, 1); + return RC_SUCC; +} + +/************************************************************************************************* + description:compare data by field + parameters: + s --data + p --to be compared + pstCond --field list + uNice --next index of field + return: + TRUE --success + FALSE --failure + *************************************************************************************************/ +bool bCompare(void *s, void *p, FdCond *pstCond, uint uNice) +{ + FdKey *pstKey; + + if(pstCond->uFldcmp <= uNice) + return TRUE; + + pstKey = &pstCond->stFdKey[uNice]; + if(pstKey->uDecorate & ORDER_ASC) + { + switch(pstKey->uDecorate & 0x0f) + { + case FIELD_DOUB: + switch(pstKey->uFldlen) + { + case 4: + if(*((float *)(s + pstKey->uFldpos)) > *((float *)(p + pstKey->uFldpos))) + return TRUE; + else if(*((float *)(s + pstKey->uFldpos)) == *((float *)(p + pstKey->uFldpos))) + return bCompare(s, p, pstCond, ++ uNice); + else + return FALSE; + case 8: + if(*((double *)(s + pstKey->uFldpos)) > *((double *)(p + pstKey->uFldpos))) + return TRUE; + else if(*((float *)(s + pstKey->uFldpos)) == *((float *)(p + pstKey->uFldpos))) + return bCompare(s, p, pstCond, ++ uNice); + else + return FALSE; + default: + return FALSE; + } + break; + case FIELD_LONG: + switch(pstKey->uFldlen) + { + case 2: + if(*((sint *)(s + pstKey->uFldpos)) > *((sint *)(p + pstKey->uFldpos))) + return TRUE; + else if(*((sint *)(s + pstKey->uFldpos)) == *((sint *)(p + pstKey->uFldpos))) + return bCompare(s, p, pstCond, ++ uNice); + else + return FALSE; + case 4: + if(*((int *)(s + pstKey->uFldpos)) > *((int *)(p + pstKey->uFldpos))) + return TRUE; + else if(*((int *)(s + pstKey->uFldpos)) == *((int *)(p + pstKey->uFldpos))) + return bCompare(s, p, pstCond, ++ uNice); + else + return FALSE; + case 8: + if(*((llong *)(s + pstKey->uFldpos)) > *((llong *)(p + pstKey->uFldpos))) + return TRUE; + else if(*((llong *)(s + pstKey->uFldpos)) == *((llong *)(p + pstKey->uFldpos))) + return bCompare(s, p, pstCond, ++ uNice); + else + return FALSE; + default: + return FALSE; + } + break; + case FIELD_CHAR: + if(0 < memcmp(s + pstKey->uFldpos, p + pstKey->uFldpos, pstKey->uFldlen)) + return TRUE; + else if(0 == memcmp(s + pstKey->uFldpos, p + pstKey->uFldpos, pstKey->uFldlen)) + return bCompare(s, p, pstCond, ++ uNice); + else + return FALSE; + break; + default: + break; + } + } + else if(pstKey->uDecorate & ORDER_DESC) + { + switch(pstKey->uDecorate & 0x0f) + { + case FIELD_DOUB: + switch(pstKey->uFldlen) + { + case 4: + if(*((float *)(s + pstKey->uFldpos)) < *((float *)(p + pstKey->uFldpos))) + return TRUE; + else if(*((float *)(s + pstKey->uFldpos)) == *((float *)(p + pstKey->uFldpos))) + return bCompare(s, p, pstCond, ++ uNice); + else + return FALSE; + case 8: + if(*((double *)(s + pstKey->uFldpos)) < *((double *)(p + pstKey->uFldpos))) + return TRUE; + else if(*((float *)(s + pstKey->uFldpos)) == *((float *)(p + pstKey->uFldpos))) + return bCompare(s, p, pstCond, ++ uNice); + else + return FALSE; + default: + return FALSE; + } + break; + case FIELD_LONG: + switch(pstKey->uFldlen) + { + case 2: + if(*((sint *)(s + pstKey->uFldpos)) < *((sint *)(p + pstKey->uFldpos))) + return TRUE; + else if(*((sint *)(s + pstKey->uFldpos)) == *((sint *)(p + pstKey->uFldpos))) + return bCompare(s, p, pstCond, ++ uNice); + else + return FALSE; + case 4: + if(*((int *)(s + pstKey->uFldpos)) < *((int *)(p + pstKey->uFldpos))) + return TRUE; + else if(*((int *)(s + pstKey->uFldpos)) == *((int *)(p + pstKey->uFldpos))) + return bCompare(s, p, pstCond, ++ uNice); + else + return FALSE; + case 8: + if(*((llong *)(s + pstKey->uFldpos)) < *((llong *)(p + pstKey->uFldpos))) + return TRUE; + else if(*((llong *)(s + pstKey->uFldpos)) == *((llong *)(p + pstKey->uFldpos))) + return bCompare(s, p, pstCond, ++ uNice); + else + return FALSE; + default: + return FALSE; + } + break; + case FIELD_CHAR: + if(0 > memcmp(s + pstKey->uFldpos, p + pstKey->uFldpos, pstKey->uFldlen)) + return TRUE; + else if(0 == memcmp(s + pstKey->uFldpos, p + pstKey->uFldpos, pstKey->uFldlen)) + return bCompare(s, p, pstCond, ++ uNice); + else + return FALSE; + break; + default: + break; + } + } + + return bCompare(s, p, pstCond, ++ uNice); +} + +/************************************************************************************************* + description:QSort list row + parameters: + pvData --data + low --low water + high --high water + lTruck --the length of truck + pstCond --field list + pvKey --next index of field + return: + *************************************************************************************************/ +void vQsortRow(void *pvData, long low, long high, size_t lTurck, FdCond *pstCond, void *pvKey) +{ + long first = low, last = high; + + if(low >= high) + return; + + memcpy(pvKey, pvData + first * lTurck, lTurck); + while(first < last) + { + while(first < last && bCompare(pvData + last * lTurck, pvKey, pstCond, 0)) + -- last; + + memcpy(pvData + first * lTurck, pvData + last * lTurck, lTurck); + + while(first < last && bCompare(pvKey, pvData + first * lTurck, pstCond, 0)) + ++ first; + memcpy(pvData + last * lTurck, pvData + first * lTurck, lTurck); + } + + memcpy(pvData + first * lTurck, pvKey, lTurck); + vQsortRow(pvData, low, first - 1, lTurck, pstCond, pvKey); + vQsortRow(pvData, first + 1, high, lTurck, pstCond, pvKey); +} + +/************************************************************************************************* + description:sort rowlist + parameters: + pstSavm --stvm handle + lRow --rows + pvData --data list + lTruck --the length of truck + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lSortRowList(SATvm *pstSavm, size_t lRow, void *pvData, size_t lTruck) +{ + void *pvKey; + FdCond *pstCond = &pstSavm->stUpdt; + + if(!bSetCondAttr(pstCond, pstSavm->tblName, ORDER_ASC | ORDER_DESC)) + return RC_SUCC; + + if(NULL == (pvKey = (char *)malloc(lTruck))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + vQsortRow(pvData, 0, (long)(lRow - 1), lTruck, pstCond, pvKey); + TFree(pvKey); + return RC_SUCC; +} + +/************************************************************************************************* + description:Collapse the rowgrp node to buffer. + parameters: + root --rowgrp root + return: + *************************************************************************************************/ +void _vConvRowList(Rowgrp *root, long lParant, void *pszBuffer, size_t *plOffset) +{ + Rowgrp *node; + + for(node = root; NULL != node; node = node->pstNext) + { + memcpy(pszBuffer + *plOffset, &lParant, sizeof(long)); *plOffset += sizeof(long); + memcpy(pszBuffer + *plOffset, &node->lLen, sizeof(long)); *plOffset += sizeof(long); + memcpy(pszBuffer + *plOffset, &node->lCount, sizeof(size_t)); *plOffset += sizeof(size_t); + memcpy(pszBuffer + *plOffset, node->psvData, node->lLen); *plOffset += node->lLen; + + _vConvRowList(node->pstSSet, node->lIdx, pszBuffer, plOffset); + } +} + +/************************************************************************************************* + description:Collapse the rowgrp + parameters: + root --rowgrp root + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lConvRowList(SATvm *pstSavm, Rowgrp *root, size_t *plOut, void **ppsvOut) +{ + Rowgrp *node; + size_t lOffset = 0; + + if(!root) + { + *plOut = 0; + return RC_SUCC; + } + + if(!ppsvOut || !plOut) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + for(node = root; NULL != node->pstNext; node = node->pstNext); + + *plOut = (node->lIdx + 1) * (sizeof(long) * 2 + sizeof(size_t) + node->lLen); + if(NULL == (*ppsvOut = (char *)calloc(1, *plOut))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + _vConvRowList(root, 0, *ppsvOut, &lOffset); + + return RC_SUCC; +} + +/************************************************************************************************* + description:find node from the rowgrp list by idx + parameters: + root --rowgrp root + idx --idx of node + return: + node --rowgrp node + *************************************************************************************************/ +Rowgrp* pFindRowList(Rowgrp *root, long idx) +{ + Rowgrp *node, *list; + + for(node = root; NULL != node; node = node->pstNext) + { + if(node->lIdx == idx) + return node; + + if(NULL != (list = pFindRowList(node->pstSSet, idx))) + return list; + } + + return NULL; +} + +/************************************************************************************************* + description:Collapse the buffer to rowgrp list + parameters: + pstSavm --stvm handle + pszBuffer --buffer + lData --the length of buffer + root --rowgrp root + return: + *************************************************************************************************/ +long lParsRowList(SATvm *pstSavm, void *pszBuffer, long lData, Rowgrp **root) +{ + Rowgrp row, *node; + long lOffset, idx; + + for(lOffset = 0; lOffset < lData; lOffset += row.lLen) + { + memcpy(&idx, pszBuffer + lOffset, sizeof(long)); lOffset += sizeof(long); + memcpy(&row.lLen, pszBuffer + lOffset, sizeof(long)); lOffset += sizeof(long); + memcpy(&row.lCount, pszBuffer + lOffset, sizeof(size_t)); lOffset += sizeof(size_t); + if(0 == idx) + { + if(NULL == (*root = (Rowgrp *)pInsertRowgrp(pstSavm, *root, NULL, NULL, + pszBuffer + lOffset, row.lLen, row.lCount))) + { + TFgrp(*root); + return RC_FAIL; + } + + continue; + } + + if(NULL == (node = pFindRowList(*root, idx))) + continue; + + if(NULL == (node = pInsertRowgrp(pstSavm, node, NULL, NULL, pszBuffer + lOffset, + row.lLen, row.lCount))) + { + TFgrp(*root); + return RC_FAIL; + } + } + + return RC_SUCC; +} + +/**************************************************************************************** + code end + ****************************************************************************************/ diff --git a/src/makefile b/src/makefile new file mode 100755 index 0000000..8e70d98 --- /dev/null +++ b/src/makefile @@ -0,0 +1,44 @@ +INCDIR= -I/usr/include -I$(HOME)/include -I./ -I./include -I../include +LIBDIR= -L$(HOME)/lib -L../lib -lstvm -lreadline -lm -lc -ldl -lpthread +AR=ar +LD=ld +LN=ln +CC=cc -fPIC +CO=-c -g +LDFLAG=-shared -g +OUTLIB=../lib +OUTBIN=../bin + +OBJFILE=tree.o sem.o msg.o tcp.o str.o list.o conf.o +TARGET=$(OUTLIB)/libstvm.a +TARDLL=$(OUTLIB)/libstvm.so +TARVER=$(OUTLIB)/libstvm.so.1.2 +STVM=$(OUTBIN)/stvm +DETVM=$(OUTBIN)/detvm + +all: $(TARGET) $(TARDLL) $(STVM) $(DETVM) clean +$(TARGET): $(OBJFILE) + rm -f $@ + $(AR) -cr $@ $(OBJFILE) + +$(TARDLL): $(OBJFILE) + $(LD) $(LDFLAG) -o $@ $(OBJFILE) + rm -f $(TARVER) + $(LN) -s $@ $(TARVER) + +$(STVM): stvm.o + $(CC) -o $@ $< $(LIBDIR) + +$(DETVM): detvm.o + $(CC) -o $@ $< $(LIBDIR) + +.SUFFIXES: .c .o + +.c.o: + $(CC) $(CO) $*.c $(INCDIR) $(LIBDIR) + +fall: + @touch *c + @make all +clean: + rm -f *.o diff --git a/src/msg.c b/src/msg.c new file mode 100644 index 0000000..2ee4e7f --- /dev/null +++ b/src/msg.c @@ -0,0 +1,313 @@ +/* +* Copyright (c) 2018 Savens Liu +* +* The original has been patented, Open source is not equal to open rights. +* Anyone can clone, download, learn and discuss for free. Without the permission +* of the copyright owner or author, it shall not be merged, published, licensed or sold. +* The copyright owner or author has the right to pursue his responsibility. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "tvm.h" + +/************************************************************************************************ + ipc msg function + ************************************************************************************************/ +/************************************************************************************************* + description:create message queue + parameters: + pstSavm --stvm handle + bCreate --create type + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lCreateQueue(SATvm *pstSavm, bool bCreate) +{ + long lQid; + + if(bCreate) + { + pstSavm->m_yMey = yGetIPCPath(pstSavm, IPC_MSG); + if(pstSavm->m_yMey <= RC_FAIL) + return RC_FAIL; + lQid = msgget(pstSavm->m_yMey, IPC_CREAT|0600); + } + else + lQid = msgget(IPC_PRIVATE, IPC_CREAT|0600); + if(RC_FAIL >= lQid) + { + switch(errno) + { + case EEXIST: + pstSavm->m_lErrno = MSG_ERR_EXIST; + break; + case EACCES: + pstSavm->m_lErrno = MSG_ERR_ACCES; + break; + case ENOMEM: + pstSavm->m_lErrno = MSG_ERR_NOMEM; + break; + default: + pstSavm->m_lErrno = MSG_ERR_INVAL; + break; + } + return RC_FAIL; + } + + return lQid; +} + +/************************************************************************************************* + description:Get the number of message queues + parameters: + pstSavm --stvm handle + lQid --msg id + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lGetQueueNum(SATvm *pstSavm, long lQid) +{ + struct msqid_ds stQueue; + + if(msgctl(lQid, IPC_STAT, &stQueue) <= -1) + { + switch(errno) + { + case EFAULT: + pstSavm->m_lErrno = MSG_ERR_FAULT; + break; + case EIDRM: + pstSavm->m_lErrno = MSG_ERR_EIDRM; + break; + default: + pstSavm->m_lErrno = MSG_ERR_INVAL; + break; + } + + return RC_FAIL; + } + + return stQueue.msg_qnum; +} + +/************************************************************************************************* + description:Get the maximum queue support byte + parameters: + pstSavm --stvm handle + lQid --msg id + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lQueueMaxByte(SATvm *pstSavm, long lQid) +{ + struct msqid_ds stQueue; + + if(msgctl(lQid, IPC_STAT, &stQueue) <= -1) + { + switch(errno) + { + case EFAULT: + pstSavm->m_lErrno = MSG_ERR_FAULT; + break; + case EIDRM: + pstSavm->m_lErrno = MSG_ERR_EIDRM; + break; + default: + pstSavm->m_lErrno = MSG_ERR_INVAL; + break; + } + + return RC_FAIL; + } + + return stQueue.msg_qbytes; +} + +/************************************************************************************************* + description:Gets the final processing time in the queue + parameters: + pstSavm --stvm handle + lQid --msg id + return: + long --success + RC_FAIL --failure + *************************************************************************************************/ +long lQueueRcvTime(SATvm *pstSavm, long lQid) +{ + struct msqid_ds stQueue; + + if(msgctl(lQid, IPC_STAT, &stQueue) <= -1) + { + switch(errno) + { + case EFAULT: + pstSavm->m_lErrno = MSG_ERR_FAULT; + break; + case EIDRM: + pstSavm->m_lErrno = MSG_ERR_EIDRM; + break; + default: + pstSavm->m_lErrno = MSG_ERR_INVAL; + break; + } + + return RC_FAIL; + } + +// return (long)time(&stQueue.msg_rtime); + return (long)stQueue.msg_rtime > 0 ? (long)stQueue.msg_rtime : (long)stQueue.msg_ctime; +} + +/************************************************************************************************* + description:read from message queue + parameters: + pstSavm --stvm handle + lQid --msg id + pstVoid --create type + lSize --create type + lMType --msg type + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lEventRead(SATvm *pstSavm, long lQid, void *pstVoid, long lSize, long lMType) +{ + if(RC_SUCC > msgrcv(lQid, pstVoid, lSize - sizeof(long), lMType, 0)) + { + switch(errno) + { + case E2BIG: + pstSavm->m_lErrno = MSG_ERR_E2BIG; + break; + case EACCES: + pstSavm->m_lErrno = MSG_ERR_ACCES; + break; + case EFAULT: + pstSavm->m_lErrno = MSG_ERR_FAULT; + break; + case EIDRM: + pstSavm->m_lErrno = MSG_ERR_EIDRM; + break; + case EINTR: + pstSavm->m_lErrno = MSG_ERR_EINTR; + break; + default: + pstSavm->m_lErrno = MSG_ERR_INVAL; + break; + } + + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:non-blocking read from message queue + parameters: + pstSavm --stvm handle + lQid --msg id + pstVoid --create type + lSize --create type + lMType --msg type + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lReadNoWait(SATvm *pstSavm, long lQid, void *psvVoid, long lSize, long lMType) +{ + errno = 0; + if(RC_SUCC > msgrcv(lQid, psvVoid, lSize - sizeof(long), lMType, IPC_NOWAIT)) + { + switch(errno) + { + case EAGAIN: + case ENOMSG: + return RC_SUCC; + case E2BIG: + pstSavm->m_lErrno = MSG_ERR_E2BIG; + break; + case EACCES: + pstSavm->m_lErrno = MSG_ERR_ACCES; + break; + case EFAULT: + pstSavm->m_lErrno = MSG_ERR_FAULT; + break; + case EIDRM: + pstSavm->m_lErrno = MSG_ERR_EIDRM; + break; + case EINTR: + pstSavm->m_lErrno = MSG_ERR_EINTR; + return RC_FAIL; + default: + pstSavm->m_lErrno = MSG_ERR_INVAL; + break; + } + + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:write to message queue + parameters: + pstSavm --stvm handle + lQid --msg id + pstVoid --create type + lSize --create type + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lEventWrite(SATvm *pstSavm, long lQid, void *psvData, long lSize) +{ + if(msgsnd(lQid, psvData, lSize - sizeof(long), 0) < RC_SUCC) + { + switch(errno) + { + case EACCES: + pstSavm->m_lErrno = MSG_ERR_ACCES; + break; + case EAGAIN: + pstSavm->m_lErrno = MSG_ERR_SNDEG; + break; + case EFAULT: + pstSavm->m_lErrno = MSG_ERR_FAULT; + break; + case EIDRM: + pstSavm->m_lErrno = MSG_ERR_EIDRM; + break; + case EINTR: + pstSavm->m_lErrno = MSG_ERR_EINTR; + break; + default: + pstSavm->m_lErrno = MSG_ERR_INVAL; + break; + } + + return RC_FAIL; + } + + return RC_SUCC; +} + +/**************************************************************************************** + code end + ****************************************************************************************/ + diff --git a/src/sem.c b/src/sem.c new file mode 100644 index 0000000..860c1ac --- /dev/null +++ b/src/sem.c @@ -0,0 +1,144 @@ +/* +* Copyright (c) 2018 Savens Liu +* +* The original has been patented, Open source is not equal to open rights. +* Anyone can clone, download, learn and discuss for free. Without the permission +* of the copyright owner or author, it shall not be merged, published, licensed or sold. +* The copyright owner or author has the right to pursue his responsibility. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "tvm.h" + +/**************************************************************************************** + senum union + ****************************************************************************************/ +union semun { + int val; + struct semid_ds *buf; + struct seminfo *__buf; +}; + +/************************************************************************************************ + sems function + ************************************************************************************************/ +/************************************************************************************************* + description:create semaphore + parameters: + pstSavm --stvm handle + pstRun --table handle + lSems --the number of semaphores + lValue --The index of the semaphores + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lCreateSems(SATvm *pstSavm, RunTime *pstRun, long lSems, long lValue) +{ + long i = 0; + union semun uSem; + + if(lSems <= 0) + { + pstSavm->m_lErrno = SEM_CDIT_NULL; + return RC_FAIL; + } + + if(RC_FAIL == (pstRun->m_semID = semget(pstSavm->m_ySey, lSems, IPC_CREAT|0600))) + { + switch(errno) + { + case EEXIST: + pstSavm->m_lErrno = SEM_ERR_EXIST; + break; + case EIDRM: + pstSavm->m_lErrno = SEM_ERR_EIDRM; + break; + case EACCES: + pstSavm->m_lErrno = SEM_ERR_ACCES; + break; + case ENOMEM: + pstSavm->m_lErrno = SEM_ERR_NOMEM; + break; + default: + pstSavm->m_lErrno = SEM_ERR_INVAL; + break; + } + + return RC_FAIL; + } + + for(i = 0, uSem.val = lValue; i < lSems; i ++) + semctl(pstRun->m_semID, i, SETVAL, uSem); + + return RC_SUCC; +} + +/************************************************************************************************* + description:create semaphore + parameters: + pstSavm --stvm handle + semID --the idx of semaphores + lSems --the number of semaphores + evp --opereate of P-V + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lOperateSems(SATvm *pstSavm, long semID, long lSems, Benum evp) +{ + struct sembuf se; + + se.sem_num = lSems; + se.sem_op = evp; + se.sem_flg = SEM_UNDO; + + if(RC_SUCC != semop(semID, &se, 1)) + { + switch(errno) + { + case EINTR: + return RC_SUCC; + case EEXIST: + pstSavm->m_lErrno = SEM_ERR_EXIST; + break; + case EIDRM: + pstSavm->m_lErrno = SEM_ERR_EIDRM; + break; + case EACCES: + pstSavm->m_lErrno = SEM_ERR_ACCES; + break; + case ENOMEM: + pstSavm->m_lErrno = SEM_ERR_NOMEM; + break; + case E2BIG: + case ERANGE: + pstSavm->m_lErrno = SEM_ERR_INVAL; + break; + default: + pstSavm->m_lErrno = SEM_ERR_INVAL; + break; + } + + return RC_FAIL; + } + + return RC_SUCC; +} + + +/**************************************************************************************** + code end + ****************************************************************************************/ + diff --git a/src/str.c b/src/str.c new file mode 100644 index 0000000..1677afc --- /dev/null +++ b/src/str.c @@ -0,0 +1,480 @@ +/* +* Copyright (c) 2018 Savens Liu +* +* The original has been patented, Open source is not equal to open rights. +* Anyone can clone, download, learn and discuss for free. Without the permission +* of the copyright owner or author, it shall not be merged, published, licensed or sold. +* The copyright owner or author has the right to pursue his responsibility. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "tstr.h" + +/************************************************************************************************ + strs function + ************************************************************************************************/ +/************************************************************************************************* + description:uppercase string + parameters: + s --string + return: + s + *************************************************************************************************/ +char *supper(char *s) +{ + long i, l = strlen(s), fg = 0; + + for(i=0; i < l; i++) + s[i] = toupper(s[i]); + + return s; +} + +/************************************************************************************************* + description:lowercas string + parameters: + s --string + return: + s + *************************************************************************************************/ +char *slower(char *s) +{ + long i, l = strlen(s), fg = 0; + + for(i = 0; i < l; i++) + s[i] = tolower(s[i]); + + return s; +} + +/************************************************************************************************* + description:drop CRLF from string + parameters: + p --string + return: + p + *************************************************************************************************/ +char* strimcrlf(char *p) +{ + int i = 0, j = 0, m = 0; + char *s = NULL; + + if(!p) return p; + if(!strlen(p)) return p; + + s = p; + m = strlen(p); + for(i = 0; i < m; i ++) + { + if(p[i] == 10 || p[i] == 13) + continue; + s[j] = p[i]; + j ++; + } + s[j] = 0x00; + return s; +} + +/************************************************************************************************* + description:trim the left space from string + parameters: + p --string + return: + p + *************************************************************************************************/ +char* sltrim(char *p) +{ + char *s = p; + long i, k = 0, l; + + if(!p || (0 == (l = strlen(p)))) + return p; + + for(i = 0; i < l; i ++, k ++) + { + if(p[i] != ' ' && '\t' != p[i]) + break; + } + + if(0 == k) return p; + + for(i = 0; i < l - k; i ++) + p[i] = s[i + k]; + p[i] = 0x00; + + return p; +} + +/************************************************************************************************* + description:trim the right space from string + parameters: + p --string + return: + p + *************************************************************************************************/ +char* srtrim(char *p) +{ + long i, k = 0, l = 0; + + if(!p || 0 == (l = strlen(p))) + return p; + + for(i = l - 1; i >= 0; i --) + { + if(p[i] == ' ' || '\t' == p[i]) + continue; + break; + } + +// p[i + 1] = '\0'; + memset(p + i + 1, 0, l - i - 1); + + return p; +} + +/************************************************************************************************* + description:trimall space from string + parameters: + p --string + return: + p + *************************************************************************************************/ +char* strimall(char *p) +{ + long i, k = 0, l = 0; + char *q = p; + + if(!p || !strlen(p)) + return p; + + l = strlen(p); + for(i = 0; i < l; i ++) + { + if(p[i] == ' ') + continue; + q[k ++] = p[i]; + } + memset(q + k, 0, l - k); + p = q; + + return q; +} + +/************************************************************************************************* + description:trim the left space from field string + parameters: + p --string + return: + p + *************************************************************************************************/ +char* strimfield(char *s) +{ + register int i, n, m; + BOOL bf = false; + + if(!s || 0 == (n = strlen(s))) + return s; + + for(i = 0, m = 0; i < n; i ++) + { + if(s[i] == '\"') + bf = !bf; + + if(bf) s[m ++] = s[i]; + else if(s[i] != ' ' && s[i] != '\t') + s[m ++] = s[i]; + } + + s[m] = 0x00; + + return s; +} + +/************************************************************************************************* + description:calcute the number of field string + parameters: + p --string + k --string + return: + p + *************************************************************************************************/ +long lfieldnum(char *p, char *k) +{ + char *y = p; + BOOL bf = false; + long idx, i, m, n; + + if(!p || !k) return 0; + + for(i = 0, idx = 0, m = strlen(p), n = strlen(k); i < m; i ++) + { + if(p[i] == '\\') + { + i ++; + continue; + } + + if(p[i] == '\"' || p[i] == '\'') + bf = !bf; + + if(bf) continue; + + if(!memcmp(p + i, k, n)) + { + ++ idx; + for(i += n; i < m; i ++) + { + if(p[i] != ' ' && p[i] != '\t' && memcmp(p + i, k, n)) + break; + } + + y = p + i; + i --; + } + } + + for(i = y - p ; i < m; i ++) + { + if(y[i] != ' ' && y[i] != '\t') + return ++ idx; + } + + return idx; +} + +/************************************************************************************************* + description:is or not gbk-Character set + parameters: + s --string + return: + 1 --yes + 0 --no + *************************************************************************************************/ +int bIsgbk(const char *s) +{ + if((ushar)s[0] > 0x80 && (ushar)s[1] >= 0x40) + return 1; + return 0; +} + +/************************************************************************************************* + description:Gets the field value of the specified character position + parameters: + p --string + s --characters + id --position + return: + char --values + *************************************************************************************************/ +char* sfieldvalue(char *p, char *k, int id) +{ + char *y = p; + BOOL bf = false; + long idx, i = 0, m = 0, n = 0; + static char szOut[1024]; + + memset(szOut, 0, sizeof(szOut)); + if(!p || !k || id <= 0) return szOut; + + for(i = 0, idx = 0, m = strlen(p), n = strlen(k); i < m; i ++) + { + if(p[i] == '\\') + { + i ++; + continue; + } + + if(p[i] == '\"' || p[i] == '\'') + { + bf = !bf; + continue; + } + if(bf) continue; + + if(!memcmp(p + i, k, n)) + { + if(++idx == id) + break; + + for(i += n; i < m; i ++) + { + if(p[i] != ' ' && p[i] != '\t' && memcmp(p + i, k, n)) + break; + } + + y = p + i; + i --; + } + } + + if(idx + 1 < id) return szOut; + memcpy(szOut, y, i - (long )(y - p)); + + return szOut; +} + +/************************************************************************************************* + description:Gets the number of specified characters + parameters: + p --string + s --characters + return: + long --number + *************************************************************************************************/ +long lgetstrnum(char *p, char *s) +{ + char *q = p; + long i, m, n, k; + + if(!p || 0 == (n = strlen(s)) || 0 == (m = strlen(p))) + return 0; + + for(i = 0, k = 0; i < m; i += n, q += n) + { + if(0 == memcmp(q, s, n)) + k ++; + } + + return k; +} + +/************************************************************************************************* + description:Gets the value of the specified character position + parameters: + p --string + s --characters + id --position + return: + char --values + *************************************************************************************************/ +char* sgetvalue(char *p, char *s, int id) +{ + char *y = p; + long i, m, n, idx = 0; + static char szOut[1024]; + + memset(szOut, 0, sizeof(szOut)); + if(!p || !s || id <= 0 || (n = strlen(s)) <= 0) + return szOut; + + for(i = 0, idx = 0, m = strlen(p); i < m; i ++) + { + if(!memcmp(p + i, s, n)) + { + if(i > 0 && bIsgbk(p + i - 1)) + continue; + + if(++ idx == id) + break; + + y = p + i + n; + } + } + + if(idx + 1 < id) return szOut; + memcpy(szOut, y, i - (int)(y - p)); + + return szOut; +} + +/************************************************************************************************* + description:Characters to replace + parameters: + p --The original string + o --key characters + d --target character + return: + char --values + *************************************************************************************************/ +char* sfieldreplace(char *p, char o, char d) +{ + char *s = p; + bool bf = false; + long idx, i, j = 0, m = 0; + + if(!p) return p; + + for(i = 0, idx = 0, m = strlen(p); i < m; i ++) + { + if(p[i] == '\"' || p[i] == '\'') + bf = !bf; + + if(bf) + { + s[j ++] = p[i]; + continue; + } + + if(o == p[i]) + { + if(i > 0 && bIsgbk(p + i - 1)) + continue; + + p[i] = d; + } + + if((j == 0 && ' ' == p[i]) || (j > 0 && ' ' == s[j - 1] && p[i] == ' ')) + continue; + s[j ++] = p[i]; + } + s[j] = 0x00; + + return s; +} + +/************************************************************************************************* + description:Get the value between o-d + parameters: + p --The original string + o --key characters + d --target character + return: + char* --values + *************************************************************************************************/ +char* strimabout(char *s, char *o, char *d) +{ + long l = 0; + char *p = NULL, *q = NULL, *m = NULL; + + if(!s || !o || !d) return NULL; + if(0 == (l = strlen(s))) return NULL; + if(NULL == (p = strstr(s, o))) return NULL; + + for(l; l > 0; l --) + { + if(NULL != (q = strstr(s + l, d))) + break; + } + if(!q) return NULL; + + l = strlen(o); + if((p - q) >= 0) return NULL; + + if(((p - q + l) == 0)) + { + s[0] = 0x00; + return NULL; + } + + for(m = s, p += l; p != q; *p ++, *m ++) + *m = *p; + *m = 0x00; + + return s; +} + +/**************************************************************************************** + code end +****************************************************************************************/ + diff --git a/src/stvm.c b/src/stvm.c new file mode 100644 index 0000000..c17a0c4 --- /dev/null +++ b/src/stvm.c @@ -0,0 +1,4139 @@ +/* +* Copyright (c) 2018 Savens Liu +* +* The original has been patented, Open source is not equal to open rights. +* Anyone can clone, download, learn and discuss for free. Without the permission +* of the copyright owner or author, it shall not be merged, published, licensed or sold. +* The copyright owner or author has the right to pursue his responsibility. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _GNU_SOURCE +#include "tvm.h" +#include "tmain.h" +#include +#include + +/************************************************************************************************* + macro + *************************************************************************************************/ +#define DEL_TAIL_CHAR(s,c) if(c == s[strlen(s) - 1]) s[strlen(s) - 1] = 0x00; + +/************************************************************************************************* + function + *************************************************************************************************/ +Benum elog = 0; +extern char **environ; +extern long lShutdownTvm(); +extern void vSetNode(char *s); +extern long lStartupTvm(TBoot *pstBoot); + +/************************************************************************************************* + description:get stvm version + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +static char* sGetTVMVers() +{ + struct utsname sinf; + static char szVersion[512]; + + memset(szVersion, 0, sizeof(szVersion)); + sprintf(szVersion, "Compile %s %s on ", __DATE__, __TIME__); + if(RC_SUCC != uname(&sinf)) + strcat(szVersion, "Linux"); + else + strcat(szVersion, sinf.sysname); + + sprintf(szVersion + strlen(szVersion), " %s Runtime\nRelease TVM C/C++ Library Version V%s on", + sinf.machine, TVM_VKERNEL); + if(8 == sizeof(long)) + strcat(szVersion, " Linux x64\n"); + else + strcat(szVersion, " Linux x32\n"); + sprintf(szVersion + strlen(szVersion), "Release STVM %s Production on %s %s\n", + TVM_VERSION, sinf.sysname, sinf.machine); + + strcat(szVersion, "Author:DeffPuzzL\n"); + strcat(szVersion, "Mail:deffpuzzl@qq.com\n"); + + return szVersion; +} + +/************************************************************************************************* + description:Get the Domain version + parameters: + return: + char* + *************************************************************************************************/ +char* sFuncVersion() +{ + struct utsname sinf; + static char szVersion[512]; + + memset(szVersion, 0, sizeof(szVersion)); + sprintf(szVersion, "Compile %s %s ", __DATE__, __TIME__); + uname(&sinf); + + sprintf(szVersion + strlen(szVersion), "Release %s Production on %s", TVM_VERSION, + sinf.sysname); + + if(8 == sizeof(long)) + strcat(szVersion, " x64\n"); + else + strcat(szVersion, " x32\n"); + + return szVersion; +} + +/************************************************************************************************* + description:Screen output debugging + parameters: + return: + *************************************************************************************************/ +void vSCRDebug(const char *fmt, ...) +{ + char szMsg[1024]; + va_list ap; + + if(0 == elog) return ; + + memset(szMsg, 0, sizeof(szMsg)); + va_start(ap, fmt); + vsnprintf(szMsg, sizeof(szMsg), fmt, ap); + va_end(ap); + + fprintf(stdout, "%s\n", szMsg); +} + +/************************************************************************************************* + description:get pragma pack + parameters: + return: + int --align + *************************************************************************************************/ +int getpack() +{ + int pack; + + struct Test + { + int a; + long b; + long long c; + char d; + }; + + pack = sizeof(struct Test); + if(8 == sizeof(long)) + { + switch(pack) + { + case 21: + return 1; + case 22: + return 2; + case 24: + return 4; + case 32: + return 8; + default: + fprintf(stdout, "当前环境对齐数值(%d)过大\n", pack); + fflush(stdout); + return -1; + } + } + else + { + switch(pack) + { + case 17: + return 1; + case 18: + return 2; + case 20: + return 4; + case 24: + return 8; + default: + fprintf(stdout, "当前环境对齐数值(%d)过大\n", pack); + fflush(stdout); + return -1; + } + } + + return pack; +} + +/************************************************************************************************* + description:Sizeof function + parameters: + return: + sizeof + *************************************************************************************************/ +int sizecn(TblKey *pstKey, long lfld) +{ + TblKey *pv; + int i, n, k, pack, size = 0; + + if(0 == lfld) return 0; + + if(-1 == (pack = getpack())) + return pack; + + for(i = 0, k = 0; i < lfld; i ++) + { + pv = &pstKey[i]; + if(FIELD_CHAR != pv->m_lAttr && pv->m_lLen > k) + k = pv->m_lLen; + } + + /* 若使用了#pragma pack(n)命令强制对齐标准, 则取n和结构体中 + 最长数据类型占的字节数两者之中的小者作为对齐标准。 */ + if(k < pack) pack = k; + if(pack == 0) return 0; + + for(i = 0, n = 0, k = 0; i < lfld; i ++) + { + pv = &pstKey[i]; + if(0 == pv->m_lLen) continue; + if(FIELD_CHAR != pv->m_lAttr) + { + /* 数据对齐原则----内存按结构成员的先后顺序排列,当排到该成员变量时, + * 其前面已摆放的空间大小必须是该成员类型大小的整倍数,如果不够则补齐 */ + /* 没有考虑用户指定 指定对齐值:#pragma pack (value)时指定的对齐value。 */ + if(pack > pv->m_lLen) + n = pv->m_lLen; + else + n = pack; + + if(0 != (k = size % n)) + size += (n - k); + } + + pv->m_lFrom = size; + size += pv->m_lLen; + } + + /* 整体空间是 占用空间最大的成员(的类型)所占字节数的整倍数 */ + if(0 != (k = size % pack)) + size += (pack - k); + + return size; +} + +/************************************************************************************************* + description:analysis of the table header + parameters: + s --string + len --strlen length + pstTde --Table define + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lAnalysHead(char *s, long len, TblDef *pstTde) +{ + long i, n; + char szTemp[512], szHead[512], szTar[64], *p = NULL; + + memset(szHead, 0, sizeof(szHead)); + if(len > sizeof(szHead)) + { + fprintf(stderr, "table head define error\n"); + return RC_FAIL; + } + + strncpy(szHead, s, len); + for(i = 0, n = lgetstrnum(szHead, "\n"); i < n; i ++) + { + memset(szTemp, 0, sizeof(szTemp)); + strncpy(szTemp, sfieldvalue(szHead, "\n", i + 1), sizeof(szTemp)); + if('#' == szTemp[0] || !strncmp(szTemp, "--", 2) || !strlen(szTemp)) + continue; + + if(strncasecmp(szTemp, "set ", 4)) + { + fprintf(stderr, "definition table syntax error\n*%s\n", szTemp); + return RC_FAIL; + } + + memset(szTar, 0, sizeof(szTar)); + strncpy(szTar, sfieldvalue(szTemp + 4, "=", 1), sizeof(szTar)); + sltrim(szTar); + if(!strcasecmp(szTar, "TABLE")) + { + pstTde->m_table = atol(sfieldvalue(szTemp + 4, "=", 2)); + if(pstTde->m_table < 5) + { + fprintf(stderr, "definition table error\n"); + return RC_FAIL; + } + } + else if(!strcasecmp(szTar, "TABLESPACE")) + pstTde->m_lMaxRow = atol(sfieldvalue(szTemp + 4, "=", 2)); + else + { + fprintf(stderr, "Unrecognized command\n*%s\n", szTemp); + return RC_FAIL; + } + } + if(pstTde->m_table < 5) + { + fprintf(stderr, "table not define\n"); + return RC_FAIL; + } + + if(pstTde->m_lMaxRow <= 0) + { + fprintf(stderr, "table size node define\n"); + return RC_FAIL; + } + + strcpy(pstTde->m_szPart, sGetNode()); + + return RC_SUCC; +} + +/************************************************************************************************* + description:analysis of the table + parameters: + s --string + len --strlen length + pstTde --Table define + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lAnalysTable(char *s, long len, TblDef *pstTde) +{ + long i, n, k; + TblKey *pv = NULL; + char szTemp[512], szField[1024], szTar[128], *p = NULL; + + memset(szField, 0, sizeof(szField)); + if(len > sizeof(szField) || len < 1) + { + fprintf(stderr, "table head define error\n"); + return RC_FAIL; + } + + strncpy(szField, s, len); + strimabout(szField, "(", ")"); + for(i = 0, n = lgetstrnum(szField, "\n"), pstTde->m_lIdxNum = 0; i < n; i ++) + { + memset(szTemp, 0, sizeof(szTemp)); + strncpy(szTemp, sfieldvalue(szField, "\n", i + 1), sizeof(szTemp)); + strimcrlf(szTemp); + sltrim(szTemp); + srtrim(szTemp); + DEL_TAIL_CHAR(szTemp, ','); + if('#' == szTemp[0] || !strncmp(szTemp, "--", 2) || !strlen(szTemp)) + continue; + + pv = &pstTde->m_stKey[pstTde->m_lIdxNum]; + strncpy(pv->m_szField, sfieldvalue(szTemp, " ", 1), MAX_FIELD_LEN); + if(!strlen(pv->m_szField)) + { + fprintf(stderr, "field define error\n"); + return RC_FAIL; + } + memset(szTar, 0, sizeof(szTar)); + strncpy(szTar, sfieldvalue(szTemp, " ", 2), MAX_FIELD_LEN); + if(!strcasecmp(szTar, "short")) + { + pv->m_lAttr = FIELD_LONG; + pv->m_lLen = sizeof(short); + } + else if(!strcasecmp(szTar, "int")) + { + pv->m_lAttr = FIELD_LONG; + pv->m_lLen = sizeof(int); + } + else if(!strcasecmp(szTar, "long")) + { + pv->m_lAttr = FIELD_LONG; + pv->m_lLen = sizeof(long); + } + else if(!strcasecmp(szTar, "llong")) + { + pv->m_lAttr = FIELD_LONG; + pv->m_lLen = sizeof(long long); + } + else if(!strcasecmp(szTar, "double")) + { + pv->m_lAttr = FIELD_DOUB; + pv->m_lLen = sizeof(double); + } + else if(!strcasecmp(szTar, "float")) + { + pv->m_lAttr = FIELD_DOUB; + pv->m_lLen = sizeof(float); + } + else if(!strncasecmp(szTar, "char", 1)) + { + pv->m_lAttr = FIELD_CHAR; + if(!strcasecmp(szTar, "char")) + pv->m_lLen = sizeof(char); + else + { + p = szTar + 4; + strimabout(p, "(", ")"); + strimabout(p, "[", "]"); + if(!strlen(p) || atol(p) <= 0) + { + fprintf(stderr, "Character size setting error\n"); + return RC_FAIL; + } + pv->m_lLen = atol(p); + } + } + else + { + fprintf(stderr, "Undefined field type\n"); + return RC_FAIL; + } + + pstTde->m_lIdxNum ++; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:creates the table index + parameters: + s --string + pstTde --Table define + em --index type + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lIndexField(char *s, TblDef *pstTde, Uenum em) +{ + long i, n; + TblKey *pstKey = NULL; + char szField[MAX_FIELD_LEN]; + + n = lfieldnum(s, ","); + if(UNQIUE == em) + { + for(i = 0, pstTde->m_lIType |= UNQIUE, pstTde->m_lIdxUp = 0; i < n; i ++) + { + memset(szField, 0, MAX_FIELD_LEN); + strncpy(szField, sfieldvalue(s, ",", i + 1), MAX_FIELD_LEN); + strimcrlf(szField); + strimall(szField); + if(NULL == (pstKey = pFindField(pstTde->m_stKey, pstTde->m_lIdxNum, szField))) + return RC_FAIL; + + strcpy(pstTde->m_stIdxUp[pstTde->m_lIdxUp].m_szField, szField); + pstTde->m_stIdxUp[pstTde->m_lIdxUp].m_lFrom = pstKey->m_lFrom; + pstTde->m_stIdxUp[pstTde->m_lIdxUp].m_lLen = pstKey->m_lLen; + pstTde->m_stIdxUp[pstTde->m_lIdxUp].m_lAttr = pstKey->m_lAttr; + pstTde->m_lIdxLen += pstKey->m_lLen; + pstTde->m_lIdxUp ++; + } + if(0 == pstTde->m_lIdxUp) + return RC_FAIL; + return RC_SUCC; + } + else if(NORMAL == em) + { + for(i = 0, pstTde->m_lIType |= NORMAL, pstTde->m_lGrpUp = 0; i < n; i ++) + { + memset(szField, 0, MAX_FIELD_LEN); + strncpy(szField, sfieldvalue(s, ",", i + 1), MAX_FIELD_LEN); + strimcrlf(szField); + strimall(szField); + if(NULL == (pstKey = pFindField(pstTde->m_stKey, pstTde->m_lIdxNum, szField))) + return RC_FAIL; + + strcpy(pstTde->m_stGrpUp[pstTde->m_lGrpUp].m_szField, szField); + pstTde->m_stGrpUp[pstTde->m_lGrpUp].m_lFrom = pstKey->m_lFrom; + pstTde->m_stGrpUp[pstTde->m_lGrpUp].m_lLen = pstKey->m_lLen; + pstTde->m_stGrpUp[pstTde->m_lGrpUp].m_lAttr = pstKey->m_lAttr; + pstTde->m_lGrpLen += pstKey->m_lLen; + pstTde->m_lGrpUp ++; + } + + if(0 == pstTde->m_lGrpUp) + return RC_FAIL; + return RC_SUCC; + } + else if(HASHID == em) + { + for(i = 0, pstTde->m_lIType |= HASHID, pstTde->m_lGrpUp = 0; i < n; i ++) + { + memset(szField, 0, MAX_FIELD_LEN); + strncpy(szField, sfieldvalue(s, ",", i + 1), MAX_FIELD_LEN); + strimcrlf(szField); + strimall(szField); + if(NULL == (pstKey = pFindField(pstTde->m_stKey, pstTde->m_lIdxNum, szField))) + return RC_FAIL; + strcpy(pstTde->m_stGrpUp[pstTde->m_lGrpUp].m_szField, szField); + pstTde->m_stGrpUp[pstTde->m_lGrpUp].m_lFrom = pstKey->m_lFrom; + pstTde->m_stGrpUp[pstTde->m_lGrpUp].m_lLen = pstKey->m_lLen; + pstTde->m_stGrpUp[pstTde->m_lGrpUp].m_lAttr = pstKey->m_lAttr; + pstTde->m_lGrpLen += pstKey->m_lLen; + pstTde->m_lGrpUp ++; + } + + if(0 == pstTde->m_lGrpUp) + return RC_FAIL; + return RC_SUCC; + } + + return RC_FAIL; +} + +/************************************************************************************************* + description:analysis of the header index + parameters: + s --string + pstTde --Table define + em --index type + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lAnalysIndex(char *s, long len, TblDef *pstTde) +{ + long i, n, k, lRet; + char szIndex[1024], szTemp[256], *p = NULL; + + memset(szIndex, 0, sizeof(szIndex)); + if(len > sizeof(szIndex) || len < 1) + { + fprintf(stderr, "table head define error\n"); + return RC_FAIL; + } + + strncpy(szIndex, s, len); + strcat(szIndex, "\n"); + for(i = 0, k = 0, n = lgetstrnum(szIndex, "\n"), pstTde->m_lIType = 0; i < n; i ++) + { + memset(szTemp, 0, sizeof(szTemp)); + strncpy(szTemp, sfieldvalue(szIndex, "\n", i + 1), sizeof(szTemp)); + strimcrlf(szTemp); + sltrim(szTemp); + srtrim(szTemp); + DEL_TAIL_CHAR(szTemp, ','); + if('#' == szTemp[0] || !strncmp(szTemp, "--", 2) || !strlen(szTemp)) + continue; + + if(p = strcasestr(szTemp, "create unique index")) + { + strimabout(p, "(", ")"); + if(k & UNQIUE) + { + fprintf(stderr, "Only one unique index can be created\n"); + return RC_FAIL; + } + + k |= UNQIUE; + lRet = lIndexField(p, pstTde, UNQIUE); + } + else if(p = strcasestr(szTemp, "create index")) + { + strimabout(p, "(", ")"); + if(k & NORMAL) + { + fprintf(stderr, "Only one index can be created\n"); + return RC_FAIL; + } + + k |= NORMAL; + lRet = lIndexField(p, pstTde, NORMAL); + } + else if(p = strcasestr(szTemp, "create hash")) + { + strimabout(p, "(", ")"); + if(k & NORMAL) + { + fprintf(stderr, "Only one index can be created\n"); + return RC_FAIL; + } + + k |= NORMAL; + lRet = lIndexField(p, pstTde, HASHID); + } + else + { + fprintf(stderr, "index define error\n"); + return RC_FAIL; + } + + if(RC_SUCC != lRet) + { + fprintf(stderr, "parse index field error\n"); + return RC_FAIL; + } + } + + return RC_SUCC; +} + +/************************************************************************************************* + description: + parameters: + pszTable --table name + return: + char* --struck name + *************************************************************************************************/ +char* sGetTabName(char *pszTable) +{ + long l = 0; + static char szName[512]; + char *p = NULL, *q = NULL; + + slower(pszTable); + memset(szName, 0, sizeof(szName)); + if(!pszTable || !strlen(pszTable)) + return szName; + + l = 0; + strcpy(szName, "db"); + while(p = strstr(pszTable + l, "_")) + { + p[0 + 1]= p[0 + 1] - 32; + q = strstr(p + 1, "_"); + if(!q) + strcat(szName, p + 1); + else + strncpy(szName + strlen(szName), p + 1, q - p - 1); + l = p - pszTable + 1; + } + return szName; +} + +/************************************************************************************************* + description:creates the table struck + parameters: + pstTde --Table define + em --index type + return: + *************************************************************************************************/ +void vCreateStruck(TblDef *pstTde, bool bf) +{ + long i; + TblKey *pv = NULL; + + fprintf(stdout, "\n#Table definition\n"); + if(bf) + { + fprintf(stdout, "\nset TABLE=%d\n", pstTde->m_table); + fprintf(stdout, "set TABLESPACE=%d\n\n", pstTde->m_lMaxRow); + } + + fprintf(stdout, "typedef struct __%s\n{\n", supper(pstTde->m_szTable)); + for(i = 0; i < pstTde->m_lIdxNum; i ++) + { + pv = &pstTde->m_stKey[i]; + if(FIELD_CHAR == pv->m_lAttr) + fprintf(stdout, " char %s[%d];\n", pv->m_szField, pv->m_lLen); + else if(FIELD_LONG == pv->m_lAttr) + { + switch(pv->m_lLen) + { + case 2: + fprintf(stdout, " short %s;\n", pv->m_szField); + break; + case 4: + fprintf(stdout, " int %s;\n", pv->m_szField); + break; + case 8: + if(8 == sizeof(long)) + fprintf(stdout, " long %s;\n", pv->m_szField); + else + fprintf(stdout, " llong %s;\n", pv->m_szField); + break; + default: + break; + } + } + else if(FIELD_DOUB == pv->m_lAttr) + { + switch(pv->m_lLen) + { + case 4: + fprintf(stdout, " float %s;\n", pv->m_szField); + break; + case 8: + fprintf(stdout, " double %s;\n", pv->m_szField); + break; + default: + break; + } + } + } + + fprintf(stdout, "}%s;\n", sGetTabName(supper(pstTde->m_szTable))); + + if(bf) + { + fprintf(stdout, "\n-- Create indexes\n"); + if(pstTde->m_lIType & UNQIUE) + { + pv = &pstTde->m_stIdxUp[0]; + fprintf(stdout, "create unique index (%s", pv->m_szField); + for(i = 1; i < pstTde->m_lIdxUp; i ++) + { + pv = &pstTde->m_stKey[i]; + fprintf(stdout, ", %s", pv->m_szField); + } + fprintf(stdout, ");\n"); + } + + if(pstTde->m_lIType & NORMAL) + { + pv = &pstTde->m_stGrpUp[0]; + fprintf(stdout, "create index (%s", pv->m_szField); + for(i = 1; i < pstTde->m_lGrpUp; i ++) + { + pv = &pstTde->m_stKey[i]; + fprintf(stdout, ", %s", pv->m_szField); + } + fprintf(stdout, ");\n"); + + } + else if(pstTde->m_lIType & HASHID) + { + pv = &pstTde->m_stGrpUp[0]; + fprintf(stdout, "create hash (%s", pv->m_szField); + for(i = 1; i < pstTde->m_lGrpUp; i ++) + { + pv = &pstTde->m_stKey[i]; + fprintf(stdout, ", %s", pv->m_szField); + } + fprintf(stdout, ");\n"); + } + } + fprintf(stdout, "\n"); + return ; +} + +/************************************************************************************************* + description:out put table struct + parameters: + t --table + return: + *************************************************************************************************/ +void vTableStruck(TABLE t) +{ + RunTime *pstRun = NULL; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + if(NULL == (pstSavm = (SATvm *)pInitSATvm(t))) + { + fprintf(stderr, "initial table (%d) failed\n", t); + return ; + } + + if(NULL == (pstRun = pInitHitTest(pstSavm, pstSavm->tblName))) + { + fprintf(stderr, "hit test table (%d) failed, err:(%d)(%s)\n", t,pstSavm->m_lErrno, + sGetTError(pstSavm->m_lErrno)); + return ; + } + + vCreateStruck((TblDef *)pGetTblDef(t), 0); + vTblDisconnect(pstSavm, pstSavm->tblName); + + return ; +} + +/************************************************************************************************* + description:user define table + parameters: + pszCreate --create string + return: + *************************************************************************************************/ +long lDefineTable(char *pszCreate, char *pszTable) +{ + long i; + TblDef stTde; + char *p = NULL, *q = NULL; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + sfieldreplace(pszCreate, '\t', ' '); + if(NULL == (p = strcasestr(pszCreate, "create table"))) + { + fprintf(stderr, "Lost table syntax\n"); + return RC_FAIL; + } + + memset(&stTde, 0, sizeof(TblDef)); + if(RC_SUCC != lAnalysHead(pszCreate, p - pszCreate, &stTde)) + return RC_FAIL; + + strncpy(stTde.m_szTable, sfieldvalue(p + 12, "\n", 1), sizeof(stTde.m_szTable)); + srtrim(stTde.m_szTable); + sltrim(stTde.m_szTable); + + if(NULL == (q = strcasestr(p, ";"))) + { + fprintf(stderr, "Separator missing\n"); + return RC_FAIL; + } + + if(RC_SUCC != lAnalysTable(p + 12, q - p - 12, &stTde)) + return RC_FAIL; + + stTde.m_lReSize = sizecn(stTde.m_stKey, stTde.m_lIdxNum); + stTde.m_lTruck = stTde.m_lReSize + sizeof(SHTruck); + + if(RC_SUCC != lAnalysIndex(q + 1, strlen(q + 1), &stTde)) + return RC_FAIL; + + if(RC_SUCC != lCustomTable(pstSavm, stTde.m_table, stTde.m_lMaxRow, &stTde)) + { + fprintf(stderr, "create table error: %s\n", sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + strcpy(pszTable, stTde.m_szTable); + return RC_SUCC; +} + +/************************************************************************************************* + description:create table by file + parameters: + return: + SQLFld + *************************************************************************************************/ +long lCreateByFile(char *pszFile) +{ + FILE *fp = NULL; + struct stat stBuf; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + char *pszCreate = NULL, szTable[MAX_FIELD_LEN]; + + sltrim(pszFile); + srtrim(pszFile); + fprintf(stdout, "\n------------------------------------------------------SQL Result" + "-----------------------------------------------------\n"); + if(0 == strlen(pszFile)) + { + fprintf(stderr, "create table syntax error\n"); + return RC_FAIL; + } + + if(0 != access(pszFile, F_OK | R_OK )) + { + fprintf(stderr, "%s is't exist, %s\n", pszFile, strerror(errno)); + return RC_FAIL; + } + + if(0 != stat(pszFile, &stBuf)) + { + fprintf(stderr, "get %s stat error: %s\n", pszFile, strerror(errno)); + return RC_FAIL; + } + + if(!(S_IFREG == (S_IFREG & stBuf.st_mode))) + { + fprintf(stderr, "file stat error\n"); + return RC_FAIL; + } + + if(NULL == (pszCreate = (char *)calloc(stBuf.st_size, 1))) + { + fprintf(stderr, "create memory error, %s\n", strerror(errno)); + return RC_FAIL; + } + + if(NULL == (fp = fopen(pszFile, "r"))) + { + TFree(pszFile); + fprintf(stderr, "open file %s error, %s\n", strerror(errno)); + return RC_FAIL; + } + + fread(pszCreate, stBuf.st_size, 1, fp); + fclose(fp); + + if(RC_SUCC != lDefineTable(pszCreate, szTable)) + return RC_FAIL; + + fprintf(stdout, "---(%s) was created ---\n", szTable); + + + TFree(pszCreate); + return RC_SUCC; +} + +/************************************************************************************************* + description:Get the end node of the list + parameters: + return: + SQLFld + *************************************************************************************************/ +SQLFld* pGetFieldTail(SQLFld *pstRoot) +{ + SQLFld *pstList = pstRoot; + + if(!pstList) return NULL; + + while(pstList->pstNext) + pstList = pstList->pstNext; + + return pstList; +} + +/************************************************************************************************* + description:add node + parameters: + return: + SQLFld + *************************************************************************************************/ +SQLFld* pInsertFiled(SQLFld *pstRoot, SQLFld *pstNode) +{ + SQLFld *pstNext = NULL, *pstTail = pGetFieldTail(pstRoot); + + if(NULL == (pstNext = (SQLFld *)malloc(sizeof(SQLFld)))) + return pstRoot; + + memcpy(pstNext, pstNode, sizeof(SQLFld)); + pstNext->pstNext = NULL; + + if(!pstRoot) + pstRoot = pstNext; + else + pstTail->pstNext = pstNext; + + return pstRoot; +} + +/************************************************************************************************* + description:Clean up the list + parameters: + return: + *************************************************************************************************/ +void vDestroyFiled(SQLFld *pstRoot) +{ + SQLFld *pstNode = pstRoot, *pstList = NULL; + + while(pstNode) + { + pstList = pstNode; + pstNode = pstNode->pstNext; + TFree(pstList); + } +} + +/************************************************************************************************* + description:Get the number of nodes + parameters: + return: + lCnt --number of nodes + *************************************************************************************************/ +long lGetNodeFiled(SQLFld *pstRoot) +{ + long lCnt; + SQLFld *pstNode = NULL; + + for(pstNode = pstRoot, lCnt = 0; pstNode; pstNode = pstNode->pstNext, lCnt ++); + + return lCnt; +} + +/************************************************************************************************* + description:sort the field + parameters: + return: + SQLFld --root + *************************************************************************************************/ +SQLFld* pSortSQLField(SQLFld *pstRoot) +{ + TblKey stKey; + SQLFld *pstNode = NULL, *pstList = NULL; + + for(pstNode = pstRoot; pstNode; pstNode = pstNode->pstNext) + { + for(pstList = pstNode->pstNext; pstList; pstList = pstList->pstNext) + { + if(pstNode->m_stKey.m_lFrom < pstList->m_stKey.m_lFrom) + continue; + + memcpy(&stKey, &pstNode->m_stKey, sizeof(TblKey)); + memcpy(&pstNode->m_stKey, &pstList->m_stKey, sizeof(TblKey)); + memcpy(&pstList->m_stKey, &stKey, sizeof(TblKey)); + } + } + + return pstRoot; +} + +/************************************************************************************************* + description:Returns the current time in millisecond + parameters: + return: + lTime --millisecond + *************************************************************************************************/ +long lGetTiskTime() +{ + long lTime; + struct timeval t; + struct tm *ptm; + + gettimeofday(&t, NULL); + ptm = localtime(&t.tv_sec); + + lTime = ptm->tm_min * 60 * 1000 + ptm->tm_sec * 1000 + t.tv_usec / 1000; + return lTime; +} + +/************************************************************************************************* + description:Calculate time consumption (milliseconds) + parameters: + return: + szTime --Time string + *************************************************************************************************/ +char* sGetCostTime(long lTime) +{ + static char szTime[30]; + + memset(szTime, 0, sizeof(szTime)); + + if(lTime < 0) + return szTime; + if(lTime < 1000) + snprintf(szTime, sizeof(szTime), "cost:%ldms", lTime); + else + snprintf(szTime, sizeof(szTime), "cost:%lds%ldms", lTime / 1000, lTime % 1000); + return szTime; +} + +/************************************************************************************************* + description:Printing system index + parameters: + return: + *************************************************************************************************/ +void vPrintIndex() +{ + TIndex stIndex; + SATvm *pstSavm = NULL; + long lRet = 0, nRecord = 0, lTime = 0; + + memset(&stIndex, 0, sizeof(TIndex)); + if(NULL == (pstSavm = (SATvm *)pInitSATvm(SYS_TVM_INDEX))) + { + fprintf(stderr, "init SYS_TABLE_IDX failure, %s\n", sGetTError(pstSavm->m_lErrno)); + return ; + } + + pstSavm->bSearch = TYPE_SYSTEM; + pstSavm->tblName = SYS_TVM_INDEX; + pstSavm->lSize = sizeof(TIndex); + lRet = lTableDeclare(pstSavm); + if(RC_SUCC != lRet) + { + fprintf(stderr, "declare SYS_TABLE_IDX failure, (%d)(%s)\n", pstSavm->m_lErrno, + sGetTError(pstSavm->m_lErrno)); + return ; + } + + fprintf(stdout, "------------------------------------------------------------------" + "------------------------------------------------------------------------------\n"); + fprintf(stdout, "line table type table_name mark ownner Key" + " shm_id sem_id maxrows size flag stat pers update-time \n"); + fprintf(stdout, "------------------------------------------------------------------" + "------------------------------------------------------------------------------\n"); + lTime = lGetTiskTime(); + while(1) + { + memset(&stIndex, 0, sizeof(stIndex)); + lRet = lTableFetch(pstSavm, (void *)&stIndex); + if(RC_FAIL == lRet) + { + fprintf(stderr, "Fetch SYS_TABLE_IDX failure, err:(%d)(%s)\n", pstSavm->m_lErrno, + sGetTError(pstSavm->m_lErrno)); + vTableClose(pstSavm); + return ; + } + else if(RC_NOTFOUND == lRet) + break; + + nRecord ++; + + fprintf(stdout, "[%3ld]: %4d|%4ld|%-22s|%-15s|%10s|%8d|%8ld|%8ld|%8ld|%4ld|%4ld|%4d|%4ld|%20s|\n", + nRecord, stIndex.m_table, stIndex.m_lType, stIndex.m_szTable, stIndex.m_szPart, + stIndex.m_szOwner, stIndex.m_yKey, stIndex.m_shmID, stIndex.m_semID, stIndex.m_lMaxRows, + stIndex.m_lRowSize, stIndex.m_lLocal, stIndex.m_lState, stIndex.m_lPers, stIndex.m_szTime); + } + lTime -= lGetTiskTime(); + vTableClose(pstSavm); + fprintf(stdout, "----------------------------------------------------------------------%s----" + "--------------------------------------------------------------\n", sGetCostTime(-1 * lTime)); + + return ; +} + +/************************************************************************************************* + description:Print table field information + parameters: + return: + *************************************************************************************************/ +void vPrintField() +{ + TField stField; + SATvm *pstSavm = NULL; + char szPrint[256]; + long lRet = 0, lRow = 0, lTime = 0; + + memset(&stField, 0, sizeof(TField)); + if(NULL == (pstSavm = (SATvm *)pInitSATvm(SYS_TVM_FIELD))) + { + fprintf(stderr, "initial SYS_TVM_FIELD failure\n"); + return ; + } + + pstSavm->lSize = sizeof(TField); + pstSavm->tblName = SYS_TVM_FIELD; + lRet = lTableDeclare(pstSavm); + if(RC_SUCC != lRet) + { + fprintf(stderr, "declare SYS_TVM_FIELD failure, err:(%d)(%s)\n", pstSavm->m_lErrno, + sGetTError(pstSavm->m_lErrno)); + return ; + } + fprintf(stdout, "------------------------------------------------------------------------" + "------------------------\n"); + fprintf(stdout, "line table seq owner table_name field_name" + " attr len PK\n"); + fprintf(stdout, "------------------------------------------------------------------------" + "------------------------\n"); + lTime = lGetTiskTime(); + while(1) + { + memset(&stField, 0, sizeof(TField)); + lRet = lTableFetch(pstSavm, (void *)&stField); + if(RC_FAIL == lRet) + { + fprintf(stderr, "fetch SYS_TVM_FIELD failure, err:(%d)(%s)\n", pstSavm->m_lErrno, + sGetTError(pstSavm->m_lErrno)); + vTableClose(pstSavm); + return ; + } + else if(RC_NOTFOUND == lRet) + break; + + lRow ++; + + memset(szPrint, 0, sizeof(szPrint)); + if(FIELD_CHAR == stField.m_lAttr) + { + snprintf(szPrint, sizeof(szPrint), "[%3ld]: %4d|%3ld|%-20s|%-22s|%18s|STRING|" + "%4ld|%4ld|\n", lRow, stField.m_table, stField.m_lSeq, stField.m_szOwner, + stField.m_szTable, stField.m_szField, stField.m_lLen, stField.m_lIsPk); + } + else if(FIELD_LONG == stField.m_lAttr) + { + snprintf(szPrint, sizeof(szPrint), "[%3ld]: %4d|%3ld|%-20s|%-22s|%18s|NUMBER|" + "%4ld|%4ld|\n", lRow, stField.m_table, stField.m_lSeq, stField.m_szOwner, + stField.m_szTable, stField.m_szField, stField.m_lLen, stField.m_lIsPk); + } + else if(FIELD_DOUB == stField.m_lAttr) + { + snprintf(szPrint, sizeof(szPrint), "[%3ld]: %4d|%3ld|%-20s|%-22s|%18s|DOUBLE|" + "%4ld|%4ld|\n", lRow, stField.m_table, stField.m_lSeq, stField.m_szOwner, + stField.m_szTable, stField.m_szField, stField.m_lLen, stField.m_lIsPk); + } + else + { + snprintf(szPrint, sizeof(szPrint), "[%3ld]: %4d|%3ld|%-20s|%-22s|%18s| NAN |" + "%4ld|%4ld|\n", lRow, stField.m_table, stField.m_lSeq, stField.m_szOwner, + stField.m_szTable, stField.m_szField, stField.m_lLen, stField.m_lIsPk); + } + + fprintf(stdout, "%s", szPrint); + } + lTime -= lGetTiskTime(); + vTableClose(pstSavm); + fprintf(stdout, "-------------------------------------------%s-----------------------------" + "----------------\n", sGetCostTime(-1 * lTime)); + + return ; +} + +/************************************************************************************************* + description:get permit + parameters: + return: + char* + *************************************************************************************************/ +char* sPermitConv(long lPers) +{ + static char szPers[5]; + + strcpy(szPers, "----"); + szPers[4] = 0x00; + + if(lPers & OPERATE_SELECT) + szPers[0] = 's'; + if(lPers & OPERATE_UPDATE) + szPers[1] = 'u'; + if(lPers & OPERATE_DELETE) + szPers[2] = 'd'; + if(lPers & OPERATE_INSERT) + szPers[3] = 'i'; + + return szPers; +} + +/************************************************************************************************* + description:Print table field information + parameters: + return: + *************************************************************************************************/ +void vPrintDomain() +{ + TDomain stDomain; + SATvm *pstSavm = NULL; + char szPrint[512]; + long lRet = 0, lRow = 0, lTime = 0; + + memset(&stDomain, 0, sizeof(TDomain)); + if(NULL == (pstSavm = (SATvm *)pInitSATvm(SYS_TVM_DOMAIN))) + { + fprintf(stderr, "initail SYS_TVM_DOMAIN failure\n"); + return ; + } + + pstSavm->lSize = sizeof(TDomain); + pstSavm->tblName = SYS_TVM_DOMAIN; + lRet = lTableDeclare(pstSavm); + if(RC_SUCC != lRet) + { + fprintf(stderr, "declare SYS_TVM_DOMAIN failure, err:(%d)(%s)\n", pstSavm->m_lErrno, + sGetTError(pstSavm->m_lErrno)); + return ; + } + fprintf(stdout, "------------------------------------------------------------------------" + "--------------------------\n"); + fprintf(stdout, "line table mtbl table_name part ip port keep " + "tmout mtry ctry stat pers\n"); + fprintf(stdout, "------------------------------------------------------------------------" + "--------------------------\n"); + lTime = lGetTiskTime(); + while(1) + { + memset(&stDomain, 0, sizeof(TDomain)); + lRet = lTableFetch(pstSavm, (void *)&stDomain); + if(RC_FAIL == lRet) + { + fprintf(stderr, "fetch SYS_TVM_DOMAIN failure, %s\n", sGetTError(pstSavm->m_lErrno)); + vTableClose(pstSavm); + return ; + } + else if(RC_NOTFOUND == lRet) + break; + + lRow ++; + + memset(szPrint, 0, sizeof(szPrint)); + snprintf(szPrint, sizeof(szPrint), "[%3ld]: %3d|%3d|%18s|%10s|%15s|%5ld|%4ld|%5ld|%4ld|%4ld|", + lRow, stDomain.m_table, stDomain.m_mtable, stDomain.m_szTable, stDomain.m_szPart, + stDomain.m_szIp, stDomain.m_lPort, stDomain.m_lKeepLive, stDomain.m_lTimeOut, + stDomain.m_lTryMax, stDomain.m_lTryTimes); + + if(RESOURCE_INIT == stDomain.m_lStatus) + strcat(szPrint, "INIT|"); + else if(RESOURCE_EXCP == stDomain.m_lStatus) + strcat(szPrint, "EXCP|"); + else if(RESOURCE_ABLE == stDomain.m_lStatus) + strcat(szPrint, "ABLE|"); + else if(RESOURCE_STOP == stDomain.m_lStatus) + strcat(szPrint, "STOP|"); + else if(RESOURCE_AUTH == stDomain.m_lStatus) + strcat(szPrint, "AUTH|"); + + strcat(szPrint, sPermitConv(stDomain.m_lPers)); + fprintf(stdout, "%s|\n", szPrint); + fflush(stdout); + } + lTime -= lGetTiskTime(); + vTableClose(pstSavm); + fprintf(stdout, "----------------------------------------%s-----------------------------" + "---------------------\n", sGetCostTime(-1 * lTime)); + + return ; +} + +/************************************************************************************************* + description:Gets the value between the string o/d + parameters: + flag --Ignore case + return: + char* + *************************************************************************************************/ +char* sGetTruckValue(const char *s, char *o, char *d, bool flag, char *out, int olen) +{ + int len = 0; + char *p = NULL, *q = NULL; + + if (!o) + { + if (!d) + { + len = strlen(s); + return memcpy(out, s, len > olen ? olen : len); + } + + if (!(q = (flag ? strcasestr(s, d) : strstr(s, d)))) + return NULL; + + return memcpy(out, s, q - s > olen ? olen : q - s); + } + else if(!d) + { + if (!o) + { + len = strlen(s); + return memcpy(out, s, len > olen ? olen : len); + } + + if (!(p = (flag ? strcasestr(s, o) : strstr(s, o)))) + return NULL; + + snprintf(out, olen, "%s", p + strlen(o)); + return out; + } + else + { + if (!(p = (flag ? strcasestr(s, o) : strstr(s, o)))) + return NULL; + + len = strlen(o); + + if (!(q = (flag ? strcasestr(p + len, d) : strstr(s, d)))) + return NULL; + + return memcpy(out, p + len, q - p - len > olen ? olen : q - p - len); + } +} + +/************************************************************************************************* + description:Ignore case-sensitive substitution of characters in strings + parameters: + return: + s + *************************************************************************************************/ +char* sUpperWord(char *s, char *w) +{ + long len; + char *p = NULL, *q = s; + + if(!s || !w || !strlen(s)) return NULL; + + if(0 == (len = strlen(w))) return NULL; + + while(NULL != (p = strcasestr(q, w))) + { + memcpy(p, w, len); + q += len; + } + + return s; +} + +/************************************************************************************************* + description:pitch field + parameters: + return: + void --success + NULL --failure + *************************************************************************************************/ +TField *pPitchField(long lCount, TField *pstField, char *pszField) +{ + int i; + + for(i = 0; i < lCount; i ++) + { + if(!strcasecmp(pszField, pstField[i].m_szField)) + return &pstField[i]; + } + + return NULL; +} + +/************************************************************************************************* + description:User-selected field when parsing extreme + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lExtremeField(SATvm *pstSavm, char *p, long lCount, TField *pstField, SQLFld **ppstRoot) +{ + Uenum uDeco; + long lRec = 0, i; + TField *pfld = NULL; + char szField[MAX_FIELD_LEN]; + SQLFld stQField, *pstRoot = NULL; + + for(i = 0, lRec = lfieldnum(p, ","); i < lRec; i ++) + { + memset(szField, 0, sizeof(szField)); + memset(&stQField, 0, sizeof(SQLFld)); + strncpy(stQField.m_stKey.m_szField, sfieldvalue(p, ",", i + 1), + sizeof(stQField.m_stKey.m_szField)); + if(!strncmp(stQField.m_stKey.m_szField, "max(", 4)) + uDeco = MATCH_MAX; + else if(!strncmp(stQField.m_stKey.m_szField, "min(", 4)) + uDeco = MATCH_MIN; + else + return RC_FAIL; + + if(!sGetTruckValue(stQField.m_stKey.m_szField, "(", ")", true, szField, sizeof(szField))) + return RC_FAIL; + + if(NULL == (pfld = pPitchField(lCount, pstField, szField))) + { + fprintf(stderr, "field (%s) undefine\n", szField); + return RC_FAIL; + } + + vSetDecorate(&pstSavm->stUpdt, pfld->m_lLen, pfld->m_lFrom, uDeco); + stQField.m_stKey.m_lLen = pfld->m_lLen; + stQField.m_stKey.m_lAttr = pfld->m_lAttr; + stQField.m_stKey.m_lFrom = pfld->m_lFrom; + if(NULL == (pstRoot = pInsertFiled(pstRoot, &stQField))) + return RC_FAIL; + } + + *ppstRoot = pstRoot; + + return RC_SUCC; +} + +/************************************************************************************************* + description:Parse SQL condition fields + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lSelectField(SATvm *pstSavm, char *p, long lCount, TField *pstField, SQLFld **ppstRoot) +{ + TField *pfld = NULL; + long lRec = 0, i, j; + char szField[MAX_FIELD_LEN]; + SQLFld stQField, *pstRoot = NULL; + FdCond *pstExm = &pstSavm->stUpdt; + + if(0 == strcmp(p, "*")) + { + if(pstSavm->lFind & GROUP_BY) + return RC_FAIL; + + for(i = 0; i < lCount; i ++) + { + memset(&stQField, 0, sizeof(SQLFld)); + stQField.m_stKey.m_lLen = pstField[i].m_lLen; + stQField.m_stKey.m_lAttr = pstField[i].m_lAttr; + stQField.m_stKey.m_lFrom = pstField[i].m_lFrom; + strcpy(stQField.m_stKey.m_szField, pstField[i].m_szField); + + if(NULL == (pstRoot = pInsertFiled(pstRoot, &stQField))) + return RC_FAIL; + } + + *ppstRoot = pSortSQLField(pstRoot); + return RC_SUCC; + } + + for(i = 0, lRec = lfieldnum(p, ","); i < lRec; i ++) + { + memset(szField, 0, sizeof(szField)); + strncpy(szField, sfieldvalue(p, ",", i + 1), MAX_FIELD_LEN); + strimall(szField); + + if((!strcasecmp(szField, "count(*)") || + !strcasecmp(szField, "count(1)"))) + { + fprintf(stderr, "%s, Temporarily not supported\n", szField); + return RC_FAIL; + } + + if(NULL == (pfld = pPitchField(lCount, pstField, szField))) + { + fprintf(stderr, "field (%s) undefine\n", szField); + return RC_FAIL; + } + + if(pstSavm->lFind & GROUP_BY) + { + for(j = 0; j < pstExm->uFldcmp; j ++) + { + if(pstExm->stFdKey[j].uFldpos == pfld->m_lFrom) + break; + } + + if(j == pstExm->uFldcmp) + { + fprintf(stderr, "Fields (%s) are not grouped\n", szField); + return RC_FAIL; + } + } + + memset(&stQField, 0, sizeof(SQLFld)); + stQField.m_stKey.m_lLen = pfld->m_lLen; + stQField.m_stKey.m_lAttr = pfld->m_lAttr; + stQField.m_stKey.m_lFrom = pfld->m_lFrom; + strcpy(stQField.m_stKey.m_szField, szField); + if(NULL == (pstRoot = pInsertFiled(pstRoot, &stQField))) + return RC_FAIL; + } + + *ppstRoot = pstRoot; + return RC_SUCC; +} + +/************************************************************************************************* + description:Parse SQL update fields + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lUpdateField(SATvm *pstSavm, char *pszField, long lCount, TField *pstField, void *pvUpdate) +{ + void *v = NULL; + TField *pfld = NULL; + long lRec = 0, i, j; + char szValue[512], szContent[1024], szField[512], szNumber[16]; + + memset(szNumber, 0, sizeof(szNumber)); + for(i = 0, lRec = lfieldnum(pszField, ","), v = (void *)szNumber; i < lRec; i ++) + { + memset(szValue, 0, sizeof(szValue)); + memset(szField, 0, sizeof(szField)); + memset(szContent, 0, sizeof(szContent)); + strncpy(szContent, sfieldvalue(pszField, ",", i + 1), sizeof(szContent)); + strncpy(szField, sfieldvalue(szContent, "=", 1), sizeof(szField)); + strimall(szField); + + strncpy(szValue, sfieldvalue(szContent, "=", 2), sizeof(szValue)); + sltrim(szValue); + srtrim(szValue); + strimabout(szValue, "\'", "\'"); + if(NULL == (pfld = pPitchField(lCount, pstField, szField))) + { + fprintf(stderr, "field (%s) undefine\n", szField); + return RC_FAIL; + } + + vSetCodField(&pstSavm->stUpdt, pfld->m_lLen, pfld->m_lFrom); + switch(pfld->m_lAttr) + { + case FIELD_DOUB: + switch(pfld->m_lLen) + { + case 4: + *((float *)v) = atof(szValue); + break; + case 8: + *((double *)v) = atof(szValue); + break; + default: + return RC_FAIL; + } + memcpy(pvUpdate + pfld->m_lFrom, v, pfld->m_lLen); + break; + case FIELD_LONG: + switch(pfld->m_lLen) + { + case 2: + *((sint *)v) = atoi(szValue); + break; + case 4: + *((int *)v) = atoi(szValue); + break; + case 8: + *((llong *)v) = atol(szValue); + break; + default: + return RC_FAIL; + } + memcpy(pvUpdate + pfld->m_lFrom, v, pfld->m_lLen); + break; + case FIELD_CHAR: + strncpy(pvUpdate + pfld->m_lFrom, szValue, pfld->m_lLen); + break; + default: + return RC_FAIL; + } + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:execute SQL-select + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lExeUpdate(SATvm *pstSavm, TIndex *pstIndex, void *pvNew, char *pvData, BOOL bRmt) +{ + long lRet; + + pstSavm->pstVoid = (void *)pvData; + pstSavm->tblName = pstIndex->m_table; + pstSavm->lSize = pstIndex->m_lRowSize; + if(bRmt) + lRet = lTvmUpdate(pstSavm, (void *)pvNew); + else + lRet = lUpdate(pstSavm, (void *)pvNew); + if(RC_SUCC != lRet) + { + fprintf(stderr, "update table (%s) failure, %s\n", pstIndex->m_szTable, + sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + fprintf(stdout, "---(%ld) records updated -ep(%d)--\n", pstSavm->m_lEffect, pstSavm->m_lEType); + return RC_SUCC; +} + +/************************************************************************************************* + description:execute SQL-delete + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lExeDelete(SATvm *pstSavm, TIndex *pstIndex, char *pvData, BOOL bRmt) +{ + long lRet; + + pstSavm->pstVoid = (void *)pvData; + pstSavm->tblName = pstIndex->m_table; + pstSavm->lSize = pstIndex->m_lRowSize; + if(bRmt) + lRet = lTvmDelete(pstSavm); + else + lRet = lDelete(pstSavm); + if(RC_SUCC != lRet) + return RC_FAIL; + + fprintf(stdout, "---(%ld) records deleted -ep(%d)--\n", pstSavm->m_lEffect, pstSavm->m_lEType); + return RC_SUCC; +} + +/************************************************************************************************* + description:execute SQL-insert + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lExeInsert(SATvm *pstSavm, TIndex *pstIndex, void *pvInsert, BOOL bRmt) +{ + long lRet; + + if(bRmt) + pstSavm->tblName = pstIndex->m_table; + else + { + if(RC_SUCC != lInitSATvm(pstSavm, pstIndex->m_table)) + return RC_FAIL; + } + + pstSavm->pstVoid = (void *)pvInsert; + pstSavm->lSize = pstIndex->m_lRowSize; + if(bRmt) + lRet = lTvmInsert(pstSavm); + else + lRet = lInsert(pstSavm); + if(RC_SUCC != lRet) + { + fprintf(stderr, "insert table (%s) failure, %s\n", pstIndex->m_szTable, + sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + fprintf(stdout, "---(%ld) records inserted ---\n", pstSavm->m_lEffect); + return RC_SUCC; +} + +/************************************************************************************************* + description:Parse SQL condition fields + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lConditField(SATvm *pstSavm, char *pszWhere, long lCount, TField *pstField, void *pvWhere) +{ + long n, i, j; + void *v = NULL; + TField *pfld = NULL; + char szValue[512], szCondit[1024], szField[512], szNumber[16]; + + if(strcasestr(pszWhere, " or ")) + { + fprintf(stderr, "Unsupported query methods\n"); + return RC_FAIL; + } + + memset(szNumber, 0, sizeof(szNumber)); + for(i = 0, v = (void *)szNumber, n = lfieldnum(pszWhere, " AND "); i < n; i ++) + { + memset(szValue, 0, sizeof(szValue)); + memset(szField, 0, sizeof(szField)); + memset(szCondit, 0, sizeof(szCondit)); + strncpy(szCondit, sfieldvalue(pszWhere, " AND ", i + 1), sizeof(szCondit)); + + strncpy(szField, sfieldvalue(szCondit, "=", 1), sizeof(szField)); + strimall(szField); + strncpy(szValue, sfieldvalue(szCondit, "=", 2), sizeof(szValue)); + sltrim(szValue); + srtrim(szValue); + strimabout(szValue, "\'", "\'"); + if(!strcmp(szField, "1") && !strcmp(szValue, "1")) + continue; + + if(NULL == (pfld = pPitchField(lCount, pstField, szField))) + { + fprintf(stderr, "field (%s) undefine\n", szField); + return RC_FAIL; + } + + vSetCodField(&pstSavm->stCond, pfld->m_lLen, pfld->m_lFrom); + switch(pfld->m_lAttr) + { + case FIELD_DOUB: + switch(pfld->m_lLen) + { + case 4: + *((float *)v) = atof(szValue); + break; + case 8: + *((double *)v) = atof(szValue); + break; + default: + return RC_FAIL; + } + memcpy(pvWhere + pfld->m_lFrom, v, pfld->m_lLen); + break; + case FIELD_LONG: + switch(pfld->m_lLen) + { + case 2: + *((sint *)v) = atoi(szValue); + break; + case 4: + *((int *)v) = atoi(szValue); + break; + case 8: + *((llong *)v) = atol(szValue); + break; + default: + return RC_FAIL; + } + memcpy(pvWhere + pfld->m_lFrom, v, pfld->m_lLen); + break; + case FIELD_CHAR: + strncpy(pvWhere + pfld->m_lFrom, szValue, pfld->m_lLen); + break; + default: + return RC_FAIL; + } + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:execute SQL-count + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lCountSelect(SATvm *pstSavm, TIndex *pstIndex, char *pvData, BOOL bRmt) +{ + size_t lRet, lSum = 0; + + pstSavm->pstVoid = (void *)pvData; + pstSavm->tblName = pstIndex->m_table; + pstSavm->lSize = pstIndex->m_lRowSize; + if(bRmt) + lRet = lTvmCount(pstSavm, &lSum); + else + lRet = lCount(pstSavm, &lSum); + if(lRet != RC_SUCC) + { + fprintf(stderr, "count table (%s) failure, %s\n", pstIndex->m_szTable, + sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + fprintf(stdout, "---(%ld) records selected -ep(%d)--\n", pstSavm->m_lEffect, pstSavm->m_lEType); + fprintf(stdout, "COUNT(*)\n"); + fprintf(stdout, "%zu\n", lSum); + fflush(stdout); + + return RC_SUCC; +} + +/************************************************************************************************* + description:execute SQL-group + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lExeGroup(SATvm *pstSavm, TIndex *pstIndex, SQLFld *pstRoot, char *pvData, BOOL bRmt) +{ + TblKey *pstKey = NULL; + SQLFld *pstNode = NULL; + Rowgrp *pstList = NULL; + char *pvResult = NULL; + size_t i, lOffset, lRows, lRet; + + pstSavm->pstVoid = (void *)pvData; + pstSavm->tblName = pstIndex->m_table; + pstSavm->lSize = pstIndex->m_lRowSize; + + if(bRmt) + lRet = lTvmGroup(pstSavm, &lRows, (void **)&pvResult); + else + lRet = lGroup(pstSavm, &lRows, (void **)&pvResult); + if(RC_SUCC != lRet) + { + if(NO_DATA_FOUND != pstSavm->m_lErrno) + { + fprintf(stderr, "Group table (%s) failure,%s\n", pstIndex->m_szTable, + sGetTError(pstSavm->m_lErrno)); + } + + return RC_FAIL; + } + + for(pstNode = pstRoot; pstNode; pstNode = pstNode->pstNext) + fprintf(stdout, "%s ", pstNode->m_stKey.m_szField); + fprintf(stdout, "\n"); + + for(i = 0; i < lRows && i < pstSavm->m_lEffect; i ++) + { + lOffset = pstIndex->m_lRowSize * i; + for(pstNode = pstRoot; pstNode; pstNode = pstNode->pstNext) + { + if(!strcasecmp(pstNode->m_stKey.m_szField, "count(*)") || + !strcasecmp(pstNode->m_stKey.m_szField, "count(1)")) + continue; + + pstKey = &pstNode->m_stKey; + switch(pstKey->m_lAttr) + { + case FIELD_DOUB: + switch(pstKey->m_lLen) + { + case 4: + fprintf(stdout, "%f ", *((float *)(pvResult + lOffset + pstKey->m_lFrom))); + break; + case 8: + fprintf(stdout, "%f ", *((double *)(pvResult + lOffset + pstKey->m_lFrom))); + break; + default: + break; + } + break; + case FIELD_LONG: + switch(pstKey->m_lLen) + { + case 2: + fprintf(stdout, "%d ", *((sint *)(pvResult + lOffset + pstKey->m_lFrom))); + break; + case 4: + fprintf(stdout, "%d ", *((int *)(pvResult + lOffset + pstKey->m_lFrom))); + break; + case 8: + fprintf(stdout, "%lld ", *((llong *)(pvResult + lOffset + pstKey->m_lFrom))); + break; + default: + break; + } + break; + case FIELD_CHAR: + fprintf(stdout, "%.*s ", (int)pstKey->m_lLen, pvResult + lOffset + pstKey->m_lFrom); + break; + default: + break; + } + } + fprintf(stdout, "\n"); + fflush(stdout); + } + TFree(pvResult); + + fprintf(stdout, "---(%ld) records selected, ep(%d)---\n", pstSavm->m_lEffect, pstSavm->m_lEType); + return RC_SUCC; +} + +/************************************************************************************************* + description:execute SQL-select + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lExeSelect(SATvm *pstSavm, TIndex *pstIndex, SQLFld *pstRoot, char *pvData, char *pszFile, + char *pszDem, BOOL bRmt) +{ + FILE *fp = NULL; + TblKey *pstKey = NULL; + SQLFld *pstNode = NULL; + Rowgrp *pstList = NULL; + size_t i, lOffset, lRows, lRet; + char szDelmit[64], *pvResult = NULL; + + memset(szDelmit, 0, sizeof(szDelmit)); + pstSavm->pstVoid = (void *)pvData; + pstSavm->tblName = pstIndex->m_table; + pstSavm->lSize = pstIndex->m_lRowSize; + if(bRmt) + lRet = lTvmQuery(pstSavm, &lRows, (void **)&pvResult); + else + lRet = lQuery(pstSavm, &lRows, (void **)&pvResult); + if(RC_SUCC != lRet) + { + if(NO_DATA_FOUND != pstSavm->m_lErrno) + { + fprintf(stderr, "Query table (%s) failure,%s\n", pstIndex->m_szTable, + sGetTError(pstSavm->m_lErrno)); + } + + return RC_FAIL; + } + + if(pszFile) + { + if(NULL == (fp = fopen(pszFile, "wb"))) + { + pstSavm->m_lErrno = FILE_NOTFOUND; + return RC_FAIL; + } + + strncpy(szDelmit, pszDem, sizeof(szDelmit)); + } + else + { + fp = stdout; + strcpy(szDelmit, " "); + } + + for(pstNode = pstRoot; pstNode; pstNode = pstNode->pstNext) + fprintf(fp, "%s ", pstNode->m_stKey.m_szField); + fprintf(fp, "\n"); + + for(i = 0; i < lRows && i < pstSavm->m_lEffect; i ++) + { + lOffset = pstIndex->m_lRowSize * i; + for(pstNode = pstRoot; pstNode; pstNode = pstNode->pstNext) + { + if(!strcasecmp(pstNode->m_stKey.m_szField, "count(*)") || + !strcasecmp(pstNode->m_stKey.m_szField, "count(1)")) + continue; + + pstKey = &pstNode->m_stKey; + switch(pstKey->m_lAttr) + { + case FIELD_DOUB: + switch(pstKey->m_lLen) + { + case 4: + fprintf(fp, "%f%s", *((float *)(pvResult + lOffset + pstKey->m_lFrom)), szDelmit); + break; + case 8: + fprintf(fp, "%f%s", *((double *)(pvResult + lOffset + pstKey->m_lFrom)), szDelmit); + break; + default: + break; + } + break; + case FIELD_LONG: + switch(pstKey->m_lLen) + { + case 2: + fprintf(fp, "%d%s", *((sint *)(pvResult + lOffset + pstKey->m_lFrom)), szDelmit); + break; + case 4: + fprintf(fp, "%d%s", *((int *)(pvResult + lOffset + pstKey->m_lFrom)), szDelmit); + break; + case 8: + fprintf(fp, "%lld%s", *((llong *)(pvResult + lOffset + pstKey->m_lFrom)), szDelmit); + break; + default: + break; + } + break; + case FIELD_CHAR: + fprintf(fp, "%.*s%s", (int)pstKey->m_lLen, pvResult + lOffset + pstKey->m_lFrom, szDelmit); + break; + default: + break; + } + } + fprintf(fp, "\n"); + fflush(fp); + } + TFree(pvResult); + + if(pszFile) + { + fprintf(stdout, "---(%ld) records unload ---\n", pstSavm->m_lEffect); + fclose(fp); + } + else + fprintf(stdout, "---(%ld) records selected, ep(%d)---\n", pstSavm->m_lEffect, pstSavm->m_lEType); + + return RC_SUCC; +} + +/************************************************************************************************* + description:execute SQL-Seque + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lParseSequece(SATvm *pstSavm, char *pszSQName, char *pszFiled, BOOL bRmt) +{ + long lRet; + ulong ulSeque; + + if(strcasecmp(pszFiled, "nextval")) + { + pstSavm->m_lErrno = SQL_ERR_FIELD; + return RC_FAIL; + } + + if(bRmt) + lRet = lTvmSelectSeque(pstSavm, pszSQName, &ulSeque); + else + lRet = lSelectSeque(pstSavm, pszSQName, &ulSeque); + if(RC_SUCC != lRet) + return RC_FAIL; + + fprintf(stdout, "%s\n", pszFiled); + fprintf(stdout, "%lu\n", ulSeque); + + return RC_SUCC; +} + +/************************************************************************************************* + description:Parse SQL decorative fields + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lParseAdorn(SATvm *pstSavm, char *pszAdorn, long lCount, TField *pstField) +{ + TField *pfld = NULL; + long lNumber, i, j; + char szWord[64], szField[512], szOrder[512]; + + if(0 == strlen(pszAdorn)) + return RC_SUCC; + + memset(szField, 0, sizeof(szField)); + memset(szOrder, 0, sizeof(szOrder)); + if(!strncasecmp(pszAdorn, "group by", 8)) + { + pstSavm->lFind |= GROUP_BY; + if(!strcasestr(pszAdorn, "order by")) + { + if(!sGetTruckValue(pszAdorn, "group by", NULL, true, szField, sizeof(szField))) + return RC_FAIL; + strimall(szField); + } + else + { + if(!sGetTruckValue(pszAdorn, "group by", "order by", true, szField, sizeof(szField))) + return RC_FAIL; + strimall(szField); + + if(!sGetTruckValue(pszAdorn, "order by", NULL, true, szOrder, sizeof(szOrder))) + return RC_FAIL; + sltrim(szOrder); + } + + for(i = 0, lNumber = lgetstrnum(szField, ",") + 1; i < lNumber; i ++) + { + memset(szWord, 0, sizeof(szWord)); + strncpy(szWord, sgetvalue(szField, ",", i + 1), sizeof(szWord)); + if(NULL == (pfld = pPitchField(lCount, pstField, szWord))) + { + fprintf(stderr, "field (%s) undefine\n", szWord); + return RC_FAIL; + } + + vSetDecorate(&pstSavm->stUpdt, pfld->m_lLen, pfld->m_lFrom, GROUP_BY); + } + + if(strlen(szOrder) > 0) + { + for(i = 0, lNumber = lgetstrnum(szOrder, ",") + 1; i < lNumber; i ++) + { + memset(szWord, 0, sizeof(szWord)); + strncpy(szWord, sfieldvalue(szOrder, ",", i + 1), sizeof(szWord)); + if(NULL == (pfld = pPitchField(lCount, pstField, sfieldvalue(szWord, " ", 1)))) + { + fprintf(stderr, "field (%s) undefine\n", sfieldvalue(szWord, " ", 1)); + return RC_FAIL; + } + + for(j = 0; j < pstSavm->stUpdt.uFldcmp; j ++) + { + if(pstSavm->stUpdt.stFdKey[j].uFldpos == pfld->m_lFrom) + { + if(!strcasecmp(sfieldvalue(szWord, " ", 2), "desc")) + pstSavm->stUpdt.stFdKey[j].uDecorate |= ORDER_DESC; + else + pstSavm->stUpdt.stFdKey[j].uDecorate |= ORDER_ASC; + break; + } + } + + if(j == pstSavm->stUpdt.uFldcmp) + return RC_FAIL; + } + } + + return RC_SUCC; + } + else if(!strncasecmp(pszAdorn, "order by", 8)) + { + pstSavm->lFind |= ORDER_BY; + if(!sGetTruckValue(pszAdorn, "order by", NULL, true, szOrder, sizeof(szOrder))) + return RC_FAIL; + sltrim(szOrder); + + for(i = 0, lNumber = lgetstrnum(szOrder, ",") + 1; i < lNumber; i ++) + { + memset(szWord, 0, sizeof(szWord)); + strncpy(szWord, sfieldvalue(szOrder, ",", i + 1), sizeof(szWord)); + if(NULL == (pfld = pPitchField(lCount, pstField, sfieldvalue(szWord, " ", 1)))) + { + fprintf(stderr, "field (%s) undefine\n", sfieldvalue(szWord, " ", 1)); + return RC_FAIL; + } + + if(!strcasecmp(sfieldvalue(szWord, " ", 2), "desc")) + vSetDecorate(&pstSavm->stUpdt, pfld->m_lLen, pfld->m_lFrom, ORDER_DESC); + else + vSetDecorate(&pstSavm->stUpdt, pfld->m_lLen, pfld->m_lFrom, ORDER_ASC); + } + + return RC_SUCC; + } + + return RC_FAIL; +} + +/************************************************************************************************* + description:execute SQL-extreme + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lExeExtreme(SATvm *pstSavm, TIndex *pstIndex, SQLFld *pstRoot, void *pvData, BOOL bRmt) +{ + long lRet; + TblKey *pstKey = NULL; + SQLFld *pstNode = NULL; + void *pvResult = NULL; + + if(NULL == (pvResult = malloc(pstIndex->m_lRowSize))) + return RC_FAIL; + + pstSavm->pstVoid = (void *)pvData; + pstSavm->tblName = pstIndex->m_table; + pstSavm->lSize = pstIndex->m_lRowSize; + if(bRmt) + lRet = lTvmExtreme(pstSavm, pvResult); + else + lRet = lExtreme(pstSavm, pvResult); + if(RC_SUCC != lRet) + { + TFree(pvResult); + vDestroyFiled(pstRoot); + fprintf(stderr, "extreme table (%s) failure, %s\n", pstIndex->m_szTable, + sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + for(pstNode = pstRoot; pstNode; pstNode = pstNode->pstNext) + fprintf(stdout, "%s ", pstNode->m_stKey.m_szField); + fprintf(stdout, "\n"); + + for(pstNode = pstRoot; pstNode; pstNode = pstNode->pstNext) + { + pstKey = &pstNode->m_stKey; + switch(pstKey->m_lAttr) + { + case FIELD_DOUB: + switch(pstKey->m_lLen) + { + case 4: + fprintf(stdout, "%f ", *((float *)(pvResult + pstKey->m_lFrom))); + break; + case 8: + fprintf(stdout, "%f ", *((double *)(pvResult + pstKey->m_lFrom))); + break; + default: + break; + } + break; + case FIELD_LONG: + switch(pstKey->m_lLen) + { + case 2: + fprintf(stdout, "%d ", *((sint *)(pvResult + pstKey->m_lFrom))); + break; + case 4: + fprintf(stdout, "%d ", *((int *)(pvResult + pstKey->m_lFrom))); + break; + case 8: + fprintf(stdout, "%lld ", *((llong *)(pvResult + pstKey->m_lFrom))); + break; + default: + break; + } + break; + case FIELD_CHAR: + fprintf(stdout, "%.*s ", (int)pstKey->m_lLen, (char *)(pvResult + pstKey->m_lFrom)); + break; + default: + break; + } + } + + fprintf(stdout, "\n"); + fflush(stdout); + TFree(pvResult); + fprintf(stdout, "---(%ld)records selected -ep(%d)--\n", pstSavm->m_lEffect, pstSavm->m_lEType); + + vDestroyFiled(pstRoot); + return RC_SUCC; +} + +/************************************************************************************************* + description:Parse SQL-select fields + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lParseSelect(SATvm *pstSavm, char *pszTable, char *pszField, char *pszWhere, char *pszFile, + char *pszDem, char *pszAdorn, BOOL bRmt) +{ + TIndex stIndex; + SQLFld *pstRoot = NULL; + void *pvWhere = NULL; + TField *pstField = NULL; + size_t lOut = 0, lRet; + + memset(&stIndex, 0, sizeof(TIndex)); + strncpy(stIndex.m_szPart, sgetvalue(pszTable, "@", 2), sizeof(stIndex.m_szPart)); + strncpy(stIndex.m_szTable, sgetvalue(pszTable, "@", 1), sizeof(stIndex.m_szTable)); + supper(stIndex.m_szTable); + if(0x00 == stIndex.m_szPart[0]) + strcpy(stIndex.m_szPart, sGetNode()); + + if(!strcmp(stIndex.m_szTable, "SEQUENCE")) + return lParseSequece(pstSavm, stIndex.m_szPart, pszField, bRmt); + + if(bRmt) + { + if(RC_SUCC != lTvmGetTblIndex(pstSavm, stIndex.m_szTable, stIndex.m_szPart, &stIndex)) + return RC_FAIL; + + if(RC_SUCC != lTvmGetTblField(pstSavm, stIndex.m_table, &lOut, &pstField)) + return RC_FAIL; + } + else + { + if(RC_SUCC != lGetTblIndex(pstSavm, stIndex.m_szTable, stIndex.m_szPart, &stIndex)) + return RC_FAIL; + + if(RC_SUCC != lGetTblField(stIndex.m_table, &lOut, &pstField)) + return RC_FAIL; + + if(RC_SUCC != lInitSATvm(pstSavm, stIndex.m_table)) + return RC_FAIL; + } + + pstSavm->stCond.uFldcmp = 0; + pstSavm->stUpdt.uFldcmp = 0; + if(RC_SUCC != lParseAdorn(pstSavm, pszAdorn, lOut, pstField)) + { + pstSavm->m_lErrno = SQL_SYNTX_ERR; + goto ERR_SELECT; + } + + if(NULL == (pvWhere = (char *)calloc(stIndex.m_lRowSize, sizeof(char)))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + goto ERR_SELECT; + } + + if(RC_SUCC != _lConditField(pstSavm, pszWhere, lOut, pstField, pvWhere)) + { + pstSavm->m_lErrno = SQL_ERR_WHERE; + goto ERR_SELECT; + } + + if((!strcasecmp(pszField, "count(*)") || !strcasecmp(pszField, "count(1)")) && + !(pstSavm->lFind & GROUP_BY)) + { + TFree(pstField); + if(RC_SUCC != _lCountSelect(pstSavm, &stIndex, pvWhere, bRmt)) + goto ERR_SELECT; + + TFree(pvWhere); + return RC_SUCC; + } + else if(!strncasecmp(pszField, "max(", 4) || !strncasecmp(pszField, "min(", 4)) + { + if(RC_SUCC != _lExtremeField(pstSavm, pszField, lOut, pstField, &pstRoot)) + { + pstSavm->m_lErrno = SQL_ERR_FIELD; + goto ERR_SELECT; + } + + if(RC_SUCC != _lExeExtreme(pstSavm, &stIndex, pstRoot, pvWhere, bRmt)) + goto ERR_SELECT; + + TFree(pstField); + TFree(pvWhere); + return RC_SUCC; + } + + if(RC_SUCC != _lSelectField(pstSavm, pszField, lOut, pstField, &pstRoot)) + { + pstSavm->m_lErrno = SQL_ERR_FIELD; + goto ERR_SELECT; + } + + TFree(pstField); + if(pstSavm->lFind & GROUP_BY) + lRet = _lExeGroup(pstSavm, &stIndex, pstRoot, pvWhere, bRmt); + else + lRet = _lExeSelect(pstSavm, &stIndex, pstRoot, pvWhere, pszFile, pszDem, bRmt); + if(RC_SUCC != lRet) + goto ERR_SELECT; + + TFree(pvWhere); + vDestroyFiled(pstRoot); + return RC_SUCC; + +ERR_SELECT: + TFree(pvWhere); + TFree(pstField); + vDestroyFiled(pstRoot); + return RC_FAIL; +} + +/************************************************************************************************** + description:Parse SQL-select syntax + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + **************************************************************************************************/ +long _lSelectSyntax(SATvm *pstSavm, char *pszSQL, char *pszFile, char *pszDem, BOOL bRmt) +{ + char szTable[512], *p = NULL; + char szWhere[512], szField[512], szAdorn[1024]; + + memset(szWhere, 0, sizeof(szWhere)); + memset(szField, 0, sizeof(szField)); + memset(szTable, 0, sizeof(szTable)); + memset(szAdorn, 0, sizeof(szAdorn)); + + if(!sGetTruckValue(pszSQL, "select ", "from ", true, szField, sizeof(szField))) + { + pstSavm->m_lErrno = SQL_FIELD_NIL; + return RC_FAIL; + } + + strimall(szField); + if(!strlen(szField)) + { + pstSavm->m_lErrno = SQL_FIELD_NIL; + return RC_FAIL; + } + + if(NULL != strcasestr(pszSQL, "where ")) + { + if(!sGetTruckValue(pszSQL, "from ", "where", true, szTable, sizeof(szTable))) + { + pstSavm->m_lErrno = SQL_TABLE_NIL; + return RC_FAIL; + } + + if(!sGetTruckValue(pszSQL, "where ", NULL, true, szWhere, sizeof(szWhere))) + { + pstSavm->m_lErrno = SQL_TABLE_NIL; + return RC_FAIL; + } + + if((p = strcasestr(szWhere, "group")) || (p = strcasestr(szWhere, "order"))) + { + strcpy(szAdorn, p); + memset(p, 0, sizeof(szWhere) - (p - szWhere)); + } + + sltrim(szWhere); + srtrim(szWhere); + sUpperWord(szWhere, " AND "); + DEL_TAIL_CHAR(szWhere, ';'); + } + else + { + if(!sGetTruckValue(pszSQL, "from ", NULL, true, szTable, sizeof(szTable))) + { + pstSavm->m_lErrno = SQL_TABLE_NIL; + return RC_FAIL; + } + + sltrim(szTable); + if((p = strcasestr(szTable, "group")) || (p = strcasestr(szTable, "order"))) + { + strcpy(szAdorn, p); + memset(p, 0, sizeof(szTable) - (p - szTable)); + } + + DEL_TAIL_CHAR(szTable, ';'); + } + + strimall(szTable); + vSCRDebug("DEBUG:select field:[%s]", szField); + vSCRDebug("DEBUG:select table:[%s]", szTable); + vSCRDebug("DEBUG:select where:[%s]", szWhere); + vSCRDebug("DEBUG:select adorn:[%s]", szAdorn); + + return _lParseSelect(pstSavm, szTable, szField, szWhere, pszFile, pszDem, szAdorn, bRmt); +} + +/************************************************************************************************* + description:Parse SQL-update fields + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lParseUpdate(SATvm *pstSavm, char *pszTable, char *pszField, char *pszWhere, BOOL bRmt) +{ + TIndex stIndex; + size_t lOut = 0, lRet; + TField *pstField = NULL; + void *pvWhere = NULL, *pvUpdate = NULL; + + memset(&stIndex, 0, sizeof(TIndex)); + strncpy(stIndex.m_szPart, sgetvalue(pszTable, "@", 2), sizeof(stIndex.m_szPart)); + strncpy(stIndex.m_szTable, sgetvalue(pszTable, "@", 1), sizeof(stIndex.m_szTable)); + supper(stIndex.m_szTable); + if(0x00 == stIndex.m_szPart[0]) + strcpy(stIndex.m_szPart, sGetNode()); + + if(bRmt) + { + if(RC_SUCC != lTvmGetTblIndex(pstSavm, stIndex.m_szTable, stIndex.m_szPart, &stIndex)) + return RC_FAIL; + + if(RC_SUCC != lTvmGetTblField(pstSavm, stIndex.m_table, &lOut, &pstField)) + return RC_FAIL; + } + else + { + if(RC_SUCC != lGetTblIndex(pstSavm, stIndex.m_szTable, stIndex.m_szPart, &stIndex)) + return RC_FAIL; + + if(RC_SUCC != lGetTblField(stIndex.m_table, &lOut, &pstField)) + return RC_FAIL; + + if(RC_SUCC != lInitSATvm(pstSavm, stIndex.m_table)) + return RC_FAIL; + } + + pstSavm->stCond.uFldcmp = 0; + pstSavm->stUpdt.uFldcmp = 0; + if(NULL == (pvUpdate = (char *)calloc(stIndex.m_lRowSize, sizeof(char)))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + goto ERR_UPDATE; + } + + if(RC_SUCC != _lUpdateField(pstSavm, pszField, lOut, pstField, pvUpdate)) + { + pstSavm->m_lErrno = SQL_ERR_FIELD; + goto ERR_UPDATE; + } + + if(NULL == (pvWhere = (char *)calloc(stIndex.m_lRowSize, sizeof(char)))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + goto ERR_UPDATE; + } + + if(RC_SUCC != _lConditField(pstSavm, pszWhere, lOut, pstField, pvWhere)) + { + pstSavm->m_lErrno = SQL_ERR_WHERE; + goto ERR_UPDATE; + } + + TFree(pstField); + if(RC_SUCC != _lExeUpdate(pstSavm, &stIndex, pvUpdate, pvWhere, bRmt)) + goto ERR_UPDATE; + + TFree(pvWhere); + TFree(pvUpdate); + return RC_SUCC; + +ERR_UPDATE: + TFree(pvWhere); + TFree(pvUpdate); + TFree(pstField); + return RC_FAIL; +} + + +/************************************************************************************************** + description:Parse SQL-update syntax + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + **************************************************************************************************/ +long _lUpdateSyntax(SATvm *pstSavm, char *pszSQL, BOOL bRmt) +{ + char szTable[MAX_FIELD_LEN]; + char szWhere[1024], szField[1024]; + + memset(szWhere, 0, sizeof(szWhere)); + memset(szField, 0, sizeof(szField)); + memset(szTable, 0, sizeof(szTable)); + + if(!sGetTruckValue(pszSQL, "update ", "set ", true, szTable, sizeof(szTable))) + { + pstSavm->m_lErrno = SQL_TABLE_NIL; + return RC_FAIL; + } + strimall(szTable); + + if(!strcasestr(pszSQL, "where")) + { + pstSavm->m_lErrno = SQL_WHERE_NIL; + return RC_FAIL; + } + + if(!sGetTruckValue(pszSQL, "set ", "where", true, szField, sizeof(szField))) + { + pstSavm->m_lErrno = SQL_FIELD_NIL; + return RC_FAIL; + } + + sltrim(szField); + srtrim(szField); + if(!strlen(szField)) + { + pstSavm->m_lErrno = SQL_FIELD_NIL; + return RC_FAIL; + } + + if(!sGetTruckValue(pszSQL, "where ", NULL, true, szWhere, sizeof(szWhere))) + { + pstSavm->m_lErrno = SQL_WHERE_NIL; + return RC_FAIL; + } + + sltrim(szWhere); + srtrim(szWhere); + sUpperWord(szWhere, " AND "); + DEL_TAIL_CHAR(szWhere, ';'); + + vSCRDebug("DEBUG:update field:[%s]", szField); + vSCRDebug("DEBUG:update table:[%s]", szTable); + vSCRDebug("DEBUG:update where:[%s]", szWhere); + + return _lParseUpdate(pstSavm, szTable, szField, szWhere, bRmt); +} + +/************************************************************************************************* + description:Parse SQL-delete fields + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lParseDelete(SATvm *pstSavm, char *pszTable, char *pszWhere, BOOL bRmt) +{ + TIndex stIndex; + size_t lOut = 0, lRet; + TField *pstField = NULL; + void *pvWhere = NULL; + + memset(&stIndex, 0, sizeof(TIndex)); + strncpy(stIndex.m_szPart, sgetvalue(pszTable, "@", 2), sizeof(stIndex.m_szPart)); + strncpy(stIndex.m_szTable, sgetvalue(pszTable, "@", 1), sizeof(stIndex.m_szTable)); + supper(stIndex.m_szTable); + if(0x00 == stIndex.m_szPart[0]) + strcpy(stIndex.m_szPart, sGetNode()); + + if(bRmt) + { + if(RC_SUCC != lTvmGetTblIndex(pstSavm, stIndex.m_szTable, stIndex.m_szPart, &stIndex)) + return RC_FAIL; + + if(RC_SUCC != lTvmGetTblField(pstSavm, stIndex.m_table, &lOut, &pstField)) + return RC_FAIL; + } + else + { + if(RC_SUCC != lGetTblIndex(pstSavm, stIndex.m_szTable, stIndex.m_szPart, &stIndex)) + return RC_FAIL; + + if(RC_SUCC != lGetTblField(stIndex.m_table, &lOut, &pstField)) + return RC_FAIL; + + if(RC_SUCC != lInitSATvm(pstSavm, stIndex.m_table)) + return RC_FAIL; + } + + pstSavm->stCond.uFldcmp = 0; + pstSavm->stUpdt.uFldcmp = 0; + if(NULL == (pvWhere = (char *)calloc(stIndex.m_lRowSize, sizeof(char)))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + goto ERR_DELETE; + } + + if(RC_SUCC != _lConditField(pstSavm, pszWhere, lOut, pstField, pvWhere)) + { + pstSavm->m_lErrno = SQL_ERR_WHERE; + goto ERR_DELETE; + } + + TFree(pstField); + if(RC_SUCC != _lExeDelete(pstSavm, &stIndex, pvWhere, bRmt)) + goto ERR_DELETE; + + TFree(pvWhere); + return RC_SUCC; + +ERR_DELETE: + TFree(pvWhere); + TFree(pstField); + return RC_FAIL; +} + +/************************************************************************************************** + description:Parse SQL-delete syntax + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + **************************************************************************************************/ +long _lDeleteSyntax(SATvm *pstSavm, char *pszSQL, BOOL bRmt) +{ + char szTable[MAX_FIELD_LEN], szWhere[1024]; + + memset(szWhere, 0, sizeof(szWhere)); + memset(szTable, 0, sizeof(szTable)); + if(strcasestr(pszSQL, " where ")) + { + if(!sGetTruckValue(pszSQL, " from ", " where ", true, szTable, sizeof(szTable))) + { + pstSavm->m_lErrno = SQL_TABLE_NIL; + return RC_FAIL; + } + strimall(szTable); + + if(!sGetTruckValue(pszSQL, " where ", NULL, true, szWhere, sizeof(szWhere))) + { + pstSavm->m_lErrno = SQL_WHERE_NIL; + return RC_FAIL; + } + sltrim(szWhere); + srtrim(szWhere); + sUpperWord(szWhere, " AND "); + DEL_TAIL_CHAR(szWhere, ';'); + } + else + { + if(!sGetTruckValue(pszSQL, " from ", NULL, true, szTable, sizeof(szTable))) + { + pstSavm->m_lErrno = SQL_TABLE_NIL; + return RC_FAIL; + } + DEL_TAIL_CHAR(szTable, ';'); + strimall(szTable); + } + + vSCRDebug("DEBUG:delete table:[%s]", szTable); + vSCRDebug("DEBUG:delete where:[%s]", szWhere); + + return _lParseDelete(pstSavm, szTable, szWhere, bRmt); +} + +/************************************************************************************************* + description:Parse SQL-insert values + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lInsertField(SATvm *pstSavm, char *pszValues, SQLFld *pstRoot, void *pvInsert) +{ + void *v = NULL; + TblKey *pstKey = NULL; + SQLFld *pstNode = NULL; + long lRec = 0, i, j, lFld; + char szValue[512], szNumber[16]; + + memset(szNumber, 0, sizeof(szNumber)); + lFld = lGetNodeFiled(pstRoot); + if(lFld != (lRec = lfieldnum(pszValues, ","))) + { + pstSavm->m_lErrno = SQL_FAV_MATCH; + return RC_FAIL; + } + + for(i = 0, v = (void *)szNumber, pstNode = pstRoot; i < lRec; i ++, pstNode = pstNode->pstNext) + { + memset(szValue, 0, sizeof(szValue)); + strncpy(szValue, sfieldvalue(pszValues, ",", i + 1), sizeof(szValue)); + sltrim(szValue); + srtrim(szValue); + strimabout(szValue, "\'", "\'"); + + if(!pstNode) + { + pstSavm->m_lErrno = SQL_FAV_MATCH; + return RC_FAIL; + } + + pstKey = &pstNode->m_stKey; + switch(pstKey->m_lAttr) + { + case FIELD_DOUB: + switch(pstKey->m_lLen) + { + case 4: + *((float *)v) = atof(szValue); + memcpy(pvInsert + pstKey->m_lFrom, v, pstKey->m_lLen); + break; + case 8: + *((double *)v) = atof(szValue); + memcpy(pvInsert + pstKey->m_lFrom, v, pstKey->m_lLen); + break; + default: + break; + } + break; + case FIELD_LONG: + switch(pstKey->m_lLen) + { + case 2: + *((sint *)v) = atoi(szValue); + memcpy(pvInsert + pstKey->m_lFrom, v, pstKey->m_lLen); + break; + case 4: + *((int *)v) = atoi(szValue); + memcpy(pvInsert + pstKey->m_lFrom, v, pstKey->m_lLen); + break; + case 8: + *((llong *)v) = atol(szValue); + memcpy(pvInsert + pstKey->m_lFrom, v, pstKey->m_lLen); + break; + default: + break; + } + break; + case FIELD_CHAR: + memcpy(pvInsert + pstKey->m_lFrom, szValue, + MIN(strlen(szValue), pstKey->m_lLen)); + break; + default: + break; + } + } + + if(pstNode) + { + pstSavm->m_lErrno = SQL_FAV_MATCH; + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Parse SQL-insert fields + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lParseInsert(SATvm *pstSavm, char *pszTable, char *pszField, char *pszValues, BOOL bRmt) +{ + TIndex stIndex; + size_t lOut = 0, lRet; + SQLFld *pstRoot = NULL; + TField *pstField = NULL; + void *pvInsert = NULL; + + memset(&stIndex, 0, sizeof(TIndex)); + strncpy(stIndex.m_szPart, sgetvalue(pszTable, "@", 2), sizeof(stIndex.m_szPart)); + strncpy(stIndex.m_szTable, sgetvalue(pszTable, "@", 1), sizeof(stIndex.m_szTable)); + supper(stIndex.m_szTable); + if(0x00 == stIndex.m_szPart[0]) + strcpy(stIndex.m_szPart, sGetNode()); + + if(bRmt) + { + if(RC_SUCC != lTvmGetTblIndex(pstSavm, stIndex.m_szTable, stIndex.m_szPart, &stIndex)) + return RC_FAIL; + + if(RC_SUCC != lTvmGetTblField(pstSavm, stIndex.m_table, &lOut, &pstField)) + return RC_FAIL; + } + else + { + if(RC_SUCC != lGetTblIndex(pstSavm, stIndex.m_szTable, stIndex.m_szPart, &stIndex)) + return RC_FAIL; + + if(RC_SUCC != lGetTblField(stIndex.m_table, &lOut, &pstField)) + return RC_FAIL; + + if(RC_SUCC != lInitSATvm(pstSavm, stIndex.m_table)) + return RC_FAIL; + } + + pstSavm->stCond.uFldcmp = 0; + pstSavm->stUpdt.uFldcmp = 0; + if(NULL == (pvInsert = (char *)calloc(stIndex.m_lRowSize, sizeof(char)))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + goto ERR_INSERT; + } + + if(RC_SUCC != _lSelectField(pstSavm, pszField, lOut, pstField, &pstRoot)) + { + pstSavm->m_lErrno = SQL_ERR_FIELD; + goto ERR_INSERT; + } + + if(RC_SUCC != _lInsertField(pstSavm, pszValues, pstRoot, pvInsert)) + goto ERR_INSERT; + +//vPrintHex(pvInsert, stIndex.m_lRowSize); + + TFree(pstField); + if(RC_SUCC != _lExeInsert(pstSavm, &stIndex, pvInsert, bRmt)) + goto ERR_INSERT; + + TFree(pvInsert); + return RC_SUCC; + +ERR_INSERT: + TFree(pvInsert); + TFree(pstField); + return RC_FAIL; +} + +/************************************************************************************************** + description:Parse SQL-insert syntax + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + **************************************************************************************************/ +long _lInsertSyntax(SATvm *pstSavm, char *pszSQL, BOOL bRmt) +{ + char szTable[MAX_FIELD_LEN]; + char szValues[1024], szField[1024]; + + memset(szField, 0, sizeof(szField)); + memset(szTable, 0, sizeof(szTable)); + memset(szValues, 0, sizeof(szValues)); + if(!sGetTruckValue(pszSQL, " into ", "values", true, szValues, sizeof(szValues))) + { + pstSavm->m_lErrno = SQL_TABLE_NIL; + return RC_FAIL; + } + + if(strstr(szValues, "(")) // 说明有选定字段 + { + if(!sGetTruckValue(szValues, NULL, "(", true, szTable, sizeof(szTable))) + { + pstSavm->m_lErrno = SQL_TABLE_NIL; + return RC_FAIL; + } + + if(!sGetTruckValue(szValues, "(", ")", true, szField, sizeof(szField))) + { + pstSavm->m_lErrno = SQL_FIELD_NIL; + return RC_FAIL; + } + + if(!strlen(strimall(szField))) + { + pstSavm->m_lErrno = SQL_FIELD_NIL; + return RC_FAIL; + } + } + else + { + strcpy(szField, "*"); + strncpy(szTable, szValues, sizeof(szTable)); + } + strimall(szTable); + + memset(szValues, 0, sizeof(szValues)); + if(!sGetTruckValue(pszSQL, "values", NULL, true, szValues, sizeof(szValues))) + { + pstSavm->m_lErrno = SQL_WHERE_NIL; + return RC_FAIL; + } + + if(!strimabout(szValues, "(", ")")) + { + pstSavm->m_lErrno = SQL_WHERE_NIL; + return RC_FAIL; + } + + if(!strlen(szValues)) + { + pstSavm->m_lErrno = SQL_WHERE_NIL; + return RC_FAIL; + } + + sltrim(szValues); + srtrim(szValues); + sUpperWord(szValues, " AND "); + + vSCRDebug("DEBUG:insert field:[%s]", szField); + vSCRDebug("DEBUG:insert table:[%s]", szTable); + vSCRDebug("DEBUG:insert field:[%s]", szValues); + + return _lParseInsert(pstSavm, szTable, szField, szValues, bRmt); +} + +/************************************************************************************************** + description:Parse SQL-truncate syntax + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + **************************************************************************************************/ +long _lTruncateSyntax(SATvm *pstSavm, char *pszSQL, BOOL bRmt) +{ + long lRet; + TIndex stIndex; + char szTable[MAX_FIELD_LEN]; + + memset(szTable, 0, sizeof(szTable)); + memset(&stIndex, 0, sizeof(TIndex)); + if(!sGetTruckValue(pszSQL, " table ", NULL, true, szTable, sizeof(szTable))) + { + pstSavm->m_lErrno = SQL_TABLE_NIL; + return RC_FAIL; + } + + strimall(szTable); + strncpy(stIndex.m_szPart, sgetvalue(szTable, "@", 2), sizeof(stIndex.m_szPart)); + strncpy(stIndex.m_szTable, sgetvalue(szTable, "@", 1), sizeof(stIndex.m_szTable)); + supper(stIndex.m_szTable); + if(0x00 == stIndex.m_szPart[0]) + strcpy(stIndex.m_szPart, sGetNode()); + + if(bRmt) + { + if(RC_SUCC != lTvmGetTblIndex(pstSavm, stIndex.m_szTable, stIndex.m_szPart, &stIndex)) + return RC_FAIL; + + pstSavm->tblName = stIndex.m_table; + } + else + { + if(RC_SUCC != lGetTblIndex(pstSavm, stIndex.m_szTable, stIndex.m_szPart, &stIndex)) + return RC_FAIL; + + if(NULL == (pstSavm = (SATvm *)pInitSATvm(stIndex.m_table))) + return RC_FAIL; + } + + pstSavm->lSize = stIndex.m_lRowSize; + if(bRmt) + lRet = lTvmTruncate(pstSavm, stIndex.m_table); + else + lRet = lTruncate(pstSavm, stIndex.m_table); + if(RC_SUCC != lRet) + return RC_FAIL; + + fprintf(stdout, "---(%ld) records deleted ---\n", pstSavm->m_lEffect); + return RC_SUCC; +} + +/************************************************************************************************** + description:Parse SQL-drop syntax + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + **************************************************************************************************/ +long _lDropSyntax(SATvm *pstSavm, char *pszSQL, BOOL bRmt) +{ + long lRet; + TIndex stIndex; + char szTable[MAX_FIELD_LEN]; + + memset(szTable, 0, sizeof(szTable)); + memset(&stIndex, 0, sizeof(TIndex)); + if(!sGetTruckValue(pszSQL, " table ", NULL, true, szTable, sizeof(szTable))) + { + pstSavm->m_lErrno = SQL_TABLE_NIL; + return RC_FAIL; + } + + strimall(szTable); + strncpy(stIndex.m_szPart, sgetvalue(szTable, "@", 2), sizeof(stIndex.m_szPart)); + strncpy(stIndex.m_szTable, sgetvalue(szTable, "@", 1), sizeof(stIndex.m_szTable)); + supper(stIndex.m_szTable); + if(0x00 == stIndex.m_szPart[0]) + strcpy(stIndex.m_szPart, sGetNode()); + + if(bRmt) + { + if(RC_SUCC != lTvmGetTblIndex(pstSavm, stIndex.m_szTable, stIndex.m_szPart, &stIndex)) + return RC_FAIL; + + pstSavm->tblName = stIndex.m_table; + } + else + { + if(RC_SUCC != lGetTblIndex(pstSavm, stIndex.m_szTable, stIndex.m_szPart, &stIndex)) + return RC_FAIL; + + if(NULL == (pstSavm = (SATvm *)pInitSATvm(stIndex.m_table))) + return RC_FAIL; + } + + pstSavm->lSize = stIndex.m_lRowSize; + if(bRmt) + lRet = lTvmDropTable(pstSavm, stIndex.m_table); + else + lRet = lDropTable(pstSavm, stIndex.m_table); + if(RC_SUCC != lRet) + return RC_FAIL; + + fprintf(stdout, "---(%s) was deleted ---\n", szTable); + + return RC_SUCC; +} + +/************************************************************************************************** + description:Parse SQL-load syntax + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + **************************************************************************************************/ +long _lLoadSyntax(SATvm *pstSavm, char *pszSQL) +{ + TIndex stIndex; + char szFile[256], szParam[256], szDelmit[64]; + +// load from a.txt DELIMITER ',' insert into tablename@bcs + memset(szFile, 0, sizeof(szFile)); + memset(szParam, 0, sizeof(szParam)); + memset(szDelmit, 0, sizeof(szDelmit)); + memset(&stIndex, 0, sizeof(TIndex)); + + if(!sGetTruckValue(pszSQL, "insert into ", NULL, true, szParam, sizeof(szParam))) + { + pstSavm->m_lErrno = SQL_TABLE_NIL; + return RC_FAIL; + } + + sltrim(szParam); + srtrim(szParam); + strimall(szParam); + strncpy(stIndex.m_szPart, sgetvalue(szParam, "@", 2), sizeof(stIndex.m_szPart)); + strncpy(stIndex.m_szTable, sgetvalue(szParam, "@", 1), sizeof(stIndex.m_szTable)); + supper(stIndex.m_szTable); + if(0x00 == stIndex.m_szPart[0]) + strcpy(stIndex.m_szPart, sGetNode()); + + if(RC_SUCC != lGetTblIndex(pstSavm, stIndex.m_szTable, stIndex.m_szPart, &stIndex)) + return RC_FAIL; + + memset(szParam, 0, sizeof(szParam)); + if(!sGetTruckValue(pszSQL, "load from ", "insert", true, szParam, sizeof(szParam))) + { + pstSavm->m_lErrno = FILE_NOT_RSET; + return RC_FAIL; + } + + strncpy(szFile, sfieldvalue(szParam, " ", 1), sizeof(szFile)); + strimall(szFile); + + strncpy(szDelmit, sfieldvalue(szParam, " ", 2), sizeof(szDelmit)); + strimall(szDelmit); + if(!strcasecmp(szDelmit, "DELIMITER")) + { + strncpy(szDelmit, sfieldvalue(szParam, " ", 3), sizeof(szDelmit)); + strimall(szDelmit); + strimabout(szDelmit, "\"", "\""); + strimabout(szDelmit, "\'", "\'"); + } + else + strcpy(szDelmit, ","); + + if(strlen(sfieldvalue(szParam, " ", 4))) + { + pstSavm->m_lErrno = SQL_SYNTX_ERR; + return RC_FAIL; + } + + if(RC_SUCC != lImportFile(stIndex.m_table, szFile, szDelmit)) + return RC_FAIL; + + fprintf(stdout, "---(%ld) records inserted ---\n", pstSavm->m_lEffect); + + return RC_SUCC; +} + +/************************************************************************************************** + description:Parse SQL-unload syntax + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + **************************************************************************************************/ +long _lUnloadSyntax(SATvm *pstSavm, char *pszSQL, BOOL bRmt) +{ + char szFile[256], szParam[256], szDelmit[64], *p = NULL; + +// unload to a.txt DELIMITER ',' select * from tablename@bcs + memset(szFile, 0, sizeof(szFile)); + memset(szParam, 0, sizeof(szParam)); + memset(szDelmit, 0, sizeof(szDelmit)); + + if(NULL == (p = strcasestr(pszSQL, "select"))) + { + pstSavm->m_lErrno = SQL_SYNTX_ERR; + return RC_FAIL; + } + + memset(szParam, 0, sizeof(szParam)); + if(!sGetTruckValue(pszSQL, "unload to ", "select", true, szParam, sizeof(szParam))) + { + pstSavm->m_lErrno = FILE_NOT_RSET; + return RC_FAIL; + } + + sltrim(szParam); + srtrim(szParam); + strncpy(szFile, sfieldvalue(szParam, " ", 1), sizeof(szFile)); + strimall(szFile); + + strncpy(szDelmit, sfieldvalue(szParam, " ", 2), sizeof(szDelmit)); + strimall(szDelmit); + if(!strcasecmp(szDelmit, "DELIMITER")) + { + strncpy(szDelmit, sfieldvalue(szParam, " ", 3), sizeof(szDelmit)); + strimall(szDelmit); + strimabout(szDelmit, "\"", "\""); + strimabout(szDelmit, "\'", "\'"); + } + else + strcpy(szDelmit, ","); + + if(strlen(sfieldvalue(szParam, " ", 4))) + { + pstSavm->m_lErrno = SQL_SYNTX_ERR; + return RC_FAIL; + } + + return _lSelectSyntax(pstSavm, p, szFile, szDelmit, bRmt); +} + +/************************************************************************************************** + description:Parse and execute SQL statements + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + **************************************************************************************************/ +long lExecuteSQL(SATvm *pstSavm, char *pszSQL) +{ + if(!pszSQL || !strlen(pszSQL)) + { + pstSavm->m_lErrno = SQL_SYNTX_ERR; + return RC_FAIL; + } + + pstSavm->lFind = 0; + pstSavm->stCond.uFldcmp = 0; + pstSavm->stUpdt.uFldcmp = 0; + if(!strncasecmp(pszSQL, "begin ", 6) && strcmp(sfieldvalue(pszSQL, ";", 2), "work")) + { + vBeginWork(pstSavm); + fprintf(stdout, "---begin work, %s---\n", sGetTError(pstSavm->m_lErrno)); + return RC_SUCC; + } + + else if(!strncasecmp(pszSQL, "end ", 4) && strcmp(sfieldvalue(pszSQL, ";", 2), "work")) + { + vEndWork(pstSavm); + fprintf(stdout, "---end work, %s---\n", sGetTError(pstSavm->m_lErrno)); + return RC_SUCC; + } + else if(!strncasecmp(pszSQL, "commit ", 7) && strcmp(sfieldvalue(pszSQL, ";", 2), "work")) + { + lCommitWork(pstSavm); + fprintf(stdout, "---commit work, %s---\n", sGetTError(pstSavm->m_lErrno)); + return RC_SUCC; + } + else if(!strncasecmp(pszSQL, "rollback ", 9) && strcmp(sfieldvalue(pszSQL, ";", 2), "work")) + { + lRollbackWork(pstSavm); + fprintf(stdout, "---(%ld) records rollback, %s---\n", pstSavm->m_lEffect, + sGetTError(pstSavm->m_lErrno)); + return RC_SUCC; + } + else if(!strncasecmp(pszSQL, "select ", 7)) + return _lSelectSyntax(pstSavm, pszSQL, NULL, NULL, false); + else if(!strncasecmp(pszSQL, "update ", 7)) + return _lUpdateSyntax(pstSavm, pszSQL, false); + else if(!strncasecmp(pszSQL, "delete ", 7)) + return _lDeleteSyntax(pstSavm, pszSQL, false); + else if(!strncasecmp(pszSQL, "insert ", 7)) + return _lInsertSyntax(pstSavm, pszSQL, false); + else if(!strncasecmp(pszSQL, "truncate ", 9)) + return _lTruncateSyntax(pstSavm, pszSQL, false); + else if(!strncasecmp(pszSQL, "drop ", 5)) + return _lDropSyntax(pstSavm, pszSQL, false); + else if(!strncasecmp(pszSQL, "load ", 5)) + return _lLoadSyntax(pstSavm, pszSQL); + else if(!strncasecmp(pszSQL, "unload ", 7)) + return _lUnloadSyntax(pstSavm, pszSQL, false); + else + { + pstSavm->m_lErrno = SQL_NOT_SUPPT; + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************** + description:Parse and execute SQL statements + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + **************************************************************************************************/ +long lExecuteTvm(SATvm *pstSavm, char *pszSQL) +{ + if(!pszSQL || !strlen(pszSQL)) + { + pstSavm->m_lErrno = SQL_SYNTX_ERR; + return RC_FAIL; + } + + pstSavm->m_lTimes = 0; + pstSavm->m_lErrno = 0; + sfieldreplace(pszSQL, '\t', ' '); + if(!strncasecmp(pszSQL, "begin ", 6) && strcmp(sfieldvalue(pszSQL, ";", 2), "work")) + { + lTvmBeginWork(pstSavm); + fprintf(stdout, "---begin work, %s---\n", sGetTError(pstSavm->m_lErrno)); + return RC_SUCC; + } + else if(!strncasecmp(pszSQL, "end ", 4) && strcmp(sfieldvalue(pszSQL, ";", 2), "work")) + { + lTvmEndWork(pstSavm); + fprintf(stdout, "---end work, %s---\n", sGetTError(pstSavm->m_lErrno)); + return RC_SUCC; + } + else if(!strncasecmp(pszSQL, "commit ", 7) && strcmp(sfieldvalue(pszSQL, ";", 2), "work")) + { + lTvmCommitWork(pstSavm); + fprintf(stdout, "---commit work, %s---\n", sGetTError(pstSavm->m_lErrno)); + return RC_SUCC; + } + else if(!strncasecmp(pszSQL, "rollback ", 9) && strcmp(sfieldvalue(pszSQL, ";", 2), "work")) + { + lTvmRollbackWork(pstSavm); + fprintf(stdout, "---(%ld) records rollback, %s---\n", pstSavm->m_lEffect, + sGetTError(pstSavm->m_lErrno)); + return RC_SUCC; + } + else if(!strncasecmp(pszSQL, "select ", 7)) + return _lSelectSyntax(pstSavm, pszSQL, NULL, NULL, true); + else if(!strncasecmp(pszSQL, "update ", 7)) + return _lUpdateSyntax(pstSavm, pszSQL, true); + else if(!strncasecmp(pszSQL, "delete ", 7)) + return _lDeleteSyntax(pstSavm, pszSQL, true); + else if(!strncasecmp(pszSQL, "insert ", 7)) + return _lInsertSyntax(pstSavm, pszSQL, true); + else if(!strncasecmp(pszSQL, "truncate ", 9)) + return _lTruncateSyntax(pstSavm, pszSQL, true); + else if(!strncasecmp(pszSQL, "drop ", 5)) + return _lDropSyntax(pstSavm, pszSQL, true); +/* + else if(!strncasecmp(pszSQL, "load ", 5)) + return _lLoadSyntax(pstSavm, pszSQL, true); +*/ + else if(!strncasecmp(pszSQL, "unload ", 7)) + return _lUnloadSyntax(pstSavm, pszSQL, true); + else + { + pstSavm->m_lErrno = SQL_NOT_SUPPT; + return RC_FAIL; + } + + return RC_SUCC; + return RC_SUCC; +} + +/************************************************************************************************** + description:Boot STVM + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + **************************************************************************************************/ +long lStartSystem(TBoot *pstBoot, char *pszMode) +{ + Benum eMode = 0; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + if(0 != access(getenv("TVMCFG"), R_OK)) + { + fprintf(stdout, "The startup parameter is not set and started by default\n"); + if(RC_SUCC != lDefaultBoot()) + return RC_FAIL; + } + + if(pszMode && !strcmp(pszMode, "o")) // offline + { + fprintf(stdout, "Warning:TVM will start offline\n"); + fflush(stdout); + eMode = 1; + } + + if(!bIsTvmBoot()) + { + if(RC_SUCC != lStartupTvm(pstBoot)) + { + fprintf(stderr, "failed to boot TVM, %s\n", sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + } + + if(RC_SUCC != lBootLocal(pstSavm, pstBoot, eMode)) + { + fprintf(stderr, "failed to boot LIS, %s\n", sGetTError(pstSavm->m_lErrno)); + return RC_SUCC; + } + + fprintf(stderr, "start TVM : (%s)\n", sGetTError(pstSavm->m_lErrno)); + + return RC_SUCC; +} + +/************************************************************************************************** + description:Stop STVM + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + **************************************************************************************************/ +long lStopSystem(TBoot *pstBoot, char *pszApp) +{ + BOOL bRet; + long i, lPid = 0; + FILE *fp = NULL; + static char szCmd[128], szPid[20]; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + memset(szPid, 0, sizeof(szPid)); + memset(szCmd, 0, sizeof(szCmd)); + snprintf(szCmd, sizeof(szCmd), "ps -u %s|grep -E \"%s|%s\"|awk '{print $1}'", + getenv("LOGNAME"), TVM_LOCAL_SERV, TVM_REMOTE_DOM); + + if(TVM_BOOT_CLUSTER == pstBoot->m_lBootType) + lOfflineNotify(pstSavm, pstBoot->m_lBootPort); + + if(NULL == (fp = popen(szCmd, "r"))) + { + fprintf(stderr, "popen execute comman err:(%s)\n", strerror(errno)); + return RC_FAIL; + } + + for(fp; fgets(szPid, sizeof(szPid), fp) != NULL; memset(szPid, 0, sizeof(szPid))) + { + strimall(szPid); + lPid = atol(szPid); + if(lPid <= 0 || lPid == getpid()) + continue; + + for(i = 0; i < 200; i ++, usleep(50000)) + { + if(FALSE == (bRet = bExistProcess(lPid))) + break; + } + + if(!bRet) continue; + kill(atol(szPid), SIGKILL); + } + pclose(fp); + + if(!bIsTvmBoot()) return RC_SUCC; + + if(RC_SUCC != lShutdownTvm()) + { + fprintf(stderr, "showdown node failed, %s\n", sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************** + description:Print Stvm parameter information + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + **************************************************************************************************/ +void vPrintParam(char *pszOpt) +{ + long n = 0, i = 0; + + if(!pszOpt || (0 == (n = strlen(pszOpt)))) return ; + + if(!bIsTvmBoot()) + return ; + + for(i = 0, n = strlen(pszOpt); i < n; i ++) + { + switch(pszOpt[i]) + { + case 'y': + vPrintIndex(); + break; + case 't': + vPrintField(); + break; + case 'd': + vPrintDomain(); + break; + default: + return ; + } + } + + return ; +} + +/************************************************************************************************** + description:Output table space Usage + parameters: + return: + **************************************************************************************************/ +void vPrintAmount(int t, char *pszTable, int nValid, int nMax) +{ + double dPer; + int i, nPer; + + if(nValid < 0 || nMax <= 0) return ; + + dPer = nValid * 100.0 / nMax; + nPer = nValid * 50 / nMax > 0 ? nValid * 50 / nMax : 1; + + fprintf(stdout, "TABLE:[%3d][%-20s]: [", t, pszTable); + if(dPer < 60.00) + fprintf(stdout, "\033[42;32m"); + else if(dPer < 70.00) + fprintf(stdout, "\033[45;35m"); + else if(dPer < 80.00) + fprintf(stdout, "\033[46;36m"); + else if(dPer < 90.00) + fprintf(stdout, "\033[43;33m"); + else + fprintf(stdout, "\033[41;31m"); + + fflush(stdout); + for(i = 0; i < nPer; i ++) + { + fprintf(stdout, "|"); + fflush(stdout); + } + + fprintf(stdout, "\033[0m"); + for(i; i < 50; i ++) + fprintf(stdout, " "); + fprintf(stdout, "] %.4f%%, (%d/%d)\n", dPer, nValid, nMax); + fflush(stdout); +} + +/************************************************************************************************** + description:print system table space usage + parameters: + return: + **************************************************************************************************/ +void vTableAmount() +{ + size_t i, lOut = 0; + RunTime *pstRun = NULL; + TIndex stIndex, *pstIndex = NULL; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + memset(&stIndex, 0, sizeof(TIndex)); + stIndex.m_lLocal = RES_LOCAL_SID; + + pstSavm->pstVoid = &stIndex; + pstSavm->bSearch = TYPE_SYSTEM; + pstSavm->tblName = SYS_TVM_INDEX; + pstSavm->lSize = sizeof(TIndex); + if(RC_SUCC != lQuery(pstSavm, &lOut, (void *)&pstIndex)) + { + if(NO_DATA_FOUND == pstSavm->m_lErrno) + pstSavm->m_lErrno = TBL_NOT_FOUND; + return ; + } + + if(lOut <= 0) return ; + + fprintf(stdout, "The amount of table is using as follows:\n\n"); + for(i = 0; i < lOut; i ++) + { + pstRun = (RunTime *)pGetRunTime(pstSavm, pstIndex[i].m_table); + pstRun->m_shmID = pstIndex[i].m_shmID; + if(NULL == (pstRun = pInitHitTest(pstSavm, pstIndex[i].m_table))) + continue; + + vPrintAmount(pstIndex[i].m_table, pstIndex[i].m_szTable, lGetTblValid(pstIndex[i].m_table), + lGetTblRow(pstIndex[i].m_table)); + vTblDisconnect(pstSavm, pstIndex[i].m_table); + } + TFree(pstIndex); + fprintf(stdout, "\n"); + + return ; +} + +/************************************************************************************************** + description:STVM operation function description + parameters: + return: + **************************************************************************************************/ +void vPrintFunc(char *s) +{ + fprintf(stdout, "\nUsage:\t%s -wspfco[oytd]\n", s); + fprintf(stdout, "\t-w[o]\t\t--Startup STVM\n"); + fprintf(stdout, "\t-s[o]\t\t--Shutdown STVM\n"); + fprintf(stdout, "\t-p(ytd)\t\t--Output STVM Running information\n"); + fprintf(stdout, "\t-f\t\t--Display the amount of table\n"); + fprintf(stdout, "\t-t\t\t--Output the table struck\n"); + fprintf(stdout, "\t-c[file]\t--Compile the startup config file\n"); + fprintf(stdout, "\t-o[file]\t--Decompile the startup config\n"); + fprintf(stdout, "\n"); + fprintf(stdout, "\n"); + fprintf(stdout, "\033[4m\033[45;33mDESCRIPTION\033[0m\n"); + fprintf(stdout, "\t\033[0m\033[33;40mSQL\t\t--SQL control\033[0m\n"); + fprintf(stdout, "\t\033[0m\033[33;40mDOM\t\t--DOM control\033[0m\n"); + fprintf(stdout, "\n"); +} + +/************************************************************************************************* + description:add history command + parameters: + return: + *************************************************************************************************/ +void vAddHistory(char *s) +{ + FILE *fp = NULL; + char szPath[512]; + + memset(szPath, 0, sizeof(szPath)); + snprintf(szPath, sizeof(szPath), "%s/%s", getenv("TVMDBD"), STVM_SQL_LINE); + if(NULL == (fp = fopen(szPath, "a+"))) + return ; + + fprintf(fp, "%s\n", s); + fclose(fp); +} + +/************************************************************************************************* + description:set user history command + parameters: + return: + *************************************************************************************************/ +void vSetHistory() +{ + long lRow = 0, i; + FILE *fp = NULL, *fb = NULL; + char szPath[512], szLine[512], szBak[512]; + + memset(szBak, 0, sizeof(szBak)); + memset(szPath, 0, sizeof(szPath)); + memset(szLine, 0, sizeof(szLine)); + snprintf(szBak, sizeof(szBak), "%s/%s@", getenv("TVMDBD"), STVM_SQL_LINE); + snprintf(szPath, sizeof(szPath), "%s/%s", getenv("TVMDBD"), STVM_SQL_LINE); + if(NULL == (fp = fopen(szPath, "r"))) + return ; + + if(NULL == (fb = fopen(szBak, "w"))) + { + fclose(fp); + return ; + } + + while(fgets(szLine, sizeof(szLine), fp) != NULL) + lRow ++; + + fseek(fp, 0L, SEEK_SET); + for(i = 0; i < lRow && fgets(szLine, sizeof(szLine), fp); i ++) + { + if(100 < lRow - i) + continue; + fprintf(fb, "%s", szLine); + strimcrlf(szLine); + add_history(szLine); + memset(szLine, 0, sizeof(szLine)); + } + + fclose(fp); + fclose(fb); + + rename(szBak, szPath); +} + +/************************************************************************************************** + description:Execute SQL functions + parameters: + return: + **************************************************************************************************/ +void vSQLStatement(int argc, char *argv[]) +{ + char *pszUser, *p, szSQL[2048]; + long i = 0, lRec, lRemote = 0, lRet; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + system("stty erase ^?"); + system("stty erase ^H"); + fprintf(stdout, "\n%s\n", sFuncVersion()); + for(i = 2; i < argc; i ++) + { + if(!strcasecmp(argv[i], "--debug=on")) + elog = 1; + else if(!strncasecmp(argv[i], "--connect=", 10)) + { + if(NULL == (pszUser = strstr(argv[i], "--connect="))) + { + fprintf(stderr, "Invalid address:%s\n", argv[i]); + exit(-1); + } + + pszUser += 10; + if(NULL == (p = strstr(pszUser, "@"))) + { + fprintf(stderr, "Invalid domain:%s\n", pszUser); + exit(-1); + } + + vSetNode(sfieldvalue(pszUser, "@", 1)); + pszUser = pszUser + (p - pszUser) + 1; + lRemote = atol(sfieldvalue(pszUser, ":", 2)); + if(RC_SUCC != lTvmConnect(pstSavm, sfieldvalue(pszUser, ":", 1), lRemote, 5)) + { + fprintf(stderr, "connect to the server %s:%ld failure, %s\n", + sfieldvalue(pszUser, ":", 1), lRemote, sGetTError(pstSavm->m_lErrno)); + exit(-1); + } + + fprintf(stdout, "Connect domain:%s@%s:%ld server successfully!!\n\n", sGetNode(), + sfieldvalue(pszUser, ":", 1), lRemote); + fflush(stdout); + } + } + + vSetHistory(); + while(1) + { + if(NULL == (pszUser = readline("M-SQL>"))) + continue; + + if(!strcmp(pszUser, "q") || !strcmp(pszUser, "Q") || !strcmp(pszUser, "exit")) + break; + + add_history(pszUser); + vAddHistory(pszUser); + if(!strcasecmp(pszUser, "clear")) + { + system("clear"); + TFree(pszUser); + continue; + } + else if(!strncasecmp(pszUser, "create", 6)) + { + if(lRemote > 0) + { + fprintf(stderr, "could not create table on Remte mode\n"); + TFree(pszUser); + continue; + } + + lCreateByFile(pszUser + 6); + fprintf(stdout, "\n\n\n"); + TFree(pszUser); + continue; + } + + strimcrlf(pszUser); + lRec = lfieldnum(pszUser, ";"); + for(i = 0; i < lRec; i ++) + { + memset(szSQL, 0, sizeof(szSQL)); + strncpy(szSQL, sfieldvalue(pszUser, ";", i + 1), sizeof(szSQL)); + sltrim(szSQL); + srtrim(szSQL); + if(!strlen(szSQL)) continue; + + sfieldreplace(szSQL, '\t', ' '); + fprintf(stdout, "\n------------------------------------------------------SQL Result" + "-----------------------------------------------------\n"); + if(lRemote > 0) + lRet = lExecuteTvm(pstSavm, szSQL); + else + lRet = lExecuteSQL(pstSavm, szSQL); + if(RC_SUCC != lRet) + { + fprintf(stderr, "execute M-SQL error, (%d)(%s)\n", pstSavm->m_lErrno, + sGetTError(pstSavm->m_lErrno)); + continue; + } + } + TFree(pszUser); + fprintf(stdout, "\n\n\n"); + } + + if(lRemote) vTvmDisconnect(pstSavm); + exit(0); +} + +/************************************************************************************************** + description:Output domain table information + parameters: + return: + **************************************************************************************************/ +void vPrintDomTable() +{ + size_t i, lOut = 0; + char szPrint[512]; + TDomain *pstDomain = NULL; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + if(RC_SUCC != lExportTable(SYS_TVM_DOMAIN, &lOut, (void **)&pstDomain)) + { + fprintf(stderr, "get domain node info failed, %s\n", sGetTError(pstSavm->m_lErrno)); + return ; + } + + fprintf(stdout, "\tROW DOMAINID TABLE_NAME PART STAT PERS\n"); + fprintf(stdout, "\t----------------------------------------------------------\n"); + for(i = 0; i < lOut; i ++) + { + memset(szPrint, 0, sizeof(szPrint)); + snprintf(szPrint, sizeof(szPrint), "\t[%-3ld]: %-10s %-18s %-10s ", i, + pstDomain[i].m_szOwner, pstDomain[i].m_szTable, pstDomain[i].m_szPart); + + if(RESOURCE_INIT == pstDomain[i].m_lStatus) + strcat(szPrint, "INIT "); + else if(RESOURCE_EXCP == pstDomain[i].m_lStatus) + strcat(szPrint, "EXCP "); + else if(RESOURCE_ABLE == pstDomain[i].m_lStatus) + strcat(szPrint, "ABLE "); + else if(RESOURCE_STOP == pstDomain[i].m_lStatus) + strcat(szPrint, "STOP "); + else if(RESOURCE_AUTH == pstDomain[i].m_lStatus) + strcat(szPrint, "AUTH "); + + fprintf(stdout, "%s %s\n", szPrint, sPermitConv(pstDomain[i].m_lPers)); + fflush(stdout); + } + TFree(pstDomain); + fprintf(stdout, "\t----------------------------------------------------------\n"); + + return ; +} + +/************************************************************************************************** + description:Manually connect to the remote domain + parameters: + return: + **************************************************************************************************/ +void vConnectDomain(char *pszDomain, TBoot *pstBoot) +{ + TDomain stDomain; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + if(!strlen(strimall(pszDomain))) + { + fprintf(stderr, "*illegal domain name\n"); + return ; + } + + if(RC_SUCC != lInitSATvm(pstSavm, SYS_TVM_DOMAIN)) + { + fprintf(stderr, "*initail SYS_TVM_DOMAIN failure, %s\n", sGetTError(pstSavm->m_lErrno)); + return ; + } + + conditinit(pstSavm, stDomain, SYS_TVM_DOMAIN); + stringsetv(pstSavm, stDomain, m_szOwner, pszDomain); + decorate(pstSavm, TDomain, m_szOwner, FIRST_ROW); + if(RC_SUCC != lSelect(pstSavm, (void *)&stDomain)) + { + fprintf(stderr, "*get domain %s error, %s\n", pszDomain, sGetTError(pstSavm->m_lErrno)); + return ; + } + + if(RC_SUCC != lConnectNotify(pstSavm, &stDomain, pstBoot->m_lBootPort)) + { + fprintf(stderr, "*reconnect remote domain(%s) failure, %s\n", pszDomain, + sGetTError(pstSavm->m_lErrno)); + return ; + } + + vPrintDomTable(); + return ; +} + +/************************************************************************************************** + description:Clone remote domain table data + parameters: + return: + **************************************************************************************************/ +void vPullTableDomain(char *pszParam) +{ + TABLE table = 0; + TDomain stDomain; + char szCmd[512], szTable[128]; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + +// BCS@TBL_ACCT_INFO/PART --table=1 + memset(szCmd, 0, sizeof(szCmd)); + memset(szTable, 0, sizeof(szTable)); + if(NULL == strstr(pszParam, "/")) + { + fprintf(stderr, "*pull Invalid parameter:\"%s\"\n", szCmd); + return ; + } + + if(RC_SUCC != lInitSATvm(pstSavm, SYS_TVM_DOMAIN)) + { + fprintf(stderr, "*initail SYS_TVM_DOMAIN failure, %s\n", sGetTError(pstSavm->m_lErrno)); + return ; + } + + conditinit(pstSavm, stDomain, SYS_TVM_DOMAIN); + stringsetv(pstSavm, stDomain, m_szOwner, sgetvalue(pszParam, "/", 1)); + if(!strlen(strimall(stDomain.m_szOwner))) + { + fprintf(stderr, "*illegal domain name\n"); + return ; + } + + // TBL_ACCT_INFO/PART --table=1 + strncpy(szCmd, sgetvalue(pszParam, "/", 2), sizeof(szCmd)); + strncpy(szTable, sgetvalue(szCmd, " ", 1), sizeof(szTable)); + strimall(szTable); + + stringsetv(pstSavm, stDomain, m_szTable, sgetvalue(szTable, "@", 1)); + supper(stDomain.m_szTable); + if(!strlen(stDomain.m_szTable)) + { + fprintf(stderr, "*Please input table name\n"); + return ; + } + + stringsetv(pstSavm, stDomain, m_szPart, sgetvalue(szTable, "@", 2)); + if(!strlen(stDomain.m_szPart)) + strcpy(stDomain.m_szPart, stDomain.m_szOwner); + + memset(szTable, 0, sizeof(szTable)); + strncpy(szTable, sgetvalue(szCmd, " ", 2), sizeof(szTable)); + strimall(szTable); + if(strlen(szTable) > 0) + { + if(!strncmp(szTable, "--table=", 8)) + { + table = atol(szTable + 8); + if(table <= 0 || table > TVM_MAX_TABLE) + { + fprintf(stderr, "*Local table set error \"%s\"\n", szTable + 8); + return ; + } + } + else + { + fprintf(stderr, "*command not supported \"%s\"\n", szTable); + return ; + } + } + + if(RC_SUCC != lSelect(pstSavm, (void *)&stDomain)) + { + fprintf(stderr, "*Select domain (%s)(%s) failure, %s\n", stDomain.m_szOwner, + stDomain.m_szTable, sGetTError(pstSavm->m_lErrno)); + return ; + } + + if(table != 0) + stDomain.m_table = table; + else + stDomain.m_table = stDomain.m_mtable; + + if(bTableIsExist(stDomain.m_table) || bPartIsExist(stDomain.m_szTable, pstSavm->m_szNode)) + { + fprintf(stderr, "*Table number (%d) already exists\n", stDomain.m_table); + return ; + } + + if((RESOURCE_ABLE != stDomain.m_lStatus) || !(stDomain.m_lPers & OPERATE_SELECT)) + { + fprintf(stderr, "*(%s)(%s) Resources are not available\n", stDomain.m_szTable, stDomain.m_szPart); + return ; + } + + if(RC_SUCC != lPullNotify(pstSavm, &stDomain, 1)) + { + fprintf(stderr, "*Cloning domain (%s) data failure, %s\n", stDomain.m_szOwner, + sGetTError(pstSavm->m_lErrno)); + return ; + } + + return ; +} + +/************************************************************************************************** + description:domain function + parameters: + return: + **************************************************************************************************/ +void vPrintDomFunc() +{ + fprintf(stderr, "Usage:\n"); + fprintf(stderr, " table\t\t--show remote tables\n"); + fprintf(stderr, " connect $DOM\t--connect remote domain\n"); + fprintf(stderr, " pull\t\t--pull remote table\n"); + fprintf(stderr, " exp:pull domain/table_name@part --table=table\n"); + return ; +} + +/************************************************************************************************** + description:Remote domain control + parameters: + return: + **************************************************************************************************/ +void vDomainCrontrl(TBoot *pstBoot) +{ + char *p = NULL, *pszUser = NULL; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + if(!bIsTvmBoot()) + { + fprintf(stderr, "stvm has not been started yet!\n"); + exit(0); + } + + system("stty erase ^?"); + system("stty erase ^H"); + fprintf(stdout, "\n%s\n", sFuncVersion()); + while(1) + { + if(NULL == (pszUser = readline("DOMAIN>"))) + continue; + + strimcrlf(pszUser); + sltrim(pszUser); + srtrim(pszUser); + if(!strlen(pszUser)) continue; + + add_history(pszUser); + + if(!strcasecmp(pszUser, "help") || !strcasecmp(pszUser, "--help") || + !strcasecmp(pszUser, "-?")) + vPrintDomFunc(); + else if(!strcasecmp(pszUser, "table")) + vPrintDomTable(); + else if(!strncasecmp(pszUser, "connect", 7)) + { + if(strncasecmp(pszUser, "connect ", 8)) + { + fprintf(stderr, "Usage:\n\t--connect domain\n\n"); + TFree(pszUser); + continue; + } + + vConnectDomain(sgetvalue(pszUser, " ", 2), pstBoot); + } + else if(!strncasecmp(pszUser, "pull", 4)) + { + if(strncasecmp(pszUser, "pull ", 5)) + { + fprintf(stderr, "Usage:\n\tpull domain/table_name@part\n\n"); + TFree(pszUser); + continue; + } + + p = pszUser + 5; + vPullTableDomain(p); + } + else if(!strcasecmp(pszUser, "q") || !strcasecmp(pszUser, "exit") || + !strcasecmp(pszUser, "quit")) + exit(0); + else + { + fprintf(stderr, "invalid option -- \"%s\"\n", pszUser); + vPrintDomFunc(); + } + + fprintf(stdout, "\n"); + TFree(pszUser); + } + + exit(0); +} + +/************************************************************************************************** + description:Check the stvm operating environment variables + parameters: + return: + **************************************************************************************************/ +void vCheckTvmEnv() +{ + int nRet; + + if(!getenv("TVMCFG")) + { + fprintf(stderr, "Environment variable \"TVMCFG\" is not set\n"); + exit(-1); + } + + if(!getenv("TVMDBD")) + { + fprintf(stderr, "Environment variable \"TVMDBD\" is not set\n"); + exit(-1); + } + +/* + if(0 != access(getenv("TVMDBD"), F_OK | X_OK )) + { + fprintf(stderr, "\"TVMDBD\" directory isnot set yet!\n"); + exit(-1); + } +*/ + + mkdir(getenv("TVMDBD"), S_IRWXU | S_IRWXG | S_IROTH | S_IEXEC ); +} + +/************************************************************************************************** + description:main(int argc, char *argv[]) + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + **************************************************************************************************/ +int main(int argc, char *argv[]) +{ + TABLE table; + char szCom[256]; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + int iChoose = 0, lAction = 0, lRet = 0; + TBoot *pstBoot = (TBoot *)pBootInitial(); + + if(3 == argc && !strcmp(argv[1], "-c")) + return lMakeConfig(argv[2]); + else if(3 == argc && !strcmp(argv[1], "-o")) + return lUnmakeConfig(argv[2]); + + memset(szCom, 0, sizeof(szCom)); + if(2 <= argc && (!strcasecmp(argv[1], "sql"))) + vSQLStatement(argc, argv); + if(2 <= argc && (!strcasecmp(argv[1], "dom"))) + vDomainCrontrl(pstBoot); + + vCheckTvmEnv(); + memset(szCom, 0, sizeof(szCom)); + while(-1 != (iChoose = getopt(argc, argv, "w::s::p::f::t:i:c:v?::"))) + { + switch(iChoose) + { + case 'w': + vInitTitle(argc, argv, environ); + return lStartSystem(pstBoot, optarg); + case 's': + return lStopSystem(pstBoot, argv[0]); + case 'p': + vPrintParam(optarg); + return RC_SUCC; + case 't': + vTableStruck(atol(optarg)); + return RC_SUCC; + case 'f': + vTableAmount(); + return RC_SUCC; + case 'i': + table = atol(optarg); + if(RC_SUCC != lRebuildIndex(pstSavm, table)) + fprintf(stderr, "rebuild index failure, %s\n", sGetTError(pstSavm->m_lErrno)); + return RC_SUCC; + case 'v': + fprintf(stdout, "%s\n", sGetTVMVers()); + fflush(stdout); + return RC_SUCC; + case '?': + default: + break; + } + } + + vPrintFunc(basename(argv[0])); + return RC_SUCC; +} + +/************************************************************************************************** + * code end + **************************************************************************************************/ diff --git a/src/tcp.c b/src/tcp.c new file mode 100644 index 0000000..c9ae23b --- /dev/null +++ b/src/tcp.c @@ -0,0 +1,4874 @@ +/* +* Copyright (c) 2018 Savens Liu +* +* The original has been patented, Open source is not equal to open rights. +* Anyone can clone, download, learn and discuss for free. Without the permission +* of the copyright owner or author, it shall not be merged, published, licensed or sold. +* The copyright owner or author has the right to pursue his responsibility. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "tmain.h" + +/************************************************************************************************* + statement + *************************************************************************************************/ +extern char **environ; +static char *g_Last = NULL; +static char **g_Argv = NULL; +static int g_eRun = 1; +Rowgrp *g_pstDomgrp = NULL, *g_pstTblgrp = NULL; + +extern char* pGetLog(); +extern long lGetBootType(); +extern void vSetBootType(long lType); +void* pParsePacket(SATvm *pstSavm, void *pstVoid, TFace *pstFace, void *pvBuffer, long lLen); +void* pProtocaJava(SATvm *pstSavm, void *pstVoid, TFace *pstFace, void *pvBuffer, long lLen); + +/************************************************************************************************* + macro + *************************************************************************************************/ +#define Tlog(...) vTraceLog(__FILE__, __LINE__, __VA_ARGS__) + +#define checkrequest(f,c,v,d,l) if(MAX(f->m_lRows, f->m_lDLen) > l) \ + { \ + if(MAX(f->m_lRows, f->m_lDLen) > DATA_MAX_LEN) \ + { \ + f->m_lErrno = RECD_TOO_LONG; \ + goto LISTEN_ERROR; \ + } \ + l = MAX(f->m_lRows, f->m_lDLen); \ + if(NULL == (c = (void *)realloc(c, l + sizeof(TFace)))) \ + { \ + f->m_lErrno = MALLC_MEM_ERR; \ + goto LISTEN_ERROR; \ + } \ + f = (TFace *)c; \ + d = c + sizeof(TFace); \ + if(NULL == (v = (void *)realloc(v, l + sizeof(TFace)))) \ + { \ + f->m_lErrno = MALLC_MEM_ERR; \ + goto LISTEN_ERROR; \ + } \ + } + +#define checkbuffer(p, r, n) if((p->lSize * n + r->m_lCurLine) > r->m_lRowSize) \ + { \ + if(r->m_lRowSize > DATA_MAX_LEN) \ + { \ + p->m_lErrno = RECD_TOO_LONG; \ + return RC_FAIL; \ + } \ + r->m_lRowSize = p->lSize + r->m_lCurLine; \ + if(NULL == (r->pstVoid = (void *)realloc(r->pstVoid, r->m_lRowSize))) \ + { \ + p->m_lErrno = MALLC_MEM_ERR; \ + return RC_FAIL; \ + } \ + } + +/************************************************************************************************* + function + *************************************************************************************************/ +/************************************************************************************************* + description:get root of domain list + parameters: + return: + void* --root + *************************************************************************************************/ +Rowgrp* pGetDomgrp() +{ + return g_pstDomgrp; +} + +/************************************************************************************************* + description:get root of table list + parameters: + return: + void* --root + *************************************************************************************************/ +Rowgrp* pGetTblgrp() +{ + return g_pstTblgrp; +} + +/************************************************************************************************* + description:checkt the child process is already started + parameters: + lPid --pid + return: + true --exist + false --disappear + *************************************************************************************************/ +bool bExistProcess(long lPid) +{ + errno = 0; + if(getpgid(lPid) == -1) + { + if(ESRCH == errno) return false; + else return true; + } + + return true; +} + +/************************************************************************************************* + description:trace log + parameters: + return: + *************************************************************************************************/ +void vTraceLog(const char *pszFile, int nLine, const char *fmt, ...) +{ + va_list ap; + FILE *fp = NULL; + char szMsg[5120]; + struct timeb tb; + struct tm *ptm = NULL; + + memset(szMsg, 0, sizeof(szMsg)); + va_start(ap, fmt); + vsnprintf(szMsg, sizeof(szMsg), fmt, ap); + va_end(ap); + + if(NULL == (fp = fopen(pGetLog(), "a+"))) + { + fprintf(stderr, "P(%d), open (%s) failed, err:%s,[%s]\n", getpid(), + pGetLog(), strerror(errno), szMsg); + return ; + } + + ftime(&tb); + ptm = localtime(&tb.time); + fprintf(fp, "F=%-8s L=%-5d P=%-7d T=%-7ld T=%04d%02d%02d %02d%02d%02d:%03d %s\n", + pszFile, nLine, getpid(), syscall(SYS_gettid), ptm->tm_year + 1900, ptm->tm_mon + 1, + ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, tb.millitm, szMsg); + fclose(fp); + return ; +} + +/************************************************************************************************* + description:Show cloning progress + parameters: + nVaild --vaild + nMax --max + return: + *************************************************************************************************/ +void vPrintProgresss(int nValid, int nMax) +{ + double dPer; + int i, nPer; + static int len = 0; + char szPrint[64]; + + for(i = len + 50; i > 0 && nValid > 1; i --) + fprintf(stdout, "\b"); + + dPer = nValid * 100.0 / nMax; + nPer = nValid * 50 / nMax > 0 ? nValid * 50 / nMax : 1; + if(dPer < 60.00) + fprintf(stdout, "\033[42;32m"); + else if(dPer < 70.00) + fprintf(stdout, "\033[45;35m"); + else if(dPer < 80.00) + fprintf(stdout, "\033[46;36m"); + else if(dPer < 90.00) + fprintf(stdout, "\033[43;33m"); + else + fprintf(stdout, "\033[41;31m"); + + fflush(stdout); + for(i = 0; i < nPer; i ++) + fprintf(stdout, "|"); + + fprintf(stdout, "\033[0m"); + for(i; i < 50; i ++) + fprintf(stdout, " "); + + memset(szPrint, 0, sizeof(szPrint)); + len = snprintf(szPrint, sizeof(szPrint), "] %6.3f%%, (%d/%d)", dPer, nValid, nMax); + fprintf(stdout, "%s", szPrint); + fflush(stdout); +} + +/************************************************************************************************* + description:Initialize the startup process name + parameters: + argc + **argv + **envp + return: + *************************************************************************************************/ +void vInitTitle(int argc, char **argv, char **envp) +{ + int i = 0; + + for(i = 0; envp[i] != NULL; i++) // calc envp num + continue; + + environ = (char **) malloc(sizeof (char *) * (i + 1)); + for (i = 0; envp[i] != NULL; i++) + { + environ[i] = malloc(sizeof(char) * strlen(envp[i]) + 1); + memset(environ[i], 0, sizeof(char) * strlen(envp[i]) + 1); + strcpy(environ[i], envp[i]); + } + + environ[i] = NULL; + g_Argv = argv; + if (i > 0) + g_Last = envp[i - 1] + strlen(envp[i - 1]); + else + g_Last = argv[argc - 1] + strlen(argv[argc - 1]); +} + +/************************************************************************************************* + description:set current process name + parameters: + pname --process name + return: + *************************************************************************************************/ +void vSetTitile(const char *pname) +{ + int i; + char *p, name[16]; + extern char **g_Argv; + extern char *g_Last; + + strncpy(name, pname, 16); + i = strlen(name); + if (i > g_Last - g_Argv[0] - 2) + { + i = g_Last - g_Argv[0] - 2; + name[i] = '\0'; + } + + (void) strcpy(g_Argv[0], name); + p = &g_Argv[0][i]; + while (p < g_Last) + *p++ = '\0'; + g_Argv[1] = NULL; + prctl(PR_SET_NAME, name); +} + +/************************************************************************************************* + description:get tick time + parameters: + return: + uint64_t + *************************************************************************************************/ +uint64_t get_tick_time() +{ + struct timeval tval; + uint64_t tick; + + gettimeofday(&tval, NULL); + + tick = tval.tv_sec * 1000L + tval.tv_usec / 1000L; + + return tick; +} + +/************************************************************************************************* + description:Set non-blocking + parameters: + skSock --socket + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lSetUnBlock(BSock skSock) +{ + int nOpt = 0; + + if(fcntl(skSock, F_GETFL) < 0) + return RC_FAIL; + + nOpt = nOpt | O_NONBLOCK; + if(fcntl(skSock, F_SETFL, nOpt) < 0) + return RC_FAIL; + + return RC_SUCC; +} + +/************************************************************************************************* + description:Set blocking + parameters: + skSock --socket + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lSetBlock(BSock skSock) +{ + int nOpt = 0; + + if(fcntl(skSock, F_GETFL) < 0) + return RC_FAIL; + + nOpt &= ~O_NONBLOCK; + if(fcntl(skSock, F_SETFL, nOpt) < 0) + return RC_FAIL; + + return RC_SUCC; +} + +/************************************************************************************************* + description:connect server + parameters: + pstSavm --stvm handle + pszIp --ip + lPort --port + bf --blocking and no-blocking + lTime --time out + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +BSock skConnectServer(SATvm *pstSavm, char *pszIp, long lPort, BOOL bf, long lTime) +{ + fd_set set, exp; + struct timeval tv; + struct linger lin; + BSock skSock; + struct sockaddr_in stAdr; + int error = -1, len = sizeof(int); + + memset(&stAdr, 0, sizeof(struct sockaddr_in)); + stAdr.sin_family = AF_INET; + stAdr.sin_addr.s_addr = inet_addr(pszIp); + stAdr.sin_port = htons((u_short)lPort); + + if((skSock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + pstSavm->m_lErrno = SOCK_ERR_CRTE; + return RC_FAIL; + } + + memset(&lin, 0, sizeof(lin)); + lin.l_onoff = TRUE; + lin.l_linger = 10; + if (0 > setsockopt(skSock, SOL_SOCKET, SO_LINGER, &lin, sizeof(lin))) + { + close(skSock); + return RC_FAIL; + } + + if(RC_SUCC != lSetUnBlock(skSock)) + { + close(skSock); + return RC_FAIL; + } + + if(RC_SUCC == connect(skSock, (struct sockaddr *)(&stAdr), sizeof(struct sockaddr_in))) + { + if(!bf) lSetBlock(skSock); + return skSock; + } + + if(errno != EINPROGRESS) + { + close(skSock); + pstSavm->m_lErrno = SOCK_CONN_ERR; + return RC_FAIL; + } + + FD_ZERO(&set); + FD_ZERO(&exp); + FD_SET(skSock, &set); + tv.tv_sec = lTime; + tv.tv_usec = 0; + errno = 0; + if(RC_SUCC >= select(skSock + 1, NULL, &set, &exp, &tv)) + { + close(skSock); + pstSavm->m_lErrno = SOCK_CONN_TMO; + return RC_FAIL; + } + + if(!FD_ISSET(skSock, &set) || FD_ISSET(skSock, &exp)) //异常套接字就绪 + { + close(skSock); + pstSavm->m_lErrno = SOCK_CONN_ERR; + return RC_FAIL; + } + +#ifdef HP_UX + getsockopt(skSock, SOL_SOCKET, SO_ERROR, &error, &len); +#else // linux + getsockopt(skSock, SOL_SOCKET, SO_ERROR, &error,(socklen_t*)&len); +#endif + if(!bf) lSetBlock(skSock); // set block + if(0 == error) return skSock; + + pstSavm->m_lErrno = SOCK_CONN_ERR; + close(skSock); + return RC_FAIL; +} + +/************************************************************************************************* + description:server initail + parameters: + pstSavm --stvm handle + lPort --port + return: + BSock --socket + *************************************************************************************************/ +BSock skServerInitail(SATvm *pstSavm, int lPort) +{ + int iret = -1; + int optval = 1; + BSock skSock = -1; + struct sockaddr_in serveraddr; + + memset(&serveraddr, 0, sizeof(struct sockaddr_in)); + if((skSock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + pstSavm->m_lErrno = SOCK_ERR_CRTE; + return RC_FAIL; + } + + if(RC_SUCC != lSetUnBlock(skSock)) + { + close(skSock); + return RC_FAIL; + } + + if (0 > setsockopt(skSock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))) + { + close(skSock); + return RC_FAIL; + } + + serveraddr.sin_family = AF_INET; + serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); + serveraddr.sin_port = htons(lPort); + + if (0 > bind(skSock, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr_in))) + { + close(skSock); + pstSavm->m_lErrno = SOCK_BIND_ERR; + return RC_FAIL; + } + + if (0 > listen(skSock, 1024)) + { + close(skSock); + pstSavm->m_lErrno = SOCK_LSEN_ERR; + return RC_FAIL; + } + + return skSock; +} + +/************************************************************************************************* + description:send buffer with no-blocking + parameters: + pstSavm --stvm handle + skSock --socket + ss --buffer + len --the length of buffer + return: + int --Number of bytes sent + *************************************************************************************************/ +int lSendUnblock(SATvm *pstSavm, int skSock, char *ss, int len) +{ + long lByte = 0, lLeft = len, lWrite = 0; + + while(lLeft > 0) + { + if((lWrite = send(skSock, ss + lByte, lLeft, MSG_DONTWAIT)) <= 0) + { + if(EWOULDBLOCK == errno|| EAGAIN == errno) + return lByte; + else + { + pstSavm->m_lErrno = SOCK_SEND_ERR; + return RC_FAIL; + } + } + else + { + lLeft -= lWrite; + lByte += lWrite; + } + } + + return lByte; +} + +/************************************************************************************************* + description:recv buffer with no-blocking + parameters: + pstSavm --stvm handle + skSock --socket + ss --buffer + len --the length of buffer + return: + int --Number of bytes recv + *************************************************************************************************/ +int lRecvUnblock(SATvm *pstSavm, int skSock, char *so, int read) +{ + int lByte = 0, lRecv = 0; + + while(read > lRecv) + { + lByte = recv(skSock, so + lRecv, read - lRecv, MSG_DONTWAIT); + if(lByte < 0) + { + if(EAGAIN == errno || EWOULDBLOCK == errno) + return lRecv; + else if(errno == ECONNRESET || ENETRESET == errno || ENETDOWN == errno || + EINTR == errno) + { + pstSavm->m_lErrno = SOCK_IO_RESET; + return RC_FAIL; + } + else + { + pstSavm->m_lErrno = SOCK_READ_ERR; + return RC_FAIL; + } + } + else if(lByte == 0) + { + pstSavm->m_lErrno = SOCK_IO_RESET; + return RC_FAIL; + } + + lRecv += lByte; + } + + return lRecv; +} + +/************************************************************************************************* + description:recv buffer with blocking + parameters: + skSock --socket + pszRecv --buffer + lRead --the byte of read + return: + int --Number of bytes recv + *************************************************************************************************/ +int lRecvBuffer(int skSock, char *pszRecv, int lRead) +{ + int lByte = 0, lRecv = 0; + + errno = 0; + while(lRead > lRecv) + { + lByte = recv(skSock, pszRecv + lRecv, lRead - lRecv, 0); + if(lByte < 0) + { + if(EAGAIN == errno || EWOULDBLOCK == errno) + return lRecv; + + // Connection reset by peer + if(errno == ECONNRESET || ENETRESET == errno || ENETDOWN == errno || + EINTR == errno) + return RC_FAIL; + else + return RC_FAIL; + } + else if(lByte == 0) + return RC_CLOSE; + + lRecv += lByte; + } + + return lRecv; +} + +/************************************************************************************************* + description:send buffer with blocking + parameters: + skSock --socket + pszSend --buffer + lSend --the byte of send + return: + int --Number of bytes send + *************************************************************************************************/ +int lSendBuffer(BSock skSock, void *pszSend, int lSend) +{ + long lByte = 0, lLeft = lSend, lWrite = 0; + + errno = 0; + while(lLeft > 0) + { + if((lWrite = send(skSock, pszSend + lByte, lLeft, 0)) <= 0) + return lByte; + else + { + lLeft -= lWrite; + lByte += lWrite; + } + } + + return lByte; +} + +/************************************************************************************************* + description:close socket of domain + parameters: + pstDom --domain + return: + *************************************************************************************************/ +void vCloseSocket(TDomain *pstDom) +{ + shutdown(pstDom->m_skSock, SHUT_RDWR); + close(pstDom->m_skSock); + pstDom->m_skSock = -1; +} + +/************************************************************************************************* + description:find table from table list + parameters: + t --table + return: + list --rowgrp node + *************************************************************************************************/ +Rowgrp* pGetTblNode(TABLE t) +{ + Rowgrp *list = NULL; + + for(list = pGetTblgrp(); list; list = list->pstNext) + { + if(!memcmp(&t, list->psvData, sizeof(TABLE))) + return list; + } + + return NULL; +} + +/************************************************************************************************* + description:update remote table perms + parameters: + pstDom --domain + pstIndex --retmote table + return: + *************************************************************************************************/ +void vUpdateDomPers(TDomain *pstDom, TIndex *pstIndex) +{ + TDomain *pvm; + Rowgrp *list, *node = NULL; + + for(list = pGetTblgrp(); list; list = list->pstNext) + { + if(memcmp(&pstIndex->m_table, list->psvData, sizeof(TABLE))) + continue; + + for(node = list->pstSSet; node; node = node->pstNext) + { + if(NULL == (pvm = (TDomain *)(list->pstFset->psvData))) + continue; + + if(strcmp(pvm->m_szIp, pstDom->m_szIp) || pvm->m_lPort != pstDom->m_lPort) + continue; + + pvm->m_lPers = pstIndex->m_lPers; + return ; + } + } +} + +/************************************************************************************************* + description:find domain from rowgrp + parameters: + pszIp --ip + lPort --port + return: + list --rowgrp node + *************************************************************************************************/ +Rowgrp* pGetDomnode(char *pszIp, long lPort) +{ + Rowgrp *list = NULL; + TDomain *pstDom = NULL; + + for(list = pGetDomgrp(); list; list = list->pstNext) + { + pstDom = (TDomain *)list->psvData; + if(!strcmp(pstDom->m_szIp, pszIp) && pstDom->m_lPort == lPort) + return list; + } + + return NULL; +} + +/************************************************************************************************* + description:find domain + parameters: + pszIp --ip + lPort --port + return: + domain --domain + *************************************************************************************************/ +TDomain* pGetDomain(char *pszIp, long lPort) +{ + Rowgrp *list = NULL; + TDomain *pstDom = NULL; + + for(list = pGetDomgrp(); list; list = list->pstNext) + { + pstDom = (TDomain *)list->psvData; + if(!strcmp(pstDom->m_szIp, pszIp) && pstDom->m_lPort == lPort) + return pstDom; + } + + return NULL; +} + +/************************************************************************************************* + description:Initialize the network connection table handle + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmBuffer(SATvm *pstSavm) +{ + RunTime *pstRun; + + if(!pstSavm) return RC_FAIL; + + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + if(pstRun->m_lRowSize > 0 && pstRun->pstVoid) + return RC_SUCC; + + pstRun->m_lCurLine = sizeof(pstSavm->stCond) + sizeof(pstSavm->stUpdt) + sizeof(TFace); + pstRun->m_lRowSize = READ_MAX_LEN > pstRun->m_lCurLine ? READ_MAX_LEN : pstRun->m_lCurLine; + if(NULL == (pstRun->pstVoid = (void *)calloc(pstRun->m_lRowSize, 1))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Update local domain information + parameters: + pstSavm --stvm handle + pszId --ip + lPort --lPort + lStatus --status + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lUpdateDomain(SATvm *pstSavm, char *pszIp, long lPort, long lStatus) +{ + TDomain stUpdate, stDomain; + + if(RC_SUCC != lInitSATvm(pstSavm, SYS_TVM_DOMAIN)) + return RC_FAIL; + + updateinit(stUpdate); + conditinit(pstSavm, stDomain, SYS_TVM_DOMAIN); + numberset(pstSavm, stDomain, m_lPort, lPort) + stringset(pstSavm, stDomain, m_szIp, pszIp); + + numberupd(pstSavm, stUpdate, m_lStatus, lStatus); + if(RESOURCE_ABLE != lStatus) + numberupd(pstSavm, stUpdate, m_lPers, 0); + if(RC_SUCC != lUpdate(pstSavm, (void *)&stUpdate)) + { + Tlog("update domain (%s:%d) failure, %s\n", pszIp, lPort, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Update local resources based on remote tables + parameters: + pstSavm --stvm handle + pstFace --request head + pstDom --domain info + pstIndx --remote resource list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lRemodeIndex(SATvm *pstSavm, TFace *pstFace, TDomain *pstDom, TIndex *pstIndex) +{ + long i; + TDomain stDomain, stRemote; + + pstFace->m_lRows = pstFace->m_lRows / pstFace->m_lDLen; + if(RC_SUCC != lInitSATvm(pstSavm, SYS_TVM_DOMAIN)) + return RC_FAIL; + + conditinit(pstSavm, stDomain, SYS_TVM_DOMAIN); + numberset(pstSavm, stDomain, m_lPort, pstDom->m_lPort); + stringset(pstSavm, stDomain, m_szIp, pstDom->m_szIp); + numberupd(pstSavm, stRemote, m_lStatus, RESOURCE_AUTH); + numberupd(pstSavm, stRemote, m_lPers, 0); + if(RC_SUCC != lUpdate(pstSavm, (void *)&stRemote)) + { + if(NO_DATA_FOUND != pstSavm->m_lErrno) + return RC_FAIL; + } + + conditinit(pstSavm, stDomain, SYS_TVM_DOMAIN); + for(i = 0; i < pstFace->m_lRows; i ++) + { + numberset(pstSavm, stDomain, m_lPort, pstDom->m_lPort); + numberset(pstSavm, stDomain, m_mtable, pstIndex[i].m_table); + stringset(pstSavm, stDomain, m_szIp, pstDom->m_szIp); + + updateinit(stRemote); + numberupd(pstSavm, stRemote, m_lLastTime, time(NULL)); + numberupd(pstSavm, stRemote, m_lTryTimes, 0); + numberupd(pstSavm, stRemote, m_lStatus, RESOURCE_ABLE); + numberupd(pstSavm, stRemote, m_skSock, pstDom->m_skSock); + numberupd(pstSavm, stRemote, m_lPers, pstIndex[i].m_lPers); + numberupd(pstSavm, stRemote, m_mtable, pstIndex[i].m_table); + numberupd(pstSavm, stRemote, m_lRowSize, pstIndex[i].m_lRowSize); + stringupd(pstSavm, stRemote, m_szPart, pstIndex[i].m_szPart); + stringupd(pstSavm, stRemote, m_szTable, pstIndex[i].m_szTable); + + if(RC_SUCC != lUpdate(pstSavm, (void *)&stRemote)) + { + Tlog("update local resource stat failed, %s, e(%d)", sGetTError(pstSavm->m_lErrno), + pstSavm->m_lEType); + if(NO_DATA_FOUND == pstSavm->m_lErrno) + continue; + return RC_FAIL; + } + + vUpdateDomPers(pstDom, &pstIndex[i]); + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Upload local resources + parameters: + pstSavm --stvm handle + pstFace --request head + skSock --domain info + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lLocalIndex(SATvm *pstSavm, TFace *pstFace, BSock skSock) +{ + size_t lWrite; + TIndex stIndex; + void *pvOut = NULL, *pvBuffer = NULL; + + pstFace->m_table = SYS_TVM_INDEX; + pstFace->m_lDLen = sizeof(TIndex); + + if(RC_SUCC != lInitSATvm(pstSavm, pstFace->m_table)) + return RC_FAIL; + + conditinit(pstSavm, stIndex, SYS_TVM_INDEX); + numberset(pstSavm, stIndex, m_lType, TYPE_CLIENT); + numberset(pstSavm, stIndex, m_lLocal, RES_LOCAL_SID); + if(RC_SUCC != lQuery(pstSavm, (size_t *)&pstFace->m_lRows, (void *)&pvOut)) + { + if(NO_DATA_FOUND != pstSavm->m_lErrno) + return RC_FAIL; + } + + if(pstFace->m_lRows == 0) + { + if(sizeof(TFace) != lSendBuffer(skSock, (void *)pstFace, sizeof(TFace))) + return RC_FAIL; + return RC_SUCC; + } + + pstFace->m_lRows = pstFace->m_lDLen * pstFace->m_lRows; + lWrite = pstFace->m_lRows + sizeof(TFace); + if(NULL == (pvBuffer = (void *)malloc(lWrite))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + TFree(pvOut); + return RC_FAIL; + } + + memcpy(pvBuffer, (void *)pstFace, sizeof(TFace)); + memcpy(pvBuffer + sizeof(TFace), (void *)pvOut, pstFace->m_lRows); + lSendBuffer(skSock, pvBuffer, lWrite); + TFree(pvOut); + TFree(pvBuffer); + + return RC_SUCC; +} + +/************************************************************************************************* + description:Join in the domain + parameters: + pstSavm --stvm handle + pstFace --request head + lPort --local port + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lConnectDomain(SATvm *pstSavm, TDomain *pstDom, long lPort) +{ + TFace stFace; + TIndex *pstIndex = NULL; + + memset(&stFace, 0, sizeof(TFace)); + if(pstDom->m_skSock < 0) + { + pstDom->m_skSock = skConnectServer(pstSavm, pstDom->m_szIp, pstDom->m_lPort, + false, pstDom->m_lTimeOut); + if(RC_FAIL == pstDom->m_skSock) + { + pstDom->m_lStatus = RESOURCE_STOP; + Tlog("connect server:%s:%d failed, %s", pstDom->m_szIp, pstDom->m_lPort, + sGetTError(pstSavm->m_lErrno)); + goto EXCP_NOTIFY; + } + } + + stFace.m_lRows = 0; + stFace.m_lFind = lPort; + stFace.m_table = SYS_TVM_INDEX; + stFace.m_enum = OPERATE_DOMPUL; + stFace.m_lErrno = TVM_DONE_SUCC; + stFace.m_lDLen = sizeof(TIndex); + if(sizeof(TFace) != lSendBuffer(pstDom->m_skSock, (void *)&stFace, sizeof(TFace))) + { + pstDom->m_lStatus = RESOURCE_EXCP; + goto EXCP_NOTIFY; + } + + if(sizeof(TFace) != lRecvBuffer(pstDom->m_skSock, (char *)&stFace, sizeof(TFace))) + { + pstDom->m_lStatus = RESOURCE_EXCP; + goto EXCP_NOTIFY; + } + + if(DOM_NOT_REGST == stFace.m_lErrno) + { + pstDom->m_lStatus = RESOURCE_AUTH; + goto EXCP_NOTIFY; + } + else if(0 != stFace.m_lErrno && NO_DATA_FOUND != stFace.m_lErrno) + { + pstDom->m_lStatus = RESOURCE_EXCP; + goto EXCP_NOTIFY; + } + + if(NULL == (pstIndex = (TIndex *)malloc(stFace.m_lRows))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + if(stFace.m_lRows != lRecvBuffer(pstDom->m_skSock, (void *)pstIndex, stFace.m_lRows)) + { + TFree(pstIndex); + return RC_FAIL; + } + + if(RC_SUCC != _lRemodeIndex(pstSavm, &stFace, pstDom, pstIndex)) + { + TFree(pstIndex); + pstDom->m_lStatus = RESOURCE_EXCP; + goto EXCP_NOTIFY; + } + TFree(pstIndex); + + stFace.m_lFind = lPort; + stFace.m_enum = OPERATE_DOMPSH; + stFace.m_lErrno = TVM_DONE_SUCC; + if(RC_SUCC != _lLocalIndex(pstSavm, &stFace, pstDom->m_skSock)) + { + pstDom->m_lStatus = RESOURCE_EXCP; + goto EXCP_NOTIFY; + } + + pstDom->m_lStatus = RESOURCE_ABLE; + return RC_SUCC; + +EXCP_NOTIFY: + vCloseSocket(pstDom); + pstDom->m_lTryTimes = pstDom->m_lTryMax; + pstDom->m_lLastTime = (long)time(NULL); + lUpdateDomain(pstSavm, pstDom->m_szIp, pstDom->m_lPort, pstDom->m_lStatus); + return RC_FAIL; +} + +/************************************************************************************************* + description:Notifies the remote domain that the local will be offline + parameters: + pstSavm --stvm handle + pstFace --request head + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lLocalOffline(SATvm *pstSavm, TFace *pstFace) +{ + Rowgrp *list = NULL; + TDomain *pstDom = NULL; + + for(list = pGetDomgrp(); list; list = list->pstNext) + { + if(NULL == (pstDom = (TDomain *)list->psvData)) + continue; + + if(RESOURCE_ABLE != pstDom->m_lStatus) + { + vCloseSocket(pstDom); + continue; + } + + while(DATA_TRUCK_LOCK == pstDom->m_lLock) + usleep(10); + + pstDom->m_lLock = DATA_TRUCK_LOCK; + pstFace->m_lRows = 0; + pstFace->m_enum = OPERATE_DOMROFF; + if(sizeof(TFace) != lSendBuffer(pstDom->m_skSock, (void *)pstFace, sizeof(TFace))) + { + vCloseSocket(pstDom); + pstDom->m_lLock = DATA_TRUCK_NULL; + continue; + } + + lRecvBuffer(pstDom->m_skSock, (char *)pstFace, sizeof(TFace)); + vCloseSocket(pstDom); + pstDom->m_lLock = DATA_TRUCK_NULL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Set the remote domain offline + parameters: + pstSavm --stvm handle + pstCon --socket handle + pstFace --request head + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lRemoteOffline(SATvm *pstSavm, SKCon *pstCon, TFace *pstFace) +{ + TDomain *pstDom = NULL; + long lPort = pstFace->m_lFind; + + if(NULL == (pstDom = pGetDomain(pstCon->m_szCltIp, pstFace->m_lFind))) + { + Tlog("Unregistered client request: %s:%d", pstCon->m_szCltIp, pstFace->m_lFind); + return RC_FAIL; + } + + vCloseSocket(pstDom); + pstDom->m_lStatus = RESOURCE_ROFF; + pstDom->m_lTryTimes = pstDom->m_lTryMax; + return lUpdateDomain(pstSavm, pstDom->m_szIp, lPort, RESOURCE_STOP); +} + +/************************************************************************************************* + description:reconnect the remote domain + parameters: + pstSavm --stvm handle + pstCon --socket handle + pstFace --request head + pv --remote domain + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lReconnectDomain(SATvm *pstSavm, SKCon *pstCon, TFace *pstFace, TDomain *pv) +{ + TDomain *pstDom; + + if(NULL == (pstDom = pGetDomain(pv->m_szIp, pv->m_lPort))) + { + Tlog("Unregistered client request: %s:%d", pv->m_szIp, pv->m_lPort); + return RC_FAIL; + } + + pstDom->m_lTryTimes = 0; + pstDom->m_lLastTime = (long)time(NULL); + return lConnectDomain(pstSavm, pstDom, pstFace->m_lFind); +} + +/************************************************************************************************* + description:Receiving remote resources + parameters: + pstSavm --stvm handle + pstCon --socket handle + pstFace --request head + pvData --remote resource + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lDomainPull(SATvm *pstSavm, SKCon *pstCon, TFace *pstFace, void *pvData) +{ + TDomain *pstDom = NULL; + + if(NULL == (pstDom = pGetDomain(pstCon->m_szCltIp, pstFace->m_lFind))) + { + Tlog("Unregistered client request: %s:%d", pstCon->m_szCltIp, pstFace->m_lFind); + return RC_FAIL; + } + + pstDom->m_lTryTimes = 0; + pstDom->m_lLastTime = (long)time(NULL); + return _lRemodeIndex(pstSavm, pstFace, pstDom, (TIndex *)pvData); +} + +/************************************************************************************************* + description:Sending local resources + parameters: + pstSavm --stvm handle + pstCon --socket handle + pstFace --request head + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lDomainPush(SATvm *pstSavm, SKCon *pstCon, TFace *pstFace) +{ + TDomain *pstDom = NULL; + + if(NULL == (pstDom = pGetDomain(pstCon->m_szCltIp, pstFace->m_lFind))) + { + Tlog("Unregistered client request: %s:%d", pstCon->m_szCltIp, pstFace->m_lFind); + return RC_FAIL; + } + + pstDom->m_lTryTimes = 0; + pstDom->m_lStatus = RESOURCE_ABLE; + pstDom->m_lLastTime = (long)time(NULL); + return _lLocalIndex(pstSavm, pstFace, pstCon->m_skSock); +} + +/************************************************************************************************* + description:Sending local table data + parameters: + pstSavm --stvm handle + pstCon --socket handle + skSock --socket + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lPushTable(SATvm *pstSavm, TFace *pstFace, BSock skSock) +{ + long lWrite, lRow = 0, lRet; + void *pvData = NULL, *pvBuffer = NULL; + + pstFace->m_lRows = 1; + pstFace->m_lDLen = sizeof(TblDef); + if(pstFace->m_lDLen != lSendBuffer(skSock, (void *)pGetTblDef(pstFace->m_table), + pstFace->m_lDLen)) + return RC_FAIL; + + if(pstFace->m_lFind <= 0) + { + pstFace->m_lRows = 0; + lSendBuffer(skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + } + + lWrite = lGetRowSize(pstFace->m_table) * pstFace->m_lFind + sizeof(TFace); + if(NULL == (pvBuffer = (char *)calloc(1, lWrite))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + pvData = pvBuffer + sizeof(TFace); + + pstSavm->pstVoid = NULL; + pstSavm->tblName = pstFace->m_table; + pstSavm->lSize = lGetRowSize(pstFace->m_table); + if(RC_SUCC != lTableDeclare(pstSavm)) + { + TFree(pvBuffer); + return RC_FAIL; + } + + ((TFace *)pvBuffer)->m_table = pstFace->m_table; + ((TFace *)pvBuffer)->m_lRows = pstFace->m_lFind; + ((TFace *)pvBuffer)->m_lDLen = lGetRowSize(pstFace->m_table); + + while(1) + { + lRet = lTableFetch(pstSavm, (void *)pvData + lRow * pstFace->m_lDLen); + if(RC_FAIL == lRet) + { + TFree(pvBuffer); + vTableClose(pstSavm); + return RC_FAIL; + } + else if(RC_NOTFOUND == lRet) + break; + + if(pstFace->m_lFind != ++ lRow) + continue; + + lRow = 0; + if(lWrite != lSendBuffer(skSock, (void *)pvBuffer, lWrite)) + { + vTableClose(pstSavm); + return RC_FAIL; + } + } + vTableClose(pstSavm); + + if(0 == lRow) + { + TFree(pvBuffer); + pstFace->m_lRows = 0; + lSendBuffer(skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + } + + ((TFace *)pvBuffer)->m_lRows = lRow; + lWrite = lGetRowSize(pstFace->m_table) * lRow + sizeof(TFace); + if(lWrite != lSendBuffer(skSock, (void *)pvBuffer, lWrite)) + { + TFree(pvBuffer); + return RC_FAIL; + } + + ((TFace *)pvBuffer)->m_lRows = 0; + if(sizeof(TFace) != lSendBuffer(skSock, (void *)pvBuffer, sizeof(TFace))) + { + TFree(pvBuffer); + return RC_FAIL; + } + + TFree(pvBuffer); + return RC_SUCC; +} + +/************************************************************************************************* + description:refresh remote domain + parameters: + pstSavm --stvm handle + pstFace --request head + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lRefreshDomain(SATvm *pstSavm, TFace *pstFace) +{ + Rowgrp *list = NULL; + TDomain *pstDom = NULL; + + for(list = pGetDomgrp(); list; list = list->pstNext) + { + if(NULL == (pstDom = (TDomain *)list->psvData)) + continue; + + while(DATA_TRUCK_LOCK == pstDom->m_lLock) + usleep(10); + + pstDom->m_lLock = DATA_TRUCK_LOCK; + lConnectDomain(pstSavm, pstDom, pstFace->m_lFind); + pstDom->m_lLock = DATA_TRUCK_NULL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Java API - event operation + parameters: + pstSavm --stvm handle + pstFace --request head + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lProcaOperate(SATvm *pstSavm, SKCon *pstCon, TFace *pstFace, char *pvData) +{ + + + + + + pstFace->m_lRows = 0; + pstFace->m_lErrno = RMT_NOT_SUPPT; + return RC_FAIL; +} + +/************************************************************************************************* + description:C/C++ API - event operation + parameters: + pstSavm --stvm handle + pstCon --socket handle + pstFace --request head + pvData --request data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lEventOperate(SATvm *pstSavm, SKCon *pstCon, TFace *pstFace, char *pvData) +{ + size_t lData; + void *pvOut = NULL; + + switch(pstFace->m_enum) + { + case OPERATE_SELECT: + if(RC_SUCC != lSelect(pstSavm, (void *)pvData)) + { + pstFace->m_lErrno = pstSavm->m_lErrno; + lData = sizeof(TFace); + } + else + { + lData = pstFace->m_lDLen + sizeof(TFace); + pstFace->m_lRows = pstSavm->m_lEffect; + } + + lSendBuffer(pstCon->m_skSock, (void *)pstFace, lData); + return RC_SUCC; + case OPERATE_QUERY: + if(RC_SUCC != lQuery(pstSavm, (size_t *)&pstFace->m_lRows, (void *)&pvOut)) + pstFace->m_lErrno = pstSavm->m_lErrno; + + lData = pstFace->m_lDLen * pstFace->m_lRows; + if(sizeof(TFace) != lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace))) + { + TFree(pvOut); + return RC_SUCC; + } + + lSendBuffer(pstCon->m_skSock, pvOut, lData); + TFree(pvOut); + return RC_SUCC; + case OPERATE_UPDATE: + pstSavm->m_bWork = pstCon->m_bWork; + pstSavm->m_pstWork = pstCon->m_pstWork; + if(RC_SUCC != lUpdate(pstSavm, pvData)) + pstFace->m_lErrno = pstSavm->m_lErrno; + else + pstFace->m_lRows = pstSavm->m_lEffect; + pstCon->m_pstWork = pstSavm->m_pstWork; + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + case OPERATE_DELETE: + pstSavm->m_bWork = pstCon->m_bWork; + pstSavm->m_pstWork = pstCon->m_pstWork; + if(RC_SUCC != lDelete(pstSavm)) + pstFace->m_lErrno = pstSavm->m_lErrno; + pstCon->m_pstWork = pstSavm->m_pstWork; + pstFace->m_lRows = pstSavm->m_lEffect; + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + case OPERATE_INSERT: + pstSavm->m_bWork = pstCon->m_bWork; + pstSavm->m_pstWork = pstCon->m_pstWork; + if(RC_SUCC != lInsert(pstSavm)) + pstFace->m_lErrno = pstSavm->m_lErrno; + else + pstFace->m_lRows = pstSavm->m_lEffect; + pstCon->m_pstWork = pstSavm->m_pstWork; + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + case OPERATE_TRCATE: + if(RC_SUCC != lTruncate(pstSavm, pstFace->m_table)) + pstFace->m_lErrno = pstSavm->m_lErrno; + else + pstFace->m_lRows = pstSavm->m_lEffect; + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + case OPERATE_COUNT: + if(RC_SUCC != lCount(pstSavm, (size_t *)&pstFace->m_lRows)) + pstFace->m_lErrno = pstSavm->m_lErrno; + + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + case OPERATE_EXTREM: + memset(pvData, 0, pstSavm->lSize); + if(RC_SUCC != lExtreme(pstSavm, (void *)pvData)) + { + pstFace->m_lErrno = pstSavm->m_lErrno; + lData = sizeof(TFace); + } + else + { + lData = pstFace->m_lDLen + sizeof(TFace); + pstFace->m_lRows = pstSavm->m_lEffect; + } + lSendBuffer(pstCon->m_skSock, (void *)pstFace, lData); + return RC_SUCC; + case OPERATE_TBDROP: + if(RC_SUCC != lDropTable(pstSavm, pstFace->m_table)) + pstFace->m_lErrno = pstSavm->m_lErrno; + else + pstFace->m_lRows = pstSavm->m_lEffect; + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + case OPERATE_RENAME: + if(RC_SUCC != lRenameTable(pstSavm, pstFace->m_table, (TABLE)pstFace->m_lDLen)) + pstFace->m_lErrno = pstSavm->m_lErrno; + + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + case OPERATE_SELSEQ: + if(RC_SUCC != lSelectSeque(pstSavm, (char *)pvData, (ulong *)pvData)) + { + pstFace->m_lErrno = pstSavm->m_lErrno; + lData = sizeof(TFace); + } + else + lData = pstFace->m_lDLen + sizeof(ulong); + + lSendBuffer(pstCon->m_skSock, (void *)pstFace, lData); + return RC_SUCC; + case OPERATE_SETSEQ: + if(RC_SUCC != lSetSequence(pstSavm, (char *)pvData, *((ulong *)(pvData + MAX_INDEX_LEN)))) + pstFace->m_lErrno = pstSavm->m_lErrno; + + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + case OPERATE_RBDIDX: + if(RC_SUCC != lRebuildIndex(pstSavm, pstFace->m_table)) + pstFace->m_lErrno = pstSavm->m_lErrno; + + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + case OPERATE_RETLOK: + if(RC_SUCC != lResetLock(pstSavm, pstFace->m_table)) + pstFace->m_lErrno = pstSavm->m_lErrno; + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + case OPERATE_GROUP: + if(RC_SUCC != lGroup(pstSavm, (size_t *)&pstFace->m_lRows, (void *)&pvOut)) + pstFace->m_lErrno = pstSavm->m_lErrno; + + lData = pstFace->m_lDLen * pstFace->m_lRows; + if(sizeof(TFace) != lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace))) + { + TFree(pvOut); + return RC_SUCC; + } + + lSendBuffer(pstCon->m_skSock, pvOut, lData); + TFree(pvOut); + return RC_SUCC; + +/* work */ + case OPERATE_BEGWORK: + if(pstCon->m_bWork && pstCon->m_uWorker != pstFace->m_lDLen) + lRollbackWork(pstSavm); + if(!pstCon->m_bWork) + { + pstCon->m_bWork = true; + pstCon->m_uWorker = pstFace->m_lDLen; + } + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + case OPERATE_ROLWORK: + if(pstCon->m_uWorker != pstFace->m_lDLen) + { + pstFace->m_lErrno = WORK_NOT_REGT; + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + } + + pstSavm->m_bWork = pstCon->m_bWork; + pstSavm->m_pstWork = pstCon->m_pstWork; + lRollbackWork(pstSavm); + pstFace->m_lRows = pstSavm->m_lEffect; + pstCon->m_pstWork = NULL; + pstFace->m_lErrno = pstSavm->m_lErrno; + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + case OPERATE_CMTWORK: + if(pstCon->m_uWorker != pstFace->m_lDLen) + { + pstFace->m_lErrno = WORK_NOT_REGT; + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + } + + pstSavm->m_bWork = pstCon->m_bWork; + pstSavm->m_pstWork = pstCon->m_pstWork; + lCommitWork(pstSavm); + pstCon->m_pstWork = NULL; + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + case OPERATE_ENDWORK: + if(pstCon->m_uWorker != pstFace->m_lDLen) + { + pstFace->m_lErrno = WORK_NOT_REGT; + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + } + + pstSavm->m_bWork = pstCon->m_bWork; + pstSavm->m_pstWork = pstCon->m_pstWork; + lCommitWork(pstSavm); + pstCon->m_bWork = false; + pstCon->m_pstWork = NULL; + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + + case OPERATE_DOMPUL: + if(RC_SUCC != lDomainPush(pstSavm, pstCon, pstFace)) + { + pstFace->m_lErrno = pstSavm->m_lErrno; + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + } + + return RC_SUCC; + case OPERATE_DOMPSH: + lDomainPull(pstSavm, pstCon, pstFace, pvData); + return RC_SUCC; + + case OPERATE_DMRECN: + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + lReconnectDomain(pstSavm, pstCon, pstFace, (TDomain *)pvData); + return RC_SUCC; + case OPERATE_REFRESH: + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + lRefreshDomain(pstSavm, pstFace); + return RC_SUCC; + case OPERATE_DOMLOFF: + lLocalOffline(pstSavm, pstFace); + g_eRun = 0; + pstSavm->m_bWork = pstCon->m_bWork; + pstSavm->m_pstWork = pstCon->m_pstWork; + lCommitWork(pstSavm); + pstCon->m_bWork = false; + pstCon->m_pstWork = NULL; + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + case OPERATE_DOMROFF: + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + lRemoteOffline(pstSavm, pstCon, pstFace); + return RC_SUCC; + case OPERATE_PULTBL: + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + lPushTable(pstSavm, pstFace, pstCon->m_skSock); + return RC_SUCC; + case OPERATE_EXEEXIT: + g_eRun = 0; + pstSavm->m_bWork = pstCon->m_bWork; + pstSavm->m_pstWork = pstCon->m_pstWork; + lCommitWork(pstSavm); + pstCon->m_bWork = false; + pstCon->m_pstWork = NULL; + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + return RC_SUCC; + default: + pstFace->m_lRows = 0; + pstFace->m_lErrno = RMT_NOT_SUPPT; + Tlog("Unknown request:%d", pstFace->m_enum); + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:accepte operation + parameters: + pstSavm --stvm handle + epdf --socket + pc --socket handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lEpollAccept(SATvm *pstSavm, BSock epfd, SKCon *pc) +{ + socklen_t kLen; + epollevt event; + BSock skAccept; + SKCon *pstCon = NULL; + struct sockaddr_in cAddr; + + while (1) + { + kLen = sizeof(struct sockaddr_in); + /* The phenomenon of "terrors" produced by multiple processes, There is only one + process returned to succ and other processes return errno=EAGAIN */ + if(0 > (skAccept = accept(pc->m_skSock, (struct sockaddr *)&cAddr, &kLen))) + break; + + if (RC_SUCC != lSetUnBlock(skAccept)) + { + close(skAccept); + continue; + } + + if(NULL == (pstCon = (SKCon *)calloc(sizeof(SKCon), 1))) + { + close(skAccept); + fprintf(stderr, "Create memory, err:(%d)(%s)", errno, strerror(errno)); + return RC_FAIL; + } + + pstCon->m_skSock = skAccept; + pstCon->m_lCltPort = ntohs(cAddr.sin_port); + strncpy(pstCon->m_szCltIp, inet_ntoa(cAddr.sin_addr), sizeof(pstCon->m_szCltIp)); + + memset(&event, 0, sizeof(event)); + event.data.ptr = pstCon; + event.events = EPOLLIN | EPOLLET; + if(0 != epoll_ctl(epfd, EPOLL_CTL_ADD, skAccept, &event)) + { + close(skAccept); + pstSavm->m_lErrno = EPOLL_ADD_ERR; + fprintf(stderr, "add socket (%d) error, err:(%d)(%s)", skAccept, + errno, strerror(errno)); + return RC_FAIL; + } + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:reset remote domain + parameters: + pstSavm --stvm handle + pszIp --ip + lPort --lport + skSock --socket + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +void vResetRemote(SATvm *pstSavm, char *pszIp, long lPort, BSock skSock) +{ + TDomain *pv = NULL; + Rowgrp *list = NULL; + + for(list = pGetDomgrp(); list; list = list->pstNext) + { + pv = (TDomain *)list->psvData; + if(strcmp(pv->m_szIp, pszIp) || pv->m_lPort != lPort) + continue; + + pv->m_lTryTimes = 0; + pv->m_lStatus = RESOURCE_ABLE; + pv->m_lLastTime = (long)time(NULL); + } + + return ; +} + +/************************************************************************************************* + description:Get the event request + parameters: + pstSovm --stvm handle + pstCon --socket handle + pstFace --request head + pstVoid --request condition + pvData --decorate + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lPollRequest(SATvm *pstSovm, SKCon *pstCon, TFace *pstFace, void *pstVoid, char *pvData) +{ + long lRet; + RunTime *pstRun = NULL; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + if(OPERATE_DMKEEP == pstFace->m_enum) + { + lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + vResetRemote(pstSovm, pstCon->m_szCltIp, pstFace->m_lFind, pstCon->m_skSock); + return RC_SUCC; + } + + if(pstFace->m_lRows != lRecvBuffer(pstCon->m_skSock, pvData, pstFace->m_lRows)) + { + Tlog("recv %d byte, err:%s", lRet, strerror(errno)); + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSovm, pstFace->m_table); + pstRun->m_bAttch = pstSovm->stRunTime[pstFace->m_table].m_bAttch; + pstRun->m_pvAddr = pstSovm->stRunTime[pstFace->m_table].m_pvAddr; + if(!pstRun->m_bAttch || !pstRun->m_pvAddr) + { +//Tlog("initial table:%d, %d, %d", pstFace->m_table, pstFace->m_enum, pstRun->m_bAttch); + if(RC_SUCC != lInitSATvm(pstSovm, pstFace->m_table)) + { + pstFace->m_lRows = 0; + pstFace->m_lErrno = pstSovm->m_lErrno; + return lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + } + } + + if(PROT_JAVA & pstFace->m_enum) + { + pstFace->m_enum = pstFace->m_enum ^ PROT_JAVA; + pstFace->m_lDLen = pstRun->m_lRowSize; + if(NULL == (pvData = pProtocaJava(pstSovm, pstVoid, pstFace, pvData, pstFace->m_lRows))) + { + pstFace->m_lErrno = RESOU_DISABLE; + pvData = (void *)pstFace + sizeof(TFace); + return lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + } + + pstSovm->pstVoid = pstVoid; + pstSovm->lFind = pstFace->m_lFind; + pstSovm->tblName = pstFace->m_table; + pstSovm->lSize = pstFace->m_lDLen; + lRet = lProcaOperate(pstSovm, pstCon, pstFace, pvData); + pstSavm->stRunTime[pstFace->m_table].m_bAttch = pstRun->m_bAttch; + pstSavm->stRunTime[pstFace->m_table].m_pvAddr = pstRun->m_pvAddr; + if(RC_SUCC == lRet) return RC_SUCC; + + return lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + } + else + { + if(NULL == (pvData = pParsePacket(pstSovm, pstVoid, pstFace, pvData, pstFace->m_lRows))) + { + pstFace->m_lErrno = RESOU_DISABLE; + pvData = (void *)pstFace + sizeof(TFace); + return lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + } + + pstSovm->pstVoid = pstVoid; + pstSovm->lFind = pstFace->m_lFind; + pstSovm->tblName = pstFace->m_table; + pstSovm->lSize = pstFace->m_lDLen; + lRet = lEventOperate(pstSovm, pstCon, pstFace, pvData); + pstSavm->stRunTime[pstFace->m_table].m_bAttch = pstRun->m_bAttch; + pstSavm->stRunTime[pstFace->m_table].m_pvAddr = pstRun->m_pvAddr; + if(RC_SUCC == lRet) return RC_SUCC; + + return lSendBuffer(pstCon->m_skSock, (void *)pstFace, sizeof(TFace)); + } +} + +/************************************************************************************************* + description:server listen + parameters: + pvParam + return: + *************************************************************************************************/ +void* vEpollListen(void *pvParam) +{ + SKCon *pstCon = NULL; + TFace *pstFace = NULL; + epollevt events[MAX_EVENTS]; + BSock epfd = *((long *)pvParam); + long i, nWait, lBuffer = READ_MAX_LEN; + char *pvData, *pvFace = NULL, *pstVoid = NULL; + SATvm *pstSavm = (SATvm *)calloc(1, sizeof(SATvm)); + + pthread_detach(pthread_self()); + vHoldConnect(pstSavm); + if(!pstSavm || NULL == (pvFace = calloc(1, lBuffer + sizeof(TFace)))) + { + fprintf(stderr, "create process(%s) memory failed, (%s)", TVM_LOCAL_SERV, strerror(errno)); + return NULL; + } + + if(NULL == (pstVoid = (void *)calloc(1, lBuffer + sizeof(TFace)))) + return NULL; + + if(RC_SUCC != lTvmBuffer(pstSavm)) + return NULL; + + pstFace = (TFace *)pvFace; + pvData = pvFace + sizeof(TFace); + while(g_eRun) + { + nWait = epoll_wait(epfd, events, MAX_EVENTS, 1000); + for(i = 0; i < nWait; i++) + { + pstCon = (SKCon *)events[i].data.ptr; + if(pstCon->m_isListen) + lEpollAccept(pstSavm, epfd, pstCon); + else if(events[i].events & EPOLLIN) + { + if(sizeof(TFace) != lRecvBuffer(pstCon->m_skSock, pvFace, sizeof(TFace))) + { + if(pstCon->m_bWork) + { + pstSavm->m_bWork = pstCon->m_bWork; + pstSavm->m_pstWork = pstCon->m_pstWork; + lRollbackWork(pstSavm); + pstCon->m_bWork = false; + } + pstCon->m_pstWork = NULL; + epoll_ctl(epfd, EPOLL_CTL_DEL, pstCon->m_skSock, &events[i]); + close(pstCon->m_skSock); + continue; + } + + if(TVM_MAX_TABLE <= pstFace->m_table) + { + pstFace->m_lErrno = RESOU_DISABLE; + goto LISTEN_ERROR; + } + + checkrequest(pstFace, pvFace, pstVoid, pvData, lBuffer); + if(RC_FAIL == lPollRequest(pstSavm, pstCon, pstFace, pstVoid, pvData)) + { + if(pstCon->m_bWork) + { + pstSavm->m_bWork = pstCon->m_bWork; + pstSavm->m_pstWork = pstCon->m_pstWork; + lRollbackWork(pstSavm); + pstCon->m_bWork = false; + } + pstCon->m_pstWork = NULL; + epoll_ctl(epfd, EPOLL_CTL_DEL, pstCon->m_skSock, &events[i]); + close(pstCon->m_skSock); + } + } + } + continue; + +LISTEN_ERROR: + lSendBuffer(pstCon->m_skSock, pvFace, sizeof(TFace)); + continue; + } + + close(epfd); + TFree(pvFace); + TFree(pstVoid); + pstSavm->pstVoid = NULL; + vTvmDisconnect(pstSavm); + return NULL; +} + +/************************************************************************************************* + description:Get the event request + parameters: + pstSovm --stvm handle + epfg --socket + plMultListen --listen handle + return: + *************************************************************************************************/ +void vMultListen(SATvm *pstSavm, BSock epfd, FUNCEXEC plMultListen) +{ + long i, nWait = 0; + SKCon *pstCon = NULL; + epollevt events[MAX_EVENTS]; + + pthread_detach(pthread_self()); + vHoldConnect(pstSavm); + while(1) + { + nWait = epoll_wait(epfd, events, MAX_EVENTS, 5000); + for(i = 0; i < nWait; i++) + { + pstCon = (SKCon *)events[i].data.ptr; + if(pstCon->m_isListen) + lEpollAccept(pstSavm, epfd, pstCon); + else if(events[i].events & EPOLLIN) + { + if(RC_CLOSE == plMultListen(pstSavm, pstCon)) + { + epoll_ctl(epfd, EPOLL_CTL_DEL, pstCon->m_skSock, &events[i]); + close(pstCon->m_skSock); + } + } + } + } + + close(epfd); + vHoldRelease(pstSavm); + return ; +} + +/************************************************************************************************* + description:Fork multi-process listening + parameters: + pstSavm --stvm handle + lPort --socket handle + lProcess --request head + plMultInitail --init handle + arg --request condition + plMultListen --listen handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lMultListen(SATvm *pstSavm, long lPort, long lProcess, FUNCEXEC plMultInitail, void *arg, + FUNCEXEC plMultListen) +{ + int i; + pid_t lPid; + epollevt event; + BSock epfd = -1; + SKCon *pstCon = NULL; + + if(NULL == (pstCon = (SKCon *)calloc(sizeof(SKCon), 1))) + { + fprintf(stderr, "create memory, err:(%d)(%s)", errno, strerror(errno)); + return RC_FAIL; + } + + pstCon->m_isListen = 1; + if(0 > (pstCon->m_skSock = skServerInitail(pstSavm, lPort))) + return RC_FAIL; + + for(i = 0; i < lProcess; i ++) + { + if(0 > (lPid = fork())) + { + close(pstCon->m_skSock); + return RC_FAIL; + } + else if(lPid > 0) + continue; + + epfd = epoll_create(MAX_EVENTS); + + memset(&event, 0, sizeof(event)); + event.data.ptr = pstCon; + event.events = EPOLLIN | EPOLLET; + if(0 != epoll_ctl(epfd, EPOLL_CTL_ADD, pstCon->m_skSock, &event)) + { + pstSavm->m_lErrno = EPOLL_ADD_ERR; + return RC_FAIL; + } + + if(plMultInitail && RC_SUCC != plMultInitail(pstSavm, (void *)arg)) + { + pstSavm->m_lErrno = INI_ERR_CHLDP; + return RC_FAIL; + } + + vMultListen(pstSavm, epfd, plMultListen); + exit(0); + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:break heart + parameters: + pstSovm --stvm handle + pstDom --remote domain + lPort --local port + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lBreakHeart(SATvm *pstSavm, TDomain *pstDom, long lPort) +{ + TFace stFace; + + if(pstDom->m_skSock < 0) + { + pstDom->m_skSock = skConnectServer(pstSavm, pstDom->m_szIp, pstDom->m_lPort, + false, pstDom->m_lTimeOut); + if(RC_FAIL == pstDom->m_skSock) + return RC_FAIL; + } + + stFace.m_lFind = lPort; + stFace.m_enum = OPERATE_DMKEEP; + if(sizeof(TFace) != lSendBuffer(pstDom->m_skSock, (void *)&stFace, sizeof(TFace))) + { + pstDom->m_lTryTimes ++; + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(pstDom->m_skSock, (void *)&stFace, sizeof(TFace))) + { + pstDom->m_lTryTimes ++; + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Domain activity detection + parameters: + pstSovm --stvm handle + lPort --socket handle + return: + *************************************************************************************************/ +void vDomainEvent(SATvm *pstSavm, long lPort) +{ + Rowgrp *list = NULL; + TDomain *pstDom = NULL; + + while(g_eRun) + { + for(sleep(1), list = pGetDomgrp(); list; list = list->pstNext) + { + if(NULL == (pstDom = (TDomain *)list->psvData)) + continue; + + if(RESOURCE_ROFF == pstDom->m_lStatus) + continue; + + if(pstDom->m_lKeepLive > ((long)time(NULL) - pstDom->m_lLastTime)) + continue; + + if(pstDom->m_lTryMax > 0 && pstDom->m_lTryMax <= pstDom->m_lTryTimes) + continue; + + if(pstDom->m_lStatus != RESOURCE_ABLE) + { + lConnectDomain(pstSavm, pstDom, lPort); + continue; + } + + if(0 != pthread_mutex_trylock(&list->lock)) + continue; + + pstDom->m_lLastTime = (long)time(NULL); + pstDom->m_lLock = DATA_TRUCK_LOCK; + if(RC_SUCC == lBreakHeart(pstSavm, pstDom, lPort)) + { + pthread_mutex_unlock(&list->lock); + pstDom->m_lTryTimes = 0; + pstDom->m_lLock = DATA_TRUCK_NULL; + pstDom->m_lStatus = RESOURCE_ABLE; + continue; + } + + pthread_mutex_unlock(&list->lock); + + vCloseSocket(pstDom); + pstDom->m_lLock = DATA_TRUCK_NULL; + if(pstDom->m_lTryMax > 0 && pstDom->m_lTryMax <= pstDom->m_lTryTimes) + { + pstDom->m_lStatus = RESOURCE_STOP; + lUpdateDomain(pstSavm, pstDom->m_szIp, pstDom->m_lPort, RESOURCE_STOP); + } + } + } + + return ; +} + +/************************************************************************************************* + description:close domain + parameters: + return: + *************************************************************************************************/ +void vCloseDomain() +{ + Rowgrp *list; + + for(list = g_pstDomgrp; list; list = list->pstNext) + { + pthread_mutex_destroy(&list->lock); + close(((TDomain *)list->psvData)->m_skSock); + ((TDomain *)list->psvData)->m_skSock = -1; + } + + TFgrp(g_pstDomgrp); + TFgrp(g_pstTblgrp); +} + +/************************************************************************************************* + description:Cache domain + parameters: + pstSavm --stvm handle + eMode --cache type + lPort --local port + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lCacheDomain(SATvm *pstSavm, Benum eMode, long lPort) +{ + size_t i, lOut = 0; + TDomain *pstDom = NULL, stDomain; + Rowgrp *list = NULL, *node = NULL; + + if(RC_SUCC != lInitSATvm(pstSavm, SYS_TVM_DOMAIN)) + { + fprintf(stderr, "init domain error, %s\n", sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + conditnull(pstSavm, TDomain, SYS_TVM_DOMAIN); + decorate(pstSavm, TDomain, m_szIp, GROUP_BY | ORDER_ASC); + decorate(pstSavm, TDomain, m_lPort, GROUP_BY | ORDER_ASC); + decorate(pstSavm, TDomain, m_lGroup, GROUP_BY); + decorate(pstSavm, TDomain, m_lTryMax, GROUP_BY); + decorate(pstSavm, TDomain, m_lTimeOut, GROUP_BY); + decorate(pstSavm, TDomain, m_lKeepLive, GROUP_BY); + if(RC_SUCC != lGroup(pstSavm, &lOut, (void *)&pstDom)) + { + if(NO_DATA_FOUND != pstSavm->m_lErrno) + { + fprintf(stderr, "get domain error, %s", sGetTError(pstSavm->m_lErrno)); + pthread_exit(NULL); + return ; + } + } + + for(i = 0; i < lOut; i ++) + { + pstDom[i].m_skSock = -1; + pstDom[i].m_lLastTime = time(NULL); + if(0 == eMode) lConnectDomain(pstSavm, &pstDom[i], lPort); + + if(NULL == (g_pstDomgrp = pInsertRowgrp(pstSavm, g_pstDomgrp, NULL, NULL, + (void *)&pstDom[i], sizeof(TDomain), 0))) + { + TFree(pstDom); + fprintf(stderr, "add domain list error, %s", strerror(errno)); + pthread_exit(NULL); + return ; + } + } + TFree(pstDom); + + conditnull(pstSavm, TDomain, SYS_TVM_DOMAIN); + decorate(pstSavm, TDomain, m_table, GROUP_BY | ORDER_ASC); + if(RC_SUCC != lGroup(pstSavm, &lOut, (void *)&pstDom)) + { + if(NO_DATA_FOUND == pstSavm->m_lErrno) + return RC_SUCC; + return RC_FAIL; + } + + for(i = 0; i < lOut; i ++) + { + if(NULL == (g_pstTblgrp = pInsertRowgrp(pstSavm, pGetTblgrp(), NULL, NULL, + (void *)&pstDom[i].m_table, sizeof(TABLE), 0))) + { + TFree(pstDom); + return RC_FAIL; + } + } + + TFree(pstDom); + + for(list = pGetTblgrp(); list; list = list->pstNext) + { + conditinit(pstSavm, stDomain, SYS_TVM_DOMAIN); + numberset(pstSavm, stDomain, m_table, *((TABLE *)list->psvData)); + if(RC_SUCC != lQuery(pstSavm, &lOut, (void *)&pstDom)) + return RC_FAIL; + + for(i = 0; i < lOut; i ++) + { + if(NULL == (list->pstSSet = pInsertRowgrp(pstSavm, list->pstSSet, list, NULL, + (void *)&pstDom[i], sizeof(TDomain), 0))) + { + TFree(pstDom); + return RC_FAIL; + } + } + + TFree(pstDom); + } + + for(list = pGetTblgrp(); list; list = list->pstNext) + { + for(node = list->pstSSet; node; node = node->pstNext) + { + if(NULL == (pstDom = (TDomain *)node->psvData)) + continue; + + node->pstFset = pGetDomnode(pstDom->m_szIp, pstDom->m_lPort); + pthread_mutex_init(&node->pstFset->lock, NULL); + } + } + + vSetBootType(TVM_BOOT_LOCAL); + return RC_SUCC; +} + +/************************************************************************************************* + description:Open domain as local mode + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lOpenDomain(SATvm *pstSavm) +{ + return lCacheDomain(pstSavm, 1, 0); +} + +/************************************************************************************************* + description:load remote resourc3 + parameters: + pstSavm --stvm handle + eMode --cache type + lPort --local port + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +void vRemoteResouce(SATvm *pstSavm, Benum eMode, long lPort) +{ + TDomain *pstDom = NULL; + Rowgrp *list, *node = NULL; + long lType = lGetBootType(); + + if(RC_SUCC != lCacheDomain(pstSavm, eMode, lPort)) + return ; + + Tlog("=-=-=-=-=-=-=-=-=-=-=-=- Domain node announcement -=-=-=-=-=-=-=-=-=-=-=-=-="); + for(list = pGetDomgrp(); list; list = list->pstNext) + { + pstDom = (TDomain *)list->psvData; + Tlog("NODE:%X, %s:%d, Group:%d, Try:%d, Time:%d, Keep:%d", list, pstDom->m_szIp, + pstDom->m_lPort, pstDom->m_lGroup, pstDom->m_lTryMax, pstDom->m_lTimeOut, + pstDom->m_lKeepLive); + } + + Tlog("=-=-=-=-=-=-=-=-=-=- Remote table resource announcement -=-=-=-=-=-=-=-=-=-=-="); + for(list = pGetTblgrp(); list; list = list->pstNext) + { + Tlog("NODE:%X, TABLE:%d", list, *((TABLE *)list->psvData)); + for(node = list->pstSSet; node; node = node->pstNext) + { + pstDom = (TDomain *)node->psvData; + Tlog("\t>>TABLE:%s, PART:%s, OWNER:%s, pstFset:%X", pstDom->m_szTable, + pstDom->m_szPart, pstDom->m_szOwner, node->pstFset); + } + } + + vSetBootType(lType); + vDomainEvent(pstSavm, lPort); + return ; +} + +/************************************************************************************************* + description:boot local process + parameters: + pstSavm --stvm handle + pstBoot --boot parameter + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lBootLocal(SATvm *pstSavm, TBoot *pstBoot, Benum eMode) +{ + int i; + pid_t lPid; + epollevt event; + BSock epfd = -1; + pthread_t *tPid = NULL; + SKCon *pstCon = NULL; + + if(!pstBoot || pstBoot->m_lBootExec < 1) // 线程数量 + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + if(TVM_BOOT_SIMPLE == pstBoot->m_lBootType) + return RC_SUCC; + +/* + pthread_mutex_init(&mutex_thread_read, NULL); + pthread_cond_init(&cond_thread_read, NULL); +*/ + if(NULL == (pstCon = (SKCon *)calloc(sizeof(SKCon), 1))) + { + fprintf(stderr, "create memory, err:(%d)(%s)", errno, strerror(errno)); + return RC_FAIL; + } + + pstCon->m_isListen = 1; + if(0 > (pstCon->m_skSock = skServerInitail(pstSavm, pstBoot->m_lBootPort))) + return RC_FAIL; + + vSetTitile(TVM_LOCAL_SERV); + fprintf(stdout, "Boot process(%s), total %ld process\n", TVM_LOCAL_SERV, pstBoot->m_lBootExec); + if(0 > (lPid = fork())) + { + close(pstCon->m_skSock); + return RC_FAIL; + } + else if(lPid > 0) + { + usleep(500); + return RC_SUCC; + } + + epfd = epoll_create(MAX_EVENTS); + + memset(&event, 0, sizeof(event)); + event.data.ptr = pstCon; + event.events = EPOLLIN | EPOLLET; + if(0 != epoll_ctl(epfd, EPOLL_CTL_ADD, pstCon->m_skSock, &event)) + { + fprintf(stderr, "add socket (%d) error, err:(%d)(%s)", pstCon->m_skSock, + errno, strerror(errno)); + return -1; + } + + signal(SIGPIPE, SIG_IGN); + signal(SIGTRAP, SIG_IGN); + tPid = malloc(sizeof(pthread_t) * pstBoot->m_lBootExec); + vHoldConnect(pstSavm); + for(i = 0; i < pstBoot->m_lBootExec; i ++) + { + if(0 != pthread_create(&tPid[i], NULL, vEpollListen, (void*)&epfd)) + { + fprintf(stderr, "create thread error, %s\n", strerror(errno)); + exit(-1); + } + } + + fprintf(stdout, " process %s id=%d ... success\n", TVM_LOCAL_SERV, getpid()); + fflush(stdout); + + vRemoteResouce(pstSavm, eMode, pstBoot->m_lBootPort); + vTvmDisconnect(pstSavm); + for(i = 0; i < pstBoot->m_lBootExec; i ++) + { + for(usleep(1000);ESRCH != pthread_kill(tPid[i], 0); usleep(1000)); + } + + vCloseDomain(); + TFree(tPid); + Tlog("Service thread exits"); + exit(-1); +} + +/************************************************************************************************* + * Domain maintenance interface + *************************************************************************************************/ +/************************************************************************************************* + description:Notification reconnect the domain + parameters: + pstSavm --stvm handle + pstDom --remote domain + lPort --local port + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lConnectNotify(SATvm *pstSavm, TDomain *pstDom, long lPort) +{ + long lWrite; + void *pvData = NULL; + + lWrite = sizeof(TFace) + sizeof(TDomain); + if(NULL == (pvData = (char *)calloc(1, lWrite))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + pstDom->m_skSock = skConnectServer(pstSavm, LOCAL_HOST_IP, lPort, false, 5); + if(RC_FAIL == pstDom->m_skSock) + { + fprintf(stderr, "Connect server %s:%ld error, %s\n", LOCAL_HOST_IP, lPort, + sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + ((TFace *)pvData)->m_lFind = lPort; + ((TFace *)pvData)->m_enum = OPERATE_DMRECN; + ((TFace *)pvData)->m_table = SYS_TVM_INDEX; + ((TFace *)pvData)->m_lDLen = sizeof(TDomain); + ((TFace *)pvData)->m_lRows = sizeof(TDomain); + memcpy(pvData + sizeof(TFace), pstDom, sizeof(TDomain)); + if(lWrite != lSendBuffer(pstDom->m_skSock, (void *)pvData, lWrite)) + { + vCloseSocket(pstDom); + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(pstDom->m_skSock, (char *)pvData, sizeof(TFace))) + { + vCloseSocket(pstDom); + return RC_FAIL; + } + + vCloseSocket(pstDom); + pstSavm->m_lErrno = ((TFace *)pvData)->m_lErrno; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + return RC_SUCC; +} + +/************************************************************************************************* + description:Notification refresh the domain + parameters: + pstSavm --stvm handle + lPort --local port + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lRefreshNotify(SATvm *pstSavm, long lPort) +{ + BSock skSock; + TFace stFace; + + stFace.m_lRows = 0; + stFace.m_lDLen = 0; + stFace.m_lFind = lPort; + stFace.m_table = SYS_TVM_INDEX; + stFace.m_enum = OPERATE_REFRESH; + skSock = skConnectServer(pstSavm, LOCAL_HOST_IP, lPort, false, 5); + if(RC_FAIL == skSock) + { + fprintf(stderr, "Connect server %s:%ld error, %s\n", LOCAL_HOST_IP, lPort, + sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + if(sizeof(TFace) != lSendBuffer(skSock, (void *)&stFace, sizeof(TFace))) + { + close(skSock); + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(skSock, (char *)&stFace, sizeof(TFace))) + { + close(skSock); + return RC_FAIL; + } + close(skSock); + + pstSavm->m_lErrno = stFace.m_lErrno; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + + return RC_SUCC; +} + +/************************************************************************************************* + description:Notification offline + parameters: + pstSavm --stvm handle + lPort --local port + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lOfflineNotify(SATvm *pstSavm, long lPort) +{ + BSock skSock; + TFace stFace; + + stFace.m_lRows = 0; + stFace.m_lDLen = 0; + stFace.m_lFind = lPort; + stFace.m_table = SYS_TVM_INDEX; + stFace.m_enum = OPERATE_DOMLOFF; + if(RC_FAIL == (skSock = skConnectServer(pstSavm, LOCAL_HOST_IP, lPort, false, 5))) + { + fprintf(stderr, "Connect server %s:%ld error, %s\n", LOCAL_HOST_IP, lPort, + sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + if(sizeof(TFace) != lSendBuffer(skSock, (void *)&stFace, sizeof(TFace))) + { + close(skSock); + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(skSock, (char *)&stFace, sizeof(TFace))) + { + close(skSock); + return RC_FAIL; + } + close(skSock); + + pstSavm->m_lErrno = stFace.m_lErrno; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + + return RC_SUCC; +} + +/************************************************************************************************* + description:Notifies to clone remote table + parameters: + pstSavm --stvm handle + pstDom --remote domain + lCount --record + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lPullNotify(SATvm *pstSavm, TDomain *pstDom, size_t lCount) +{ + TblDef stDet; + TFace stFace; + void *pvData = NULL; + size_t lRecv, i, lRow = 0, lValid; + + memset(&stDet, 0, sizeof(TblDef)); + memset(&stFace, 0, sizeof(TFace)); + stFace.m_lRows = 0; + stFace.m_lFind = lCount; + stFace.m_enum = OPERATE_PULTBL; + stFace.m_table = pstDom->m_mtable; + if(RC_FAIL == (pstDom->m_skSock = skConnectServer(pstSavm, pstDom->m_szIp, pstDom->m_lPort, + false, pstDom->m_lTimeOut))) + { + fprintf(stderr, "Connect server %s:%ld error, %s\n", LOCAL_HOST_IP, pstDom->m_lPort, + sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + if(sizeof(TFace) != lSendBuffer(pstDom->m_skSock, (void *)&stFace, sizeof(TFace))) + goto ERR_PULLNOTIFY; + + if(sizeof(TFace) != lRecvBuffer(pstDom->m_skSock, (void *)&stFace, sizeof(TFace))) + goto ERR_PULLNOTIFY; + + pstSavm->m_lErrno = stFace.m_lErrno; + if(0 != pstSavm->m_lErrno) + goto ERR_PULLNOTIFY; + + fprintf(stdout, "\nCopying table(%s)(%d) define ..", pstDom->m_szTable, pstDom->m_table); + fflush(stdout); + usleep(5000); + if(sizeof(TblDef) != lRecvBuffer(pstDom->m_skSock, (void *)&stDet, sizeof(TblDef))) + goto ERR_PULLNOTIFY; + + lValid = stDet.m_lValid; + stDet.m_lValid = 0; + stDet.m_lGroup = 0; + if(RC_SUCC != lCustomTable(pstSavm, pstDom->m_table, stDet.m_lMaxRow, &stDet)) + { + fprintf(stderr, "Create table(%d) failed, err:(%d)(%s)\n", pstDom->m_table, + pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + fprintf(stdout, "\b\bcompleted .\nCopy table(%s) success, table maxrow:%d, valid:%ld " + " completed .\n", stDet.m_szTable, stDet.m_lMaxRow, lValid); + fflush(stdout); + if(NULL == (pstSavm = (SATvm *)pInitSATvm(pstDom->m_table))) + { + fprintf(stderr, "initial table(%s) error, err:(%d)(%s)\n", pstDom->m_szTable, + pstSavm->m_lErrno, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + fprintf(stdout, "Start Copy table(%s)(%s)rows:[", pstDom->m_szTable, pstDom->m_szPart); + fprintf(stdout, "\033[?25l"); + + if(NULL == (pvData = (char *)malloc(lCount * stDet.m_lReSize))) + goto ERR_PULLNOTIFY; + + pstSavm->lSize = stDet.m_lReSize; + while(1) + { + if(sizeof(TFace) != lRecvBuffer(pstDom->m_skSock, (void *)&stFace, sizeof(TFace))) + goto ERR_PULLNOTIFY; + + if(0 == stFace.m_lRows) + break; + + lRecv = stDet.m_lReSize * stFace.m_lRows; + if(lRecv != lRecvBuffer(pstDom->m_skSock, (char *)pvData, lRecv)) + goto ERR_PULLNOTIFY; + + for(i = 0; i < stFace.m_lRows; i ++) + { + pstSavm->pstVoid = (void *)pvData + i * stDet.m_lReSize; + if(RC_SUCC != lInsert(pstSavm)) + goto ERR_PULLNOTIFY; + + ++ lRow; + vPrintProgresss(lRow, lValid); + } + } + TFree(pvData); + fprintf(stdout, "\n"); + fprintf(stdout, "\033[?25h"); + fprintf(stdout, "Copy (%s)(%s) success,rows(%ld), completed successfully!!!\n", + pstDom->m_szTable, pstDom->m_szPart, lRow); + fflush(stdout); + + vCloseSocket(pstDom); + return RC_SUCC; + +ERR_PULLNOTIFY: + fprintf(stdout, "\n"); + fprintf(stdout, "\033[?25h"); + fflush(stdout); + TFree(pvData); + vCloseSocket(pstDom); + return RC_FAIL; +} + + +/************************************************************************************************* + Remote table access + *************************************************************************************************/ +/************************************************************************************************* + description:remote - Select + parameters: + pstSavm --stvm handle + psvOut --out of data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lSelectByRt(SATvm *pstSavm, void *psvOut) +{ + long lRet; + TDomain *pvm, *pnoe; + Rowgrp *list = NULL, *node = NULL; + + if(NULL == (node = pGetTblNode(pstSavm->tblName))) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstSavm->m_lErrno = RESOU_DISABLE; + switch(lGetBootType()) + { + case TVM_BOOT_CLUSTER: + for(list = node->pstSSet; list; list = list->pstNext) + { + if(!list->pstFset) + continue; + + if(NULL == (pvm = (TDomain *)(list->pstFset->psvData))) + continue; + + pnoe = (TDomain *)list->psvData; + if(0 == (OPERATE_SELECT & pnoe->m_lPers) || RESOURCE_ABLE != pvm->m_lStatus || + pnoe->m_lRelia < 0) + continue; + + pstSavm->m_skSock = pvm->m_skSock; + pstSavm->tblName = pnoe->m_mtable; + pthread_mutex_lock(&list->pstFset->lock); + lRet = lTvmSelect(pstSavm, psvOut); + if(RC_SUCC == lRet || SOCK_COM_EXCP != pstSavm->m_lErrno) + { + pvm->m_lTryTimes = 0; + pvm->m_lLastTime = time(NULL); + } + + pthread_mutex_unlock(&list->pstFset->lock); + return lRet; + } + return RC_FAIL; + default: + for(list = node->pstSSet; list; list = list->pstNext) + { + if(NULL == (pvm = (TDomain *)(list->psvData))) + continue; + + if(0 == (OPERATE_SELECT & pvm->m_lPers)) + continue; + + if(RC_SUCC != lTvmConnect(pstSavm, pvm->m_szIp, pvm->m_lPort, pvm->m_lTimeOut)) + continue; + + pstSavm->tblName = pvm->m_mtable; + lRet = lTvmSelect(pstSavm, psvOut); + if(RC_SUCC == lRet || SOCK_COM_EXCP != pstSavm->m_lErrno) + { + close(pstSavm->m_skSock); + ((RunTime *)pGetRunTime(pstSavm, 0))->m_lRowSize = 0; + TFree(((RunTime *)pGetRunTime(pstSavm, 0))->pstVoid); + return lRet; + } + + close(pstSavm->m_skSock); + } + + ((RunTime *)pGetRunTime(pstSavm, 0))->m_lRowSize = 0; + TFree(((RunTime *)pGetRunTime(pstSavm, 0))->pstVoid); + return RC_FAIL; + } +} + +/************************************************************************************************* + description:remote - Query + parameters: + pstSavm --stvm handle + plOut --number + psvOut --out of data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lQueryByRt(SATvm *pstSavm, size_t *plOut, void **ppsvOut) +{ + long lRet; + TDomain *pvm, *pnoe; + Rowgrp *list = NULL, *node = NULL; + + if(NULL == (node = pGetTblNode(pstSavm->tblName))) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstSavm->m_lErrno = RESOU_DISABLE; + switch(lGetBootType()) + { + case TVM_BOOT_CLUSTER: + for(list = node->pstSSet; list; list = list->pstNext) + { + if(!list->pstFset) + continue; + + if(NULL == (pvm = (TDomain *)(list->pstFset->psvData))) + continue; + + pnoe = (TDomain *)list->psvData; + if(0 == (OPERATE_SELECT & pnoe->m_lPers) || RESOURCE_ABLE != pvm->m_lStatus || + pnoe->m_lRelia < 0) + continue; + + pstSavm->m_skSock = pvm->m_skSock; + pstSavm->tblName = pnoe->m_mtable; + pthread_mutex_lock(&list->pstFset->lock); + lRet = lTvmQuery(pstSavm, plOut, ppsvOut); + if(RC_SUCC == lRet || SOCK_COM_EXCP != pstSavm->m_lErrno) + { + pvm->m_lTryTimes = 0; + pvm->m_lLastTime = time(NULL); + } + + pthread_mutex_unlock(&list->pstFset->lock); + return lRet; + } + + return RC_FAIL; + default: + for(list = node->pstSSet; list; list = list->pstNext) + { + if(NULL == (pvm = (TDomain *)(list->psvData))) + continue; + + if(0 == (OPERATE_SELECT & pvm->m_lPers)) + continue; + + if(RC_SUCC != lTvmConnect(pstSavm, pvm->m_szIp, pvm->m_lPort, pvm->m_lTimeOut)) + continue; + + pstSavm->tblName = pvm->m_mtable; + lRet = lTvmQuery(pstSavm, plOut, ppsvOut); + if(RC_SUCC == lRet || SOCK_COM_EXCP != pstSavm->m_lErrno) + { + close(pstSavm->m_skSock); + ((RunTime *)pGetRunTime(pstSavm, 0))->m_lRowSize = 0; + TFree(((RunTime *)pGetRunTime(pstSavm, 0))->pstVoid); + return lRet; + } + + close(pstSavm->m_skSock); + } + + ((RunTime *)pGetRunTime(pstSavm, 0))->m_lRowSize = 0; + TFree(((RunTime *)pGetRunTime(pstSavm, 0))->pstVoid); + return RC_FAIL; + } +} + +/************************************************************************************************* + description:remote - Delete + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lDeleteByRt(SATvm *pstSavm) +{ + TDomain *pvm, *pnoe; + long lRet = RC_FAIL; + Rowgrp *list = NULL, *node = NULL; + + if(NULL == (node = pGetTblNode(pstSavm->tblName))) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstSavm->m_lErrno = RESOU_DISABLE; + switch(lGetBootType()) + { + case TVM_BOOT_CLUSTER: + for(list = node->pstSSet; list; list = list->pstNext) + { + if(!list->pstFset) + continue; + + if(NULL == (pvm = (TDomain *)(list->pstFset->psvData))) + continue; + + pnoe = (TDomain *)list->psvData; + if(0 == (OPERATE_DELETE & pnoe->m_lPers) || RESOURCE_ABLE != pvm->m_lStatus) + continue; + + pstSavm->m_skSock = pvm->m_skSock; + pstSavm->tblName = pnoe->m_mtable; + pthread_mutex_lock(&list->pstFset->lock); + if(RC_SUCC == lTvmDelete(pstSavm)) + { + lRet = RC_SUCC; + pvm->m_lTryTimes = 0; + pvm->m_lLastTime = time(NULL); + } + else if(SOCK_COM_EXCP == pstSavm->m_lErrno) + { + pnoe->m_lRelia --; + Tlog("Delete err: %s, T(%d), F(%s:%d), R(%d)", sGetTError(pstSavm->m_lErrno), + pstSavm->tblName, pvm->m_szIp, pvm->m_lPort, pnoe->m_lRelia); + } + + pthread_mutex_unlock(&list->pstFset->lock); + } + return lRet; + default: + for(list = node->pstSSet; list; list = list->pstNext) + { + if(NULL == (pvm = (TDomain *)(list->psvData))) + continue; + + if(0 == (OPERATE_DELETE & pvm->m_lPers)) + continue; + + if(RC_SUCC != lTvmConnect(pstSavm, pvm->m_szIp, pvm->m_lPort, pvm->m_lTimeOut)) + continue; + + pstSavm->tblName = pvm->m_mtable; + lRet = lTvmDelete(pstSavm); + if(RC_SUCC == lRet || SOCK_COM_EXCP != pstSavm->m_lErrno) + { + close(pstSavm->m_skSock); + ((RunTime *)pGetRunTime(pstSavm, 0))->m_lRowSize = 0; + TFree(((RunTime *)pGetRunTime(pstSavm, 0))->pstVoid); + return lRet; + } + + close(pstSavm->m_skSock); + } + + ((RunTime *)pGetRunTime(pstSavm, 0))->m_lRowSize = 0; + TFree(((RunTime *)pGetRunTime(pstSavm, 0))->pstVoid); + return lRet; + } +} + +/************************************************************************************************* + description:remote - Truncate + parameters: + pstSavm --stvm handle + t --table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lTruncateByRt(SATvm *pstSavm, TABLE t) +{ + TDomain *pvm, *pnoe; + long lRet = RC_FAIL; + Rowgrp *list = NULL, *node = NULL; + + if(NULL == (node = pGetTblNode(t))) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstSavm->m_lErrno = RESOU_DISABLE; + switch(lGetBootType()) + { + case TVM_BOOT_CLUSTER: + for(list = node->pstSSet; list; list = list->pstNext) + { + if(!list->pstFset) + continue; + + if(NULL == (pvm = (TDomain *)(list->pstFset->psvData))) + continue; + + pnoe = (TDomain *)list->psvData; + if(0 == (OPERATE_DELETE & pnoe->m_lPers) || RESOURCE_ABLE != pvm->m_lStatus) + continue; + + pstSavm->m_skSock = pvm->m_skSock; + pstSavm->tblName = pnoe->m_mtable; + pthread_mutex_lock(&list->pstFset->lock); + if(RC_SUCC == lTvmTruncate(pstSavm, pstSavm->tblName)) + { + lRet = RC_SUCC; + pvm->m_lTryTimes = 0; + pvm->m_lLastTime = time(NULL); + } + else if(SOCK_COM_EXCP == pstSavm->m_lErrno) + { + pnoe->m_lRelia --; + Tlog("Truncate err: %s, T(%d), F(%s:%d), R(%d)", sGetTError(pstSavm->m_lErrno), + pstSavm->tblName, pvm->m_szIp, pvm->m_lPort, pnoe->m_lRelia); + } + + pthread_mutex_unlock(&list->pstFset->lock); + } + return lRet; + default: + for(list = node->pstSSet; list; list = list->pstNext) + { + if(NULL == (pvm = (TDomain *)(list->psvData))) + continue; + + if(0 == (OPERATE_DELETE & pvm->m_lPers)) + continue; + + if(RC_SUCC != lTvmConnect(pstSavm, pvm->m_szIp, pvm->m_lPort, pvm->m_lTimeOut)) + continue; + + pstSavm->tblName = pvm->m_mtable; + lRet = lTvmTruncate(pstSavm, pstSavm->tblName); + if(RC_SUCC == lRet || SOCK_COM_EXCP != pstSavm->m_lErrno) + { + close(pstSavm->m_skSock); + ((RunTime *)pGetRunTime(pstSavm, 0))->m_lRowSize = 0; + TFree(((RunTime *)pGetRunTime(pstSavm, 0))->pstVoid); + return lRet; + } + + close(pstSavm->m_skSock); + } + + ((RunTime *)pGetRunTime(pstSavm, 0))->m_lRowSize = 0; + TFree(((RunTime *)pGetRunTime(pstSavm, 0))->pstVoid); + + return lRet; + } +} + +/************************************************************************************************* + description:remote - Insert + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lInsertByRt(SATvm *pstSavm) +{ + TDomain *pvm, *pnoe; + long lRet = RC_FAIL; + Rowgrp *list = NULL, *node = NULL; + + if(NULL == (node = pGetTblNode(pstSavm->tblName))) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstSavm->m_lErrno = RESOU_DISABLE; + switch(lGetBootType()) + { + case TVM_BOOT_CLUSTER: + for(list = node->pstSSet; list; list = list->pstNext) + { + if(!list->pstFset) + continue; + if(NULL == (pvm = (TDomain *)(list->pstFset->psvData))) + continue; + + pnoe = (TDomain *)list->psvData; + if(0 == (OPERATE_INSERT & pnoe->m_lPers) || RESOURCE_ABLE != pvm->m_lStatus) + continue; + + pstSavm->m_skSock = pvm->m_skSock; + pstSavm->tblName = pnoe->m_mtable; + pthread_mutex_lock(&list->pstFset->lock); + if(RC_SUCC == lTvmInsert(pstSavm)) + { + lRet = RC_SUCC; + pvm->m_lTryTimes = 0; + pvm->m_lLastTime = time(NULL); + } + else if(SOCK_COM_EXCP == pstSavm->m_lErrno) + { + pnoe->m_lRelia --; + Tlog("Insert err: %s, T(%d), F(%s:%d), R(%d)", sGetTError(pstSavm->m_lErrno), + pstSavm->tblName, pvm->m_szIp, pvm->m_lPort, pnoe->m_lRelia); + } + + pthread_mutex_unlock(&list->pstFset->lock); + } + return lRet; + default: + for(list = node->pstSSet; list; list = list->pstNext) + { + if(NULL == (pvm = (TDomain *)(list->psvData))) + continue; + + if(0 == (OPERATE_INSERT & pvm->m_lPers)) + continue; + + if(RC_SUCC != lTvmConnect(pstSavm, pvm->m_szIp, pvm->m_lPort, pvm->m_lTimeOut)) + continue; + + pstSavm->tblName = pvm->m_mtable; + lRet = lTvmInsert(pstSavm); + if(RC_SUCC == lRet || SOCK_COM_EXCP != pstSavm->m_lErrno) + { + close(pstSavm->m_skSock); + ((RunTime *)pGetRunTime(pstSavm, 0))->m_lRowSize = 0; + TFree(((RunTime *)pGetRunTime(pstSavm, 0))->pstVoid); + return lRet; + } + + close(pstSavm->m_skSock); + } + + ((RunTime *)pGetRunTime(pstSavm, 0))->m_lRowSize = 0; + TFree(((RunTime *)pGetRunTime(pstSavm, 0))->pstVoid); + return lRet; + } +} + +/************************************************************************************************* + description:remote - Update + parameters: + pstSavm --stvm handle + psvUpdate --update + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lUpdateByRt(SATvm *pstSavm, void *pvUpdate) +{ + TDomain *pvm, *pnoe; + long lRet = RC_FAIL; + Rowgrp *list = NULL, *node = NULL; + + if(NULL == (node = pGetTblNode(pstSavm->tblName))) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstSavm->m_lErrno = RESOU_DISABLE; + switch(lGetBootType()) + { + case TVM_BOOT_CLUSTER: + for(list = node->pstSSet; list; list = list->pstNext) + { + if(!list->pstFset) + continue; + + if(NULL == (pvm = (TDomain *)(list->pstFset->psvData))) + continue; + + pnoe = (TDomain *)list->psvData; + if(0 == (OPERATE_UPDATE & pnoe->m_lPers) || RESOURCE_ABLE != pvm->m_lStatus) + continue; + + pstSavm->m_skSock = pvm->m_skSock; + pstSavm->tblName = pnoe->m_mtable; + pthread_mutex_lock(&list->pstFset->lock); + if(RC_SUCC == lTvmUpdate(pstSavm, pvUpdate)) + { + lRet = RC_SUCC; + pvm->m_lTryTimes = 0; + pvm->m_lLastTime = time(NULL); + } + else if(SOCK_COM_EXCP == pstSavm->m_lErrno) + { + pnoe->m_lRelia --; + Tlog("Update err: %s, T(%d), F(%s:%d), R(%d)", sGetTError(pstSavm->m_lErrno), + pstSavm->tblName, pvm->m_szIp, pvm->m_lPort, pnoe->m_lRelia); + } + + pthread_mutex_unlock(&list->pstFset->lock); + } + return lRet; + default: + for(list = node->pstSSet; list; list = list->pstNext) + { + if(NULL == (pvm = (TDomain *)(list->psvData))) + continue; + + if(0 == (OPERATE_UPDATE & pvm->m_lPers)) + continue; + + if(RC_SUCC != lTvmConnect(pstSavm, pvm->m_szIp, pvm->m_lPort, pvm->m_lTimeOut)) + continue; + + pstSavm->tblName = pvm->m_mtable; + lRet = lTvmUpdate(pstSavm, pvUpdate); + if(RC_SUCC == lRet || SOCK_COM_EXCP != pstSavm->m_lErrno) + { + close(pstSavm->m_skSock); + ((RunTime *)pGetRunTime(pstSavm, 0))->m_lRowSize = 0; + TFree(((RunTime *)pGetRunTime(pstSavm, 0))->pstVoid); + return lRet; + } + + close(pstSavm->m_skSock); + } + + ((RunTime *)pGetRunTime(pstSavm, 0))->m_lRowSize = 0; + TFree(((RunTime *)pGetRunTime(pstSavm, 0))->pstVoid); + return lRet; + } +} + +/************************************************************************************************* + description:remote - Group + parameters: + pstSavm --stvm handle + plOut --number + psvOut --out of data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lGroupByRt(SATvm *pstSavm, size_t *plOut, void **ppvOut) +{ + long lRet; + TDomain *pvm, *pnoe; + Rowgrp *list = NULL, *node = NULL; + + if(NULL == (node = pGetTblNode(pstSavm->tblName))) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstSavm->m_lErrno = RESOU_DISABLE; + switch(lGetBootType()) + { + case TVM_BOOT_CLUSTER: + for(list = node->pstSSet; list; list = list->pstNext) + { + if(!list->pstFset) + continue; + + if(NULL == (pvm = (TDomain *)(list->pstFset->psvData))) + continue; + + pnoe = (TDomain *)list->psvData; + if(0 == (OPERATE_SELECT & pnoe->m_lPers) || RESOURCE_ABLE != pvm->m_lStatus || + pnoe->m_lRelia < 0) + continue; + + pstSavm->m_skSock = pvm->m_skSock; + pstSavm->tblName = pnoe->m_mtable; + pthread_mutex_lock(&list->pstFset->lock); + lRet = lTvmGroup(pstSavm, plOut, ppvOut); + if(RC_SUCC == lRet || SOCK_COM_EXCP != pstSavm->m_lErrno) + { + pvm->m_lTryTimes = 0; + pvm->m_lLastTime = time(NULL); + } + + pthread_mutex_unlock(&list->pstFset->lock); + return lRet; + } + return RC_FAIL; + default: + for(list = node->pstSSet; list; list = list->pstNext) + { + if(NULL == (pvm = (TDomain *)(list->psvData))) + continue; + + if(0 == (OPERATE_SELECT & pvm->m_lPers)) + continue; + + if(RC_SUCC != lTvmConnect(pstSavm, pvm->m_szIp, pvm->m_lPort, pvm->m_lTimeOut)) + continue; + + pstSavm->tblName = pvm->m_mtable; + lRet = lTvmGroup(pstSavm, plOut, ppvOut); + if(RC_SUCC == lRet || SOCK_COM_EXCP != pstSavm->m_lErrno) + { + close(pstSavm->m_skSock); + ((RunTime *)pGetRunTime(pstSavm, 0))->m_lRowSize = 0; + TFree(((RunTime *)pGetRunTime(pstSavm, 0))->pstVoid); + return lRet; + } + + close(pstSavm->m_skSock); + } + + ((RunTime *)pGetRunTime(pstSavm, 0))->m_lRowSize = 0; + TFree(((RunTime *)pGetRunTime(pstSavm, 0))->pstVoid); + return RC_FAIL; + } +} + +/************************************************************************************************* + description:remote - Count + parameters: + pstSavm --stvm handle + plOut --count + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lCountByRt(SATvm *pstSavm, size_t *plCount) +{ + long lRet; + TDomain *pvm, *pnoe; + Rowgrp *list = NULL, *node = NULL; + + if(NULL == (node = pGetTblNode(pstSavm->tblName))) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstSavm->m_lErrno = RESOU_DISABLE; + switch(lGetBootType()) + { + case TVM_BOOT_CLUSTER: + for(list = node->pstSSet; list; list = list->pstNext) + { + if(!list->pstFset) + continue; + + if(NULL == (pvm = (TDomain *)(list->pstFset->psvData))) + continue; + + pnoe = (TDomain *)list->psvData; + if(0 == (OPERATE_SELECT & pnoe->m_lPers) || RESOURCE_ABLE != pvm->m_lStatus || + pnoe->m_lRelia < 0) + continue; + + pstSavm->m_skSock = pvm->m_skSock; + pstSavm->tblName = pnoe->m_mtable; + pthread_mutex_lock(&list->pstFset->lock); + lRet = lTvmCount(pstSavm, plCount); + if(RC_SUCC == lRet || SOCK_COM_EXCP != pstSavm->m_lErrno) + { + pvm->m_lTryTimes = 0; + pvm->m_lLastTime = time(NULL); + } + + pthread_mutex_unlock(&list->pstFset->lock); + return lRet; + } + return RC_FAIL; + default: + for(list = node->pstSSet; list; list = list->pstNext) + { + if(NULL == (pvm = (TDomain *)(list->psvData))) + continue; + + if(0 == (OPERATE_SELECT & pvm->m_lPers)) + continue; + + if(RC_SUCC != lTvmConnect(pstSavm, pvm->m_szIp, pvm->m_lPort, pvm->m_lTimeOut)) + continue; + + pstSavm->tblName = pvm->m_mtable; + lRet = lTvmCount(pstSavm, plCount); + if(RC_SUCC == lRet || SOCK_COM_EXCP != pstSavm->m_lErrno) + { + close(pstSavm->m_skSock); + ((RunTime *)pGetRunTime(pstSavm, 0))->m_lRowSize = 0; + TFree(((RunTime *)pGetRunTime(pstSavm, 0))->pstVoid); + return lRet; + } + + close(pstSavm->m_skSock); + } + + ((RunTime *)pGetRunTime(pstSavm, 0))->m_lRowSize = 0; + TFree(((RunTime *)pGetRunTime(pstSavm, 0))->pstVoid); + return RC_FAIL; + } +} + +/************************************************************************************************* + description:remote - Extreme + parameters: + pstSavm --stvm handle + psvOut --out of data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lExtremeByRt(SATvm *pstSavm, void *psvOut) +{ + long lRet; + TDomain *pvm, *pnoe; + Rowgrp *list = NULL, *node = NULL; + + if(NULL == (node = pGetTblNode(pstSavm->tblName))) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstSavm->m_lErrno = RESOU_DISABLE; + switch(lGetBootType()) + { + case TVM_BOOT_CLUSTER: + for(list = node->pstSSet; list; list = list->pstNext) + { + if(!list->pstFset) + continue; + + if(NULL == (pvm = (TDomain *)(list->pstFset->psvData))) + continue; + + pnoe = (TDomain *)list->psvData; + if(0 == (OPERATE_SELECT & pnoe->m_lPers) || RESOURCE_ABLE != pvm->m_lStatus || + pnoe->m_lRelia < 0) + continue; + + pstSavm->m_skSock = pvm->m_skSock; + pstSavm->tblName = pnoe->m_mtable; + pthread_mutex_lock(&list->pstFset->lock); + lRet = lTvmExtreme(pstSavm, psvOut); + if(RC_SUCC == lRet || SOCK_COM_EXCP != pstSavm->m_lErrno) + { + pvm->m_lTryTimes = 0; + pvm->m_lLastTime = time(NULL); + } + + pthread_mutex_unlock(&list->pstFset->lock); + return lRet; + } + return RC_FAIL; + default: + for(list = node->pstSSet; list; list = list->pstNext) + { + if(NULL == (pvm = (TDomain *)(list->psvData))) + continue; + + if(0 == (OPERATE_SELECT & pvm->m_lPers)) + continue; + + if(RC_SUCC != lTvmConnect(pstSavm, pvm->m_szIp, pvm->m_lPort, pvm->m_lTimeOut)) + continue; + + pstSavm->tblName = pvm->m_mtable; + lRet = lTvmExtreme(pstSavm, psvOut); + if(RC_SUCC == lRet || SOCK_COM_EXCP != pstSavm->m_lErrno) + { + close(pstSavm->m_skSock); + ((RunTime *)pGetRunTime(pstSavm, 0))->m_lRowSize = 0; + TFree(((RunTime *)pGetRunTime(pstSavm, 0))->pstVoid); + return lRet; + } + + close(pstSavm->m_skSock); + } + + ((RunTime *)pGetRunTime(pstSavm, 0))->m_lRowSize = 0; + TFree(((RunTime *)pGetRunTime(pstSavm, 0))->pstVoid); + return RC_FAIL; + } +} + +/************************************************************************************************* + description:remote - Droptable + parameters: + pstSavm --stvm handle + t --table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +void _vDropTableByRt(SATvm *pstSavm, TABLE t) +{ + Rowgrp *node = NULL; + + if(NULL == (node = pGetTblNode(t))) + return ; + + memset(node->psvData, 0, sizeof(TABLE)); +// vDropNodegrp(&g_pstTblgrp, node); +} + +/************************************************************************************************* + description:remote - Rename + parameters: + pstSavm --stvm handle + to --from table + tn --to table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lRenameTableByRt(SATvm *pstSavm, TABLE to, TABLE tn) +{ + TDomain stDom, stUpd; + Rowgrp *node = NULL; + + if(NULL == (node = pGetTblNode(to))) + return RC_SUCC; + + if(RC_SUCC != lInitSATvm(pstSavm, SYS_TVM_DOMAIN)) + return RC_FAIL; + + updateinit(stUpd); + conditinit(pstSavm, stDom, SYS_TVM_DOMAIN); + numberset(pstSavm, stDom, m_table, to) + numberupd(pstSavm, stUpd, m_table, tn); + + if(RC_SUCC != lUpdate(pstSavm, &stUpd)) + return RC_FAIL; + + memcpy(node->psvData, &tn, sizeof(TABLE)); + return RC_SUCC; +} + +/************************************************************************************************* + description:disconnect server + parameters: + pstSavm --stvm handle + return: + *************************************************************************************************/ +void vTvmDisconnect(SATvm *pstSavm) +{ + RunTime *pstRun; + + if(!pstSavm) return ; + + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + pstRun->m_lRowSize = 0; + close(pstSavm->m_skSock); + TFree(pstRun->pstVoid); + + vHoldRelease(pstSavm); +} + +/************************************************************************************************* + description:connect server + parameters: + pstSavm --stvm handle + pszIp --server ip + lPort --server port + times --time out + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmConnect(SATvm *pstSavm, char *pszIp, long lPort, int times) +{ + RunTime *pstRun; + + if(!pstSavm || !pszIp) + return RC_FAIL; + + pstSavm->m_lTimes = times; + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + pstSavm->m_skSock = skConnectServer(pstSavm, pszIp, lPort, false, times); + if(RC_FAIL == pstSavm->m_skSock) + { + Tlog("Connect server %s:%d failed, %s", pszIp, lPort, sGetTError(pstSavm->m_lErrno)); + return RC_FAIL; + } + + return lTvmBuffer(pstSavm); +} + +/************************************************************************************************* + description:parse Java packed + parameters: + pstSavm --stvm handle + pstVoid --conditon + pstFace --request head + pvBuffer --recv buffer + lLen --the length of buffer + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +void* pProtocaJava(SATvm *pstSavm, void *pstVoid, TFace *pstFace, void *pvBuffer, long lLen) +{ + void *pvData, *q; + int i, len, n, m, k; + FdCond *pstCond = &pstSavm->stCond; + char szLen[5] = {0}, szField[MAX_FIELD_LEN]; + TblKey *pstKey, *pv = pGetTblKey(pstFace->m_table); + + if(pstFace->m_lRows == 0) + return pvBuffer; + +// pstFace->m_lDLen +// szName[256]="020020tx_date=201708120016tx_name=DefPuzzL"; + pstCond->uFldcmp = 0; + memcpy(szLen, pvBuffer, 2); + for(i = 0, lLen -= 2, pvData = pvBuffer + 2, k = atol(szLen); i < k; i ++) + { + memcpy(szLen, pvData, 4); + pvData += 4; + + if(lLen < (len = strlen(szLen))) return NULL; + lLen -= (len + 4); + + if(NULL == (q = strstr(pvData, "="))) + return NULL; + + n = q - pvData; + m = MIN(n, MAX_FIELD_LEN); + memcpy(szField, pvData, m); + szField[m] = 0x00; + if(NULL == (pstKey = pFindField(pv, lGetIdxNum(pstFace->m_table), szField))) + return NULL; + + vSetCodField(pstCond, pstKey->m_lLen, pstKey->m_lFrom); + memcpy(pstVoid + pstKey->m_lFrom, pvData + n + 1, m); + pvData += len; + } + + switch(pstFace->m_enum) + { + case OPERATE_INSERT: + return pvBuffer; + case OPERATE_UPDATE: + pstCond = &pstSavm->stUpdt; + pstCond->uFldcmp = 0; + memset(szLen, 0, sizeof(szLen)); + memcpy(szLen, pvBuffer, 2); + pstVoid += pstFace->m_lDLen; + for(i = 0, lLen -= 2, pvData += 2, k = atol(szLen); i < k; i ++) + { + memcpy(szLen, pvData, 4); + pvData += 4; + + if(lLen < (len = strlen(szLen))) return NULL; + lLen -= (len + 4); + + if(NULL == (q = strstr(pvData, "="))) + return NULL; + + n = q - pvData; + m = MIN(n, MAX_FIELD_LEN); + memcpy(szField, pvData, m); + szField[m] = 0x00; + if(NULL == (pstKey = pFindField(pv, lGetIdxNum(pstFace->m_table), szField))) + return NULL; + + vSetCodField(pstCond, pstKey->m_lLen, pstKey->m_lFrom); + memcpy(pstVoid + pstKey->m_lFrom, pvData + n + 1, m); + pvData += len; + } + if(lLen < 0) return NULL; + + return memcpy(pvBuffer, pstVoid, pstFace->m_lDLen); + case OPERATE_SELECT: + case OPERATE_QUERY: + case OPERATE_DELETE: + case OPERATE_TRCATE: + case OPERATE_GROUP: + case OPERATE_EXTREM: + if(lLen < 0) return NULL; + + pstCond = &pstSavm->stUpdt; + pstCond->uFldcmp = 0; + memset(szLen, 0, sizeof(szLen)); + memcpy(szLen, pvBuffer, 2); + for(i = 0, lLen -= 2, pvData += 2, k = atol(szLen); i < k; i ++) + { + memcpy(szLen, pvData, 4); + pvData += 4; + + if(lLen < (len = strlen(szLen))) return NULL; + lLen -= (len + 4); + + if(NULL == (q = strstr(pvData, "="))) + return NULL; + + n = q - pvData; + m = MIN(n, MAX_FIELD_LEN); + memcpy(szField, pvData, m); + szField[m] = 0x00; + if(NULL == (pstKey = pFindField(pv, lGetIdxNum(pstFace->m_table), szField))) + return NULL; + + m = ((char *)pvData)[n + 1]; + vSetDecorate(pstCond, pstKey->m_lLen, pstKey->m_lFrom, (Uenum)m); + pstSavm->lFind = m & FIRST_ROW; + pvData += len; + } + + return pvBuffer; + default: + return pvBuffer; + } + + return NULL; +} + +/************************************************************************************************* + description:parse packed + parameters: + pstSavm --stvm handle + pstVoid --conditon + pstFace --request head + pvBuffer --recv buffer + lLen --the length of buffer + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +void* pParsePacket(SATvm *pstSavm, void *pstVoid, TFace *pstFace, void *pvBuffer, long lLen) +{ + register uint i; + FdKey *pstFld; + void *pvData = pvBuffer; + FdCond *pstCond = &pstSavm->stCond; + + if(pstFace->m_lRows == 0) + return pvBuffer; + + switch(pstFace->m_enum) + { + case OPERATE_INSERT: + return memcpy(pstVoid, pvData, pstFace->m_lDLen); + case OPERATE_UPDATE: + memcpy(&pstCond->uFldcmp, pvData, sizeof(uint)); + for(i = 0, pvData += sizeof(uint); i < pstCond->uFldcmp; i ++) + { + pstFld = &pstCond->stFdKey[i]; + memcpy(pstFld, pvData, sizeof(FdKey)); + pvData += sizeof(FdKey); + memcpy(pstVoid + pstFld->uFldpos, pvData, pstFld->uFldlen); + pvData += pstFld->uFldlen; + } + + pstCond = &pstSavm->stUpdt; + memcpy(&pstCond->uFldcmp, pvData, sizeof(uint)); + if(0 == pstCond->uFldcmp) return pvBuffer; + + for(i = 0, pvData += sizeof(uint), pstVoid += pstFace->m_lDLen; i < pstCond->uFldcmp; i ++) + { + pstFld = &pstCond->stFdKey[i]; + memcpy(pstFld, pvData, sizeof(FdKey)); + pvData += sizeof(FdKey); + memcpy(pstVoid + pstFld->uFldpos, pvData, pstFld->uFldlen); + pvData += pstFld->uFldlen; + } + + return memcpy(pvBuffer, pstVoid, pstFace->m_lDLen); + case OPERATE_SELECT: + case OPERATE_QUERY: + case OPERATE_DELETE: + case OPERATE_TRCATE: + case OPERATE_GROUP: + case OPERATE_COUNT: + case OPERATE_EXTREM: + memcpy(&pstCond->uFldcmp, pvData, sizeof(uint)); + for(i = 0, pvData += sizeof(uint); i < pstCond->uFldcmp; i ++) + { + pstFld = &pstCond->stFdKey[i]; + memcpy(pstFld, pvData, sizeof(FdKey)); + pvData += sizeof(FdKey); + memcpy(pstVoid + pstFld->uFldpos, pvData, pstFld->uFldlen); + pvData += pstFld->uFldlen; + } + + pstCond = &pstSavm->stUpdt; + memcpy(&pstCond->uFldcmp, pvData, sizeof(uint)); + if(0 == pstCond->uFldcmp) return pvBuffer; + + pvData += sizeof(uint); + memcpy(pstCond->stFdKey, pvData, sizeof(FdKey) * pstCond->uFldcmp); + return pvBuffer; +/* + case OPERATE_TBDROP: + case OPERATE_RENAME: + case OPERATE_SELSEQ: + case OPERATE_SETSEQ: + case OPERATE_RETLOK: + case OPERATE_RBDIDX: + case OPERATE_DOMPSH: + case OPERATE_DOMPUL: + .... +*/ + default: + return pvBuffer; + } + + return NULL; +} + +/************************************************************************************************* + description:build condition packed + parameters: + pvData --send buffer + pvBuffer --condition + pstCond --cond field + plRows --length + return: + *************************************************************************************************/ +void vBuildPacket(void *pvData, void *pvBuffer, FdCond *pstCond, uint *plRows) +{ + uint i; + FdKey *pstFld; + + if(!pvBuffer) + { + memset(pvData + (*plRows), 0, sizeof(uint)); + (*plRows) += sizeof(uint); + return; + } + + memcpy(pvData + (*plRows), (void *)&pstCond->uFldcmp, sizeof(uint)); + for(i = 0, (*plRows) += sizeof(uint); i < pstCond->uFldcmp; i ++) + { + pstFld = &pstCond->stFdKey[i]; + memcpy(pvData + (*plRows), (void *)pstFld, sizeof(FdKey)); + (*plRows) += sizeof(FdKey); + memcpy(pvData + (*plRows), pvBuffer + pstFld->uFldpos, pstFld->uFldlen); + (*plRows) += pstFld->uFldlen; + } + + return ; +} + +/************************************************************************************************* + description:parse decorate packed + parameters: + pvData --send buffer + pstCond --decorate field + plRows --length + return: + *************************************************************************************************/ +void vAppendCond(void *pvData, FdCond *pstCond, uint *plRows) +{ + memcpy(pvData + (*plRows), (void *)&pstCond->uFldcmp, sizeof(uint)); + (*plRows) += sizeof(uint); + if(pstCond->uFldcmp <= 0) + return ; + + memcpy(pvData + (*plRows), (void *)&pstCond->stFdKey, pstCond->uFldcmp * sizeof(FdKey)); + (*plRows) += sizeof(FdKey) * pstCond->uFldcmp; + return ; +} + +/************************************************************************************************* + description:API - select + parameters: + pstSavm --stvm handle + pvOut --out data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmSelect(SATvm *pstSavm, void *pvOut) +{ + RunTime *pstRun; + TFace *pstFace; + uint lWrite = sizeof(TFace); + + if(!pstSavm || !pstSavm->pstVoid) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + if(!pstRun->pstVoid) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstFace = (TFace *)pstRun->pstVoid; + pstFace->m_lFind = pstSavm->lFind; + pstFace->m_lDLen = pstSavm->lSize; + pstFace->m_lErrno = TVM_DONE_SUCC; + pstFace->m_enum = OPERATE_SELECT; + pstFace->m_table = pstSavm->tblName; + + checkbuffer(pstSavm, pstRun, 1); + vBuildPacket(pstRun->pstVoid, pstSavm->pstVoid, &pstSavm->stCond, &lWrite); + vAppendCond(pstRun->pstVoid, &pstSavm->stUpdt, &lWrite); + pstFace->m_lRows = lWrite - sizeof(TFace); + + if(lWrite != lSendBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, lWrite)) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + pstSavm->m_lErrno = pstFace->m_lErrno; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + + pstSavm->m_lEffect = pstFace->m_lRows; + if(pstSavm->lSize != lRecvBuffer(pstSavm->m_skSock, (char *)pvOut, pstSavm->lSize)) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:API - query + parameters: + pstSavm --stvm handle + plOut --number + ppvOut --out data list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmQuery(SATvm *pstSavm, size_t *plOut, void **ppvOut) +{ + RunTime *pstRun; + TFace *pstFace; + uint lWrite = sizeof(TFace); + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + if(!pstRun->pstVoid) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstFace = (TFace *)pstRun->pstVoid; + pstFace->m_lFind = pstSavm->lFind; + pstFace->m_lDLen = pstSavm->lSize; + pstFace->m_lErrno = TVM_DONE_SUCC; + pstFace->m_enum = OPERATE_QUERY; + pstFace->m_table = pstSavm->tblName; + + checkbuffer(pstSavm, pstRun, 1); + vBuildPacket(pstRun->pstVoid, pstSavm->pstVoid, &pstSavm->stCond, &lWrite); + vAppendCond(pstRun->pstVoid, &pstSavm->stUpdt, &lWrite); + pstFace->m_lRows = lWrite - sizeof(TFace); + + if(lWrite != lSendBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, lWrite)) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + pstSavm->m_lErrno = pstFace->m_lErrno; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + + pstRun->m_lRowSize = pstSavm->lSize * pstFace->m_lRows; + if(NULL == (*ppvOut = (void *)malloc(pstRun->m_lRowSize))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + if(pstRun->m_lRowSize != lRecvBuffer(pstSavm->m_skSock, (char *)*ppvOut, pstRun->m_lRowSize)) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + *plOut = pstFace->m_lRows; + pstSavm->m_lEffect = pstFace->m_lRows; + return RC_SUCC; +} + +/************************************************************************************************* + description:API - insert + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmInsert(SATvm *pstSavm) +{ + RunTime *pstRun; + TFace *pstFace; + uint lWrite = sizeof(TFace); + + if(!pstSavm || !pstSavm->pstVoid) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + if(!pstRun->pstVoid) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstFace = (TFace *)pstRun->pstVoid; + pstFace->m_lFind = pstSavm->lFind; + pstFace->m_lDLen = pstSavm->lSize; + pstFace->m_lErrno = TVM_DONE_SUCC; + pstFace->m_enum = OPERATE_INSERT; + pstFace->m_table = pstSavm->tblName; + + pstFace->m_lRows = pstSavm->lSize; + lWrite = pstFace->m_lRows + sizeof(TFace); + + checkbuffer(pstSavm, pstRun, 1); + memcpy(pstRun->pstVoid + sizeof(TFace), pstSavm->pstVoid, pstSavm->lSize); + if(lWrite != lSendBuffer(pstSavm->m_skSock, (void *)pstRun->pstVoid, lWrite)) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + pstSavm->m_lErrno = pstFace->m_lErrno; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + + pstSavm->m_lEffect = pstFace->m_lRows; + return RC_SUCC; +} + +/************************************************************************************************* + description:API - delete + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmDelete(SATvm *pstSavm) +{ + RunTime *pstRun; + TFace *pstFace; + uint lWrite = sizeof(TFace); + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + if(!pstRun->pstVoid) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstFace = (TFace *)pstRun->pstVoid; + pstFace->m_lFind = pstSavm->lFind; + pstFace->m_lDLen = pstSavm->lSize; + pstFace->m_lErrno = TVM_DONE_SUCC; + pstFace->m_enum = OPERATE_DELETE; + pstFace->m_table = pstSavm->tblName; + + checkbuffer(pstSavm, pstRun, 1); + vBuildPacket(pstRun->pstVoid, pstSavm->pstVoid, &pstSavm->stCond, &lWrite); + vAppendCond(pstRun->pstVoid, &pstSavm->stUpdt, &lWrite); + pstFace->m_lRows = lWrite - sizeof(TFace); + + if(lWrite != lSendBuffer(pstSavm->m_skSock, (void *)pstRun->pstVoid, lWrite)) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + pstSavm->m_lErrno = ((TFace *)pstRun->pstVoid)->m_lErrno; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + + pstSavm->m_lEffect = ((TFace *)pstRun->pstVoid)->m_lRows; + return RC_SUCC; +} + +/************************************************************************************************* + description:API - update + parameters: + pstSavm --stvm handle + pvData --update data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmUpdate(SATvm *pstSavm, void *pvData) +{ + RunTime *pstRun; + FdCond *pstCond; + TFace *pstFace; + uint lWrite = sizeof(TFace); + + if(!pstSavm || !pvData) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + if(!pstRun->pstVoid) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstFace = (TFace *)pstRun->pstVoid; + pstFace->m_lFind = pstSavm->lFind; + pstFace->m_lDLen = pstSavm->lSize; + pstFace->m_lErrno = TVM_DONE_SUCC; + pstFace->m_enum = OPERATE_UPDATE; + pstFace->m_table = pstSavm->tblName; + + checkbuffer(pstSavm, pstRun, 2); + pstCond = &pstSavm->stUpdt; + if(0 == pstCond->uFldcmp) + { + pstSavm->m_lErrno = UPDFD_NOT_SET; + return RC_FAIL; + } + + vBuildPacket(pstRun->pstVoid, pstSavm->pstVoid, &pstSavm->stCond, &lWrite); + vBuildPacket(pstRun->pstVoid, pvData, pstCond, &lWrite); + pstFace->m_lRows = lWrite - sizeof(TFace); + + if(lWrite != lSendBuffer(pstSavm->m_skSock, (void *)pstRun->pstVoid, lWrite)) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + pstSavm->m_lErrno = ((TFace *)pstRun->pstVoid)->m_lErrno; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + + pstSavm->m_lEffect = ((TFace *)pstRun->pstVoid)->m_lRows; + return RC_SUCC; +} + +/************************************************************************************************* + description:API - truncate + parameters: + pstSavm --stvm handle + t --t + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmTruncate(SATvm *pstSavm, TABLE t) +{ + RunTime *pstRun; + TFace *pstFace; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + if(!pstRun->pstVoid) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstFace = (TFace *)pstRun->pstVoid; + pstFace->m_table = t; + pstFace->m_lRows = 0; + pstFace->m_lErrno = TVM_DONE_SUCC; + pstFace->m_enum = OPERATE_TRCATE; + + if(sizeof(TFace) != lSendBuffer(pstSavm->m_skSock, (void *)pstFace, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(pstSavm->m_skSock, (void *)pstFace, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + pstSavm->m_lErrno = pstFace->m_lErrno; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + + pstSavm->m_lEffect = pstFace->m_lRows; + return RC_SUCC; +} + +/************************************************************************************************* + description:API - group + parameters: + pstSavm --stvm handle + plOut --number + ppvOut --out data list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmGroup(SATvm *pstSavm, size_t *plOut, void **ppvOut) +{ + RunTime *pstRun; + TFace *pstFace; + FdCond *pstCond; + uint lWrite = sizeof(TFace); + + if(!pstSavm || !ppvOut) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + if(!pstRun->pstVoid) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstFace = (TFace *)pstRun->pstVoid; + pstFace->m_lFind = pstSavm->lFind; + pstFace->m_lDLen = pstSavm->lSize; + pstFace->m_lErrno = TVM_DONE_SUCC; + pstFace->m_enum = OPERATE_GROUP; + pstFace->m_table = pstSavm->tblName; + + checkbuffer(pstSavm, pstRun, 1); + pstCond = &pstSavm->stUpdt; + if(0 == pstCond->uFldcmp) + { + pstSavm->m_lErrno = GROUP_SET_ERR; + return RC_FAIL; + } + + vBuildPacket(pstRun->pstVoid, pstSavm->pstVoid, &pstSavm->stCond, &lWrite); + vAppendCond(pstRun->pstVoid, &pstSavm->stUpdt, &lWrite); + pstFace->m_lRows = lWrite - sizeof(TFace); + if(lWrite != lSendBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, lWrite)) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + pstSavm->m_lErrno = pstFace->m_lErrno; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + + pstRun->m_lRowSize = pstSavm->lSize * pstFace->m_lRows; + if(NULL == (*ppvOut = (void *)malloc(pstRun->m_lRowSize))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + if(pstRun->m_lRowSize != lRecvBuffer(pstSavm->m_skSock, (char *)*ppvOut, pstRun->m_lRowSize)) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + *plOut = pstFace->m_lRows; + pstSavm->m_lEffect = pstFace->m_lRows; + return RC_SUCC; +} + +/************************************************************************************************* + description:API - count + parameters: + pstSavm --stvm handle + plcount --count + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmCount(SATvm *pstSavm, size_t *plCount) +{ + RunTime *pstRun; + TFace *pstFace; + uint lWrite = sizeof(TFace); + + if(!pstSavm || !plCount) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + if(!pstRun->pstVoid) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstFace = (TFace *)pstRun->pstVoid; + pstFace->m_lFind = pstSavm->lFind; + pstFace->m_lDLen = pstSavm->lSize; + pstFace->m_lErrno = TVM_DONE_SUCC; + pstFace->m_enum = OPERATE_COUNT; + pstFace->m_table = pstSavm->tblName; + + checkbuffer(pstSavm, pstRun, 1); + vBuildPacket(pstRun->pstVoid, pstSavm->pstVoid, &pstSavm->stCond, &lWrite); + vAppendCond(pstRun->pstVoid, &pstSavm->stUpdt, &lWrite); + pstFace->m_lRows = lWrite - sizeof(TFace); + + if(lWrite != lSendBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, lWrite)) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + pstSavm->m_lErrno = pstFace->m_lErrno; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + + *plCount = pstFace->m_lRows; + return RC_SUCC; +} + +/************************************************************************************************* + description:API - extreme + parameters: + pstSavm --stvm handle + pvOut --out data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmExtreme(SATvm *pstSavm, void *pvOut) +{ + RunTime *pstRun; + TFace *pstFace; + FdCond *pstCond; + uint lWrite = sizeof(TFace); + + if(!pstSavm || !pvOut) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + if(!pstRun->pstVoid) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstFace = (TFace *)pstRun->pstVoid; + pstFace->m_lFind = pstSavm->lFind; + pstFace->m_lDLen = pstSavm->lSize; + pstFace->m_lErrno = TVM_DONE_SUCC; + pstFace->m_enum = OPERATE_EXTREM; + pstFace->m_table = pstSavm->tblName; + + checkbuffer(pstSavm, pstRun, 1); + pstCond = &pstSavm->stUpdt; + if(0 == pstCond->uFldcmp) + { + pstSavm->m_lErrno = GROUP_SET_ERR; + return RC_FAIL; + } + + vBuildPacket(pstRun->pstVoid, pstSavm->pstVoid, &pstSavm->stCond, &lWrite); + vAppendCond(pstRun->pstVoid, pstCond, &lWrite); + pstFace->m_lRows = lWrite - sizeof(TFace); + + if(lWrite != lSendBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, lWrite)) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + pstSavm->m_lErrno = pstFace->m_lErrno; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + + if(pstSavm->lSize != lRecvBuffer(pstSavm->m_skSock, (char *)pvOut, pstSavm->lSize)) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:API - droptable + parameters: + pstSavm --stvm handle + t --table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmDropTable(SATvm *pstSavm, TABLE t) +{ + RunTime *pstRun; + TFace *pstFace; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + if(!pstRun->pstVoid) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstFace = (TFace *)pstRun->pstVoid; + pstFace->m_lRows = 0; + pstFace->m_table = t; + pstFace->m_lErrno = TVM_DONE_SUCC; + pstFace->m_enum = OPERATE_TBDROP; + + if(sizeof(TFace) != lSendBuffer(pstSavm->m_skSock, (void *)pstRun->pstVoid, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + pstSavm->m_lErrno = pstFace->m_lErrno; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + + pstSavm->m_lEffect = pstFace->m_lRows; + return RC_SUCC; +} + +/************************************************************************************************* + description:API - renametable + parameters: + pstSavm --stvm handle + to --from + tn --to table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmRenameTable(SATvm *pstSavm, TABLE to, TABLE tn) +{ + RunTime *pstRun; + TFace *pstFace; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + if(!pstRun->pstVoid) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstFace = (TFace *)pstRun->pstVoid; + pstFace->m_lRows = 0; + pstFace->m_table = to; + pstFace->m_lDLen = tn; + pstFace->m_lErrno = TVM_DONE_SUCC; + pstFace->m_enum = OPERATE_RENAME; + + if(sizeof(TFace) != lSendBuffer(pstSavm->m_skSock, (void *)pstRun->pstVoid, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + pstSavm->m_lErrno = ((TFace *)pstRun->pstVoid)->m_lErrno; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + + pstSavm->m_lEffect = ((TFace *)pstRun->pstVoid)->m_lRows; + return RC_SUCC; +} + +/************************************************************************************************* + description:API - selectseque + parameters: + pstSavm --stvm handle + pszSQName --seque name + pulNumber --oout seque + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmSelectSeque(SATvm *pstSavm, char *pszSQName, ulong *pulNumber) +{ + RunTime *pstRun; + TFace *pstFace; + uint lWrite = sizeof(TFace) + MAX_INDEX_LEN; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + if(!pstRun->pstVoid) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstFace = (TFace *)pstRun->pstVoid; + pstFace->m_table = SYS_TVM_SEQUE; + pstFace->m_lDLen = MAX_INDEX_LEN; + pstFace->m_lErrno = TVM_DONE_SUCC; + pstFace->m_enum = OPERATE_SELSEQ; + pstFace->m_lRows = MAX_INDEX_LEN; + + strncpy(pstRun->pstVoid + sizeof(TFace), pszSQName, MAX_INDEX_LEN); + if(lWrite != lSendBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, lWrite)) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + pstSavm->m_lErrno = pstFace->m_lErrno; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + + if(sizeof(ulong) != lRecvBuffer(pstSavm->m_skSock, (void *)pstRun->pstVoid, sizeof(ulong))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + memcpy((void *)pulNumber, pstRun->pstVoid, sizeof(ulong)); + return RC_SUCC; +} + +/************************************************************************************************* + description:API - setsequence + parameters: + pstSavm --stvm handle + pszSQName --seque name + uStart --out seque + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmSetSequence(SATvm *pstSavm, char *pszSQName, ulong uStart) +{ + RunTime *pstRun; + TFace *pstFace; + uint lWrite = sizeof(TFace) + MAX_INDEX_LEN; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + if(!pstRun->pstVoid) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstFace = (TFace *)pstRun->pstVoid; + pstFace->m_table = SYS_TVM_SEQUE; + pstFace->m_lDLen = MAX_INDEX_LEN; + pstFace->m_lErrno = TVM_DONE_SUCC; + pstFace->m_enum = OPERATE_SETSEQ; + + strncpy(pstRun->pstVoid + sizeof(TFace), pszSQName, MAX_INDEX_LEN); + *((ulong *)(pstRun->pstVoid + lWrite)) = uStart; + lWrite += sizeof(ulong); + pstFace->m_lRows = lWrite - sizeof(TFace); + if(lWrite != lSendBuffer(pstSavm->m_skSock, (void *)pstRun->pstVoid, lWrite)) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + pstSavm->m_lErrno = ((TFace *)pstRun->pstVoid)->m_lErrno; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + + return RC_SUCC; +} + +/************************************************************************************************* + description:API - rebuildindex + parameters: + pstSavm --stvm handle + t --table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmRebuildIndex(SATvm *pstSavm, TABLE t) +{ + RunTime *pstRun; + TFace *pstFace; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + if(!pstRun->pstVoid) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstFace = (TFace *)pstRun->pstVoid; + pstFace->m_lRows = 0; + pstFace->m_table = t; + pstFace->m_lErrno = TVM_DONE_SUCC; + pstFace->m_enum = OPERATE_RBDIDX; + + if(sizeof(TFace) != lSendBuffer(pstSavm->m_skSock, (void *)pstRun->pstVoid, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(pstSavm->m_skSock, (char *)pstRun->pstVoid, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + pstSavm->m_lErrno = ((TFace *)pstRun->pstVoid)->m_lErrno; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + + return RC_SUCC; +} + +/************************************************************************************************* + description:API - Relock + parameters: + pstSavm --stvm handle + t --table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmResetLock(SATvm *pstSavm, TABLE t) +{ + RunTime *pstRun; + TFace *pstFace; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + if(!pstRun->pstVoid) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstFace = (TFace *)pstRun->pstVoid; + pstFace->m_lRows = 0; + pstFace->m_table = t; + pstFace->m_lErrno = TVM_DONE_SUCC; + pstFace->m_enum = OPERATE_RETLOK; + + if(sizeof(TFace) != lSendBuffer(pstSavm->m_skSock, (void *)pstFace, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(pstSavm->m_skSock, (char *)pstFace, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + pstSavm->m_lErrno = ((TFace *)pstRun->pstVoid)->m_lErrno; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + + return RC_SUCC; +} + +/************************************************************************************************* + description:API - work + parameters: + pstSavm --stvm handle + eWork --ework + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lTvmWork(SATvm *pstSavm, Benum eWork) +{ + RunTime *pstRun; + TFace *pstFace; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, 0); + if(!pstRun->pstVoid) + { + pstSavm->m_lErrno = DOM_NOT_INITL; + return RC_FAIL; + } + + pstFace = (TFace *)pstRun->pstVoid; + pstFace->m_lRows = 0; + pstFace->m_enum = eWork; + pstFace->m_table = SYS_TVM_INDEX; + pstFace->m_lErrno = TVM_DONE_SUCC; +//#ifdef __linux__ + pstFace->m_lDLen = syscall(SYS_gettid); +//#endif + + if(sizeof(TFace) != lSendBuffer(pstSavm->m_skSock, (void *)pstFace, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + if(sizeof(TFace) != lRecvBuffer(pstSavm->m_skSock, (char *)pstFace, sizeof(TFace))) + { + pstSavm->m_lErrno = SOCK_COM_EXCP; + return RC_FAIL; + } + + pstSavm->m_lErrno = pstFace->m_lErrno; + pstSavm->m_lEffect = pstFace->m_lRows; + if(0 != pstSavm->m_lErrno) + return RC_FAIL; + + return RC_SUCC; +} + +/************************************************************************************************* + description:API - begin work + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmBeginWork(SATvm *pstSavm) +{ + return _lTvmWork(pstSavm, OPERATE_BEGWORK); +} + +/************************************************************************************************* + description:API - rollback work + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmRollbackWork(SATvm *pstSavm) +{ + return _lTvmWork(pstSavm, OPERATE_ROLWORK); +} + +/************************************************************************************************* + description:API - commit work + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmCommitWork(SATvm *pstSavm) +{ + return _lTvmWork(pstSavm, OPERATE_CMTWORK); +} + +/************************************************************************************************* + description:API - end work + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmEndWork(SATvm *pstSavm) +{ + return _lTvmWork(pstSavm, OPERATE_ENDWORK); +} + +/************************************************************************************************* + description:API - exit + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmExit(SATvm *pstSavm) +{ + return _lTvmWork(pstSavm, OPERATE_EXEEXIT); +} + +/************************************************************************************************* + description:Gets the remote table index, user STVM-SQL + parameters: + pstSavm --stvm handle + pszTable --table name + pszPart --part + pstIndex --table index + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmGetTblIndex(SATvm *pstSavm, char *pszTable, char *pszPart, TIndex *pstIndex) +{ + TIndex stIndex; + + if(!pszTable || !pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstSavm->bSearch = TYPE_SYSTEM; + conditinit(pstSavm, stIndex, SYS_TVM_INDEX); + stringset(pstSavm, stIndex, m_szPart, pszPart); + stringset(pstSavm, stIndex, m_szTable, pszTable); + numberset(pstSavm, stIndex, m_lLocal, RES_LOCAL_SID); + if(RC_SUCC != lTvmSelect(pstSavm, (void *)pstIndex)) + { + if(NO_DATA_FOUND == pstSavm->m_lErrno) + pstSavm->m_lErrno = TBL_NOT_FOUND; + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Gets the remote table field, user STVM-SQL + parameters: + pstSavm --stvm handle + t --t + plOut --number + ppstField --table field + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTvmGetTblField(SATvm *pstSavm, TABLE t, size_t *plOut, TField **ppstField) +{ + TField stField; + + conditinit(pstSavm, stField, SYS_TVM_FIELD) + numberset(pstSavm, stField, m_table, t); + + return lTvmQuery(pstSavm, plOut, (void **)ppstField); +} + +/************************************************************************************************* + * code end + *************************************************************************************************/ diff --git a/src/tree.c b/src/tree.c new file mode 100644 index 0000000..3060907 --- /dev/null +++ b/src/tree.c @@ -0,0 +1,9511 @@ +/* +* Copyright (c) 2018 Savens Liu +* +* The original has been patented, Open source is not equal to open rights. +* Anyone can clone, download, learn and discuss for free. Without the permission +* of the copyright owner or author, it shall not be merged, published, licensed or sold. +* The copyright owner or author has the right to pursue his responsibility. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "tvm.h" +#include "tmain.h" + +/************************************************************************************************* + globle + *************************************************************************************************/ +SATvm g_stSavm = {0}; +TblDef g_stTblDef[TVM_MAX_TABLE] = {0}; + +extern long _lInsertByRt(SATvm *pstSavm); +extern long _lGroupByRt(SATvm *pstSavm, size_t *plOut, void **ppvOut); +extern long _lSelectByRt(SATvm *pstSavm, void *psvOut); +extern long _lCountByRt(SATvm *pstSavm, size_t *plCount); +extern long _lDeleteByRt(SATvm *pstSavm); +extern long _lUpdateByRt(SATvm *pstSavm, void *pvUpdate); +extern long _lTruncateByRt(SATvm *pstSavm, TABLE t); +extern long _lQueryByRt(SATvm *pstSavm, size_t *plOut, void **ppsvOut); +extern long _lExtremeByRt(SATvm *pstSavm, void *psvOut); +extern void _vDropTableByRt(SATvm *pstSavm, TABLE t); +extern long _lRenameTableByRt(SATvm *pstSavm, TABLE to, TABLE tn); +/************************************************************************************************* + macro + *************************************************************************************************/ +#define Tremohold(p,r) if(p->m_bHold) r->m_lState = RESOURCE_ABLE; + +/************************************************************************************************* + Error message definition + *************************************************************************************************/ +static char tvmerr[100][MAX_INDEX_LEN] = { + "completed successfully", + "sever exception", + "index field values is null", + "condition is null", + "no space for insert data", + "generate shm key failure", + "Invalid parameter or shm has disappeared", + "shared memory already exists", + "shared memory has been deleted", + "Permission denied .shm", + "Insufficient core memory .shm", + "data truck version mismatch", + "size is error to creat data block", + "unique index definition overflow", + "unique index length overflow", + "normal index definition overflow", + "normal index length overflow", + "index type not define", + "field define overflow", + "index data mismatch", + "field type not define", + "memory has not been initialized", + "unique index repeat", + "no space for create index", + "no data be found", + "more then one records be selected", + "malloc memory error", + "cursor invalid", + "table not define", + "file not exist", + "semget condition is null", + "Invalid parameter or sem has disappeared", + "semaphore already exists", + "semaphore has been deleted", + "Permission denied .sem", + "Insufficient core memory .sem", + "Semaphore value out of limit", + "SQL syntax is error", + "SQL syntax not be supported", + "SQL no table name be inputted", + "SQL field is not selected", + "SQL conditional syntax error", + "SQL field syntax error", + "SQL where syntax error", + "table not found", + "SQL fields does not match the value", + "set the read lock failure", + "unlock read lock failure", + "set the write lock failure", + "unlock write lock failure", + "socket connect failure", + "socket connect timeout", + "create socket failure", + "socket recv failure", + "socket send failure", + "socket bind failure", + "socket listen failure", + "socket send timeout", + "socket read timeout", + "socket reset by peer", + "socket communication anomaly", + "epoll add fd error", + "create epoll fd failure", + "delete epoll fd failure", + "socket accept failure", + "SQL remote does not support", + "file not found", + "boot parameters error", + "parameters table related error", + "Incompatible version", + "domain not register", + "domain work does not support", + "sequence does not exist", + "file is not set", + "record data too long", + "Resource unavailable", + "message queue already exists", + "Permission denied .msg", + "Insufficient(msg) core memory", + "Invalid parameter or msg has disappeared", + "message Invalid address", + "message queue has been deleted", + "message text length is greater than msgsz", + "Interrupted by signal", + "msgsnd queue overrun", + "initial child process failed", + "field not exist", + "table already exist", + "The transaction has not been opened yet", + "The transaction has not been register", + "domain not initail", + "table field not define", + "set field value error", + "update field not set", + "extreme set decorate error", + "group set decorate error", + "", +}; + +/************************************************************************************************* + description:error message customization + parameters: + return: + *************************************************************************************************/ +void vRedeError(long err, char *s) +{ + if(100 <= err || !s) + return ; + strncpy(tvmerr[err], s, MAX_INDEX_LEN - 1); +} + +/************************************************************************************************* + description:output hexadecimal + parameters: + return: + *************************************************************************************************/ +void vPrintHex(char *s, long lIdx, bool bf) +{ + int i = 0; + FILE *fp = NULL; + + if(!bf) + { + for(i = 0; i < lIdx; i ++) + { + if((ushar)s[i] > 0x80 && (ushar)s[i + 1] >= 0x40) + { + fprintf(stdout, "\033[0;35m%c%c\033[0m", s[i], s[i + 1]); + ++ i; + continue; + } + + if(s[i] > 40 && s[i] < 126) + fprintf(stdout, "\033[0;35m%C\033[0m", s[i]); + else + fprintf(stdout, "/x%0X ", (ushar)s[i]); + } + } + else + { + fp = fopen("log.txt", "a"); + fwrite(s, 1, lIdx, fp); + fclose(fp); + } + + fprintf(stdout, "\n"); + fflush(stdout); +} + +/************************************************************************************************* + description:System table creation + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +CREATE lCreateTvmIndex() +{ + DEFINE(SYS_TVM_INDEX, "SYS_TVM_INDEX", "", TIndex) + FIELD(TIndex, m_table, "m_table", FIELD_LONG) + FIELD(TIndex, m_lType, "m_lType", FIELD_LONG) + FIELD(TIndex, m_szTable, "m_szTable", FIELD_CHAR) + FIELD(TIndex, m_szPart, "m_szPart", FIELD_CHAR) + FIELD(TIndex, m_szOwner, "m_szOwner", FIELD_CHAR) + FIELD(TIndex, m_yKey, "m_yKey", FIELD_LONG) + FIELD(TIndex, m_shmID, "m_shmID", FIELD_LONG) + FIELD(TIndex, m_semID, "m_semID", FIELD_LONG) + FIELD(TIndex, m_lPid, "m_lPid", FIELD_LONG) + FIELD(TIndex, m_lValid, "m_lValid", FIELD_LONG) + FIELD(TIndex, m_lMaxRows, "m_lMaxRows", FIELD_LONG) + FIELD(TIndex, m_lRowSize, "m_lRowSize", FIELD_LONG) + FIELD(TIndex, m_lLocal, "m_lLocal", FIELD_LONG) + FIELD(TIndex, m_lState, "m_lState", FIELD_LONG) + FIELD(TIndex, m_lPers, "m_lPers", FIELD_LONG) + FIELR(TIndex, m_szTime, "m_szTime", FIELD_LONG) + + CREATE_IDX(NORMAL) + IDX_FIELD(TIndex, m_szTable, FIELD_CHAR); + IDX_FIELD(TIndex, m_szPart, FIELD_CHAR); + + CREATE_IDX(UNQIUE) + IDX_FIELD(TIndex, m_table, FIELD_LONG); + FINISH +} + +/************************************************************************************************* + description:field table creation + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +CREATE lCreateTvmField() +{ + DEFINE(SYS_TVM_FIELD, "SYS_TVM_FIELD", "", TField) + FIELD(TField, m_table, "m_table", FIELD_LONG) + FIELD(TField, m_szOwner, "m_szOwner", FIELD_CHAR) + FIELD(TField, m_szTable, "m_szTable", FIELD_CHAR) + FIELD(TField, m_szField, "m_szField", FIELD_CHAR) + FIELD(TField, m_lSeq, "m_lSeq", FIELD_LONG) + FIELD(TField, m_lAttr, "m_lAttr", FIELD_LONG) + FIELD(TField, m_lFrom, "m_lFrom", FIELD_LONG) + FIELD(TField, m_lLen, "m_lLen", FIELD_LONG) + FIELD(TField, m_lIsPk, "m_lIsPk", FIELD_LONG) + + CREATE_IDX(NORMAL) + IDX_FIELD(TField, m_table, FIELD_LONG); + + CREATE_IDX(UNQIUE) + IDX_FIELD(TField, m_table, FIELD_LONG); + IDX_FIELD(TField, m_lSeq, FIELD_LONG); + FINISH +} + +/************************************************************************************************* + description:domain table creation + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +CREATE lCreateTvmDomain() +{ + DEFINE(SYS_TVM_DOMAIN, "SYS_TVM_DOMAIN", "", TDomain) + FIELD(TDomain, m_skSock, "m_skSock", FIELD_LONG) + FIELD(TDomain, m_table, "m_table", FIELD_LONG) + FIELD(TDomain, m_mtable, "m_mtable", FIELD_LONG) + FIELD(TDomain, m_lLock, "m_lLock", FIELD_LONG) + FIELD(TDomain, m_lGroup, "m_lGroup", FIELD_LONG) + FIELD(TDomain, m_lKeepLive, "m_lKeepLive", FIELD_LONG) + FIELD(TDomain, m_lLastTime, "m_lLastTime", FIELD_LONG) + FIELD(TDomain, m_lTimeOut, "m_lTimeOut", FIELD_LONG) + FIELD(TDomain, m_lTryMax, "m_lTryMax", FIELD_LONG) + FIELD(TDomain, m_lTryTimes, "m_lTryTimes", FIELD_LONG) + FIELD(TDomain, m_lRowSize, "m_lRowSize", FIELD_LONG) + FIELD(TDomain, m_lStatus, "m_lStatus", FIELD_LONG) + FIELD(TDomain, m_lPers, "m_lPers", FIELD_LONG) + FIELD(TDomain, m_lPort, "m_lPort", FIELD_LONG) + FIELD(TDomain, m_szIp, "m_szIp", FIELD_CHAR) + FIELD(TDomain, m_szTable, "m_szTable", FIELD_CHAR) + FIELD(TDomain, m_szPart, "m_szPart", FIELD_CHAR) + FIELD(TDomain, m_szOwner, "m_szOwner", FIELD_CHAR) + + CREATE_IDX(NORMAL) + IDX_FIELD(TDomain, m_szTable, FIELD_CHAR) + IDX_FIELD(TDomain, m_szPart, FIELD_CHAR) + + CREATE_IDX(UNQIUE) + IDX_FIELD(TDomain, m_mtable, FIELD_LONG) + IDX_FIELD(TDomain, m_lPort, FIELD_LONG) + IDX_FIELD(TDomain, m_szIp, FIELD_CHAR) + + FINISH +} + +/************************************************************************************************* + description:seque table creation + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +CREATE lCreateTvmSeque() +{ + DEFINE(SYS_TVM_SEQUE, "SYS_TVM_SEQUE", "", TSeque) + FIELD(TSeque, m_szSQName, "m_szSQName", FIELD_CHAR) + FIELD(TSeque, m_uIncrement, "m_uIncrement", FIELD_LONG) + + CREATE_IDX(UNQIUE) + IDX_FIELD(TSeque, m_szSQName, FIELD_CHAR) + + FINISH +} + +/************************************************************************************************* + description:timestamp string + parameters: + return: + char* + *************************************************************************************************/ +char* sGetUpdTime() +{ + time_t current; + struct tm *tm = NULL; + static char szTime[20]; + + tzset(); + time(¤t); + tm = localtime(¤t); + + memset(szTime, 0, sizeof(szTime)); + snprintf(szTime, sizeof(szTime), "%4d/%02d/%02d %02d:%02d:%02d", tm->tm_year + 1900, + tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); + + return szTime; +} + +/************************************************************************************************* + description:Conditional field setting + parameters: + return: + *************************************************************************************************/ +void vSetCodField(FdCond *pstCond, uint ulen, uint uPos) +{ + register int i = 0; + + for(i; i < pstCond->uFldcmp; i ++) + { + if(pstCond->stFdKey[i].uFldpos == uPos) + return ; + } + + pstCond->stFdKey[pstCond->uFldcmp].uFldlen = ulen; + pstCond->stFdKey[pstCond->uFldcmp].uFldpos = uPos; + pstCond->uFldcmp ++; + return ; +} + +/************************************************************************************************* + description:decorate field setting + parameters: + return: + *************************************************************************************************/ +void vSetDecorate(FdCond *pstCond, uint ulen, uint uPos, Uenum em) +{ + register int i = 0; + + for(i; i < pstCond->uFldcmp; i ++) + { + if(pstCond->stFdKey[i].uFldpos == uPos) + return ; + } + + pstCond->stFdKey[pstCond->uFldcmp].uFldlen = ulen; + pstCond->stFdKey[pstCond->uFldcmp].uFldpos = uPos; + pstCond->stFdKey[pstCond->uFldcmp].uDecorate = em; + pstCond->uFldcmp ++; + + return ; +} + +/************************************************************************************************* + description:pick index from data + parameters: + return: + char* + *************************************************************************************************/ +char* pPickIndex(long lIdx, TblKey *pstKey, void *psvData, char *pszIdx) +{ + register int i, j, m = 0; + static char szZore[MAX_INDEX_LEN] = {0}; + + if(!psvData) return NULL; + + for(i = 0, j = 0; i < lIdx; i ++) + { + if(FIELD_CHAR != pstKey[i].m_lAttr) + m ++; + memcpy(pszIdx + j, psvData + pstKey[i].m_lFrom, pstKey[i].m_lLen); + j += pstKey[i].m_lLen; + } + + if(0 != m) return pszIdx; + + if(!memcmp(pszIdx, szZore, j)) + return NULL; + + return pszIdx; +} + +/************************************************************************************************* + description:get index from data + parameters: + return: + char* + *************************************************************************************************/ +char* pGetIndex(FdCond *pstCond, long lIdx, TblKey *pstKey, void *psvData, char *pszIdx) +{ + register int i, j, m; + + if(!psvData || 0 == pstCond->uFldcmp) + return NULL; + + for(i = 0, m = 0; i < lIdx; i ++) + { + for(j = 0; j < pstCond->uFldcmp; j ++) + { + if(pstKey[i].m_lFrom == pstCond->stFdKey[j].uFldpos) + { + memcpy(pszIdx + m, psvData + pstKey[i].m_lFrom, pstKey[i].m_lLen); + m += pstKey[i].m_lLen; + break; + } + } + + if(j == pstCond->uFldcmp) + return NULL; + } + + return pszIdx; +} + +/************************************************************************************************* + description:get stvm handle + parameters: + return: + void* + *************************************************************************************************/ +void* pGetSATvm() +{ + return &g_stSavm; +} + +/************************************************************************************************* + description:initial stvm handle + parameters: + return: + *************************************************************************************************/ +void vInitSATvm(SATvm *pstSavm) +{ + memset(pstSavm, 0, sizeof(SATvm)); +} + +/************************************************************************************************* + description:User custom error message + parameters: + return: + *************************************************************************************************/ +void vSetTvmMsg(SATvm *pstSamo, char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsnprintf(pstSamo->m_szMsg, sizeof(pstSamo->m_szMsg), fmt, ap); + va_end(ap); +} + +/************************************************************************************************* + description:get custom error message + parameters: + return: + char* + *************************************************************************************************/ +char* sGetTvmMsg(SATvm *pstSamo) +{ + return pstSamo->m_szMsg; +} + +/************************************************************************************************* + description:Gets the operation error code + parameters: + return: + long --errno code + *************************************************************************************************/ +long lGetTErrno() +{ + return g_stSavm.m_lErrno; +} + +/************************************************************************************************* + description:set operation error code index from data + parameters: + error --errno + return: + *************************************************************************************************/ +void vSetTErrno(long err) +{ + g_stSavm.m_lErrno = err; +} + +/************************************************************************************************* + description:Gets the operation error message + parameters: + error --errno + return: + char* + *************************************************************************************************/ +char* sGetTError(long err) +{ + return tvmerr[(uint)err]; +} + +/************************************************************************************************* + description:Operation STVM affects the number of records. + parameters: + return: + size_t + *************************************************************************************************/ +size_t lGetEffect() +{ + return g_stSavm.m_lEffect; +} + +/************************************************************************************************* + description:Get the table run handle + parameters: + return: + RunTime* + *************************************************************************************************/ +RunTime* pGetRunTime(SATvm *pstSavm, TABLE t) +{ + return &pstSavm->stRunTime[t]; +} + +/************************************************************************************************* + description:get table starting address + parameters: + return: + void* + *************************************************************************************************/ +void* pGetAddr(SATvm *pstSavm, TABLE t) +{ + return ((RunTime *)pGetRunTime(pstSavm, t))->m_pvAddr; +} + +/************************************************************************************************* + description:Gets the table structure information + parameters: + t --table + return: + TblDef* + *************************************************************************************************/ +TblDef* pGetTblDef(TABLE t) +{ + return &g_stTblDef[t]; +} + +/************************************************************************************************* + description:Gets the table structure information + parameters: + pvAddr --address + return: + RWLock* + *************************************************************************************************/ +RWLock* pGetRWLock(char* pvAddr) +{ + return &((TblDef *)pvAddr)->m_rwlock; +} + +/************************************************************************************************* + description:initial the table structure information + parameters: + pvAddr --address + return: + RWLock* + *************************************************************************************************/ +void vInitTblDef(TABLE t) +{ + memset(&g_stTblDef[t], 0, sizeof(TblDef)); +} + +/************************************************************************************************* + description:Get the number of query index groups + parameters: + t --table + return: + long + *************************************************************************************************/ +long lGetTblGroup(TABLE t) +{ + return g_stTblDef[t].m_lGroup; +} + +/************************************************************************************************* + description:Get the maximum number of table support records + parameters: + t --table + return: + size_t + *************************************************************************************************/ +size_t lGetTblRow(TABLE t) +{ + return g_stTblDef[t].m_lMaxRow; +} + +/************************************************************************************************* + description:Get the current record number of valid records + parameters: + t --table + return: + size_t + *************************************************************************************************/ +size_t lGetTblValid(TABLE t) +{ + return g_stTblDef[t].m_lValid; +} + +/************************************************************************************************* + description:Get the table's unique index length + parameters: + t --table + return: + long + *************************************************************************************************/ +long lGetIdxLen(TABLE t) +{ + return g_stTblDef[t].m_lIdxLen; +} + +/************************************************************************************************* + description:Get the location of the table index + parameters: + t --table + return: + size_t + *************************************************************************************************/ +size_t lGetIdxPos(TABLE t) +{ + return g_stTblDef[t].m_lTreePos; +} + +/************************************************************************************************* + description:Gets the unique index of the table Root position + parameters: + t --table + return: + size_t + *************************************************************************************************/ +size_t lGetIdxRoot(TABLE t) +{ + return g_stTblDef[t].m_lTreeRoot; +} + +/************************************************************************************************* + description:Get NIL position of the table + parameters: + t --table + return: + size_t + *************************************************************************************************/ +size_t lGetNodeNil(TABLE t) +{ + return g_stTblDef[t].m_lNodeNil; +} + +/************************************************************************************************* + description:Get the index of the table query group length + parameters: + t --table + return: + long + *************************************************************************************************/ +long lGetGrpLen(TABLE t) +{ + return g_stTblDef[t].m_lGrpLen; +} + +/************************************************************************************************* + description:Get the location of the index group for the table + parameters: + t --table + return: + size_t + *************************************************************************************************/ +size_t lGetGrpPos(TABLE t) +{ + return g_stTblDef[t].m_lGroupPos; +} + +/************************************************************************************************* + description:Get the root position of the table + parameters: + t --table + return: + size_t + *************************************************************************************************/ +size_t lGetGrpRoot(TABLE t) +{ + return g_stTblDef[t].m_lGroupRoot; +} + +/************************************************************************************************* + description:Gets the offset of the index list + parameters: + t --table + return: + size_t + *************************************************************************************************/ +size_t lGetListOfs(TABLE t) +{ + return g_stTblDef[t].m_lListOfs; +} + +/************************************************************************************************* + description:Gets the position of the index list + parameters: + t --table + return: + size_t + *************************************************************************************************/ +size_t lGetListPos(TABLE t) +{ + return g_stTblDef[t].m_lListPos; +} + +/************************************************************************************************* + description:Get table data area location + parameters: + t --table + return: + size_t + *************************************************************************************************/ +size_t lGetTblData(TABLE t) +{ + return g_stTblDef[t].m_lData; +} + +/************************************************************************************************* + description:Get the number of unique index combinations + parameters: + t --table + return: + uint + *************************************************************************************************/ +uint lGetIdxNum(TABLE t) +{ + return g_stTblDef[t].m_lIdxUp; +} + +/************************************************************************************************* + description:Get unique index field list + parameters: + t --table + return: + TblKey + size_t + *************************************************************************************************/ +TblKey* pGetTblIdx(TABLE t) +{ + return g_stTblDef[t].m_stIdxUp; +} + +/************************************************************************************************* + description:Get the number of index combinations + parameters: + t --table + return: + uint + *************************************************************************************************/ +uint lGetGrpNum(TABLE t) +{ + return g_stTblDef[t].m_lGrpUp; +} + +/************************************************************************************************* + description:Get index field list + parameters: + t --table + return: + TblKey + *************************************************************************************************/ +TblKey* pGetTblGrp(TABLE t) +{ + return g_stTblDef[t].m_stGrpUp; +} + +/************************************************************************************************* + description:Get the entire table size + parameters: + t --table + return: + size_t + *************************************************************************************************/ +size_t lGetTableSize(TABLE t) +{ + return g_stTblDef[t].m_lTable; +} + +/************************************************************************************************* + description:Get a table to define a single record size + parameters: + t --table + return: + long + *************************************************************************************************/ +long lGetRowSize(TABLE t) +{ + return g_stTblDef[t].m_lReSize; +} + +/************************************************************************************************* + description:Get Table Defines a single data block size + parameters: + t --table + return: + size_t + *************************************************************************************************/ +size_t lGetRowTruck(TABLE t) +{ + return g_stTblDef[t].m_lTruck; +} + +/************************************************************************************************* + description:Get the number of table fields + parameters: + t --table + return: + long + *************************************************************************************************/ +long lGetFldNum(TABLE t) +{ + return g_stTblDef[t].m_lIdxNum; +} + +/************************************************************************************************* + description:Get the table fields + parameters: + t --table + return: + TblKey + *************************************************************************************************/ +TblKey* pGetTblKey(TABLE t) +{ + return g_stTblDef[t].m_stKey; +} + +/************************************************************************************************* + description:Get the field by offset + parameters: + t --table + return: + TblKey + *************************************************************************************************/ +TblKey* pGetFldKey(TABLE t, uint uFrom, uint uLen) +{ + long i = 0; + TblKey *pstKey = (TblKey *)pGetTblKey(t); + + for(i = 0; i < lGetFldNum(t); i ++) + { + if(pstKey[i].m_lFrom == uFrom && pstKey[i].m_lLen == uLen) + return &pstKey[i]; + } + + return NULL; +} + +/************************************************************************************************* + description:initial field condition + parameters: + t --table + return: + *************************************************************************************************/ +void vCondInsInit(FdCond *pstCond, TABLE t) +{ + long i = 0; + TblKey *pstKey = (TblKey *)pGetTblKey(t); + + for(pstCond->uFldcmp = lGetFldNum(t); i < pstCond->uFldcmp; i ++) + { + pstCond->stFdKey[i].uFldpos = pstKey[i].m_lFrom; + pstCond->stFdKey[i].uFldlen = pstKey[i].m_lLen; + } + + return ; +} + +/************************************************************************************************* + description:Set the field properties + parameters: + pstCond --condion field + t --table + return: + true + *************************************************************************************************/ +bool bSetCondAttr(FdCond *pstCond, TABLE t, Uenum eCheck) +{ + FdKey *pstFd; + register int i, j; + bool bCheck = false; + TblKey *pstKey = (TblKey *)pGetTblKey(t); + + for(j = 0; j < pstCond->uFldcmp; j ++) + { + pstFd = &pstCond->stFdKey[j]; + for(i = 0; i < lGetFldNum(t); i ++) + { + if(pstKey[i].m_lFrom == pstFd->uFldpos) + { + pstFd->uDecorate |= pstKey[i].m_lAttr; + break; + } + } + + if(pstFd->uDecorate & eCheck) + bCheck = true; + } + + return bCheck; +} + +/************************************************************************************************* + description:Check to see if it is an index field. + parameters: + t --table + pstRrp --field list + return: + true --yes + false --no + *************************************************************************************************/ +bool bIsGroupFld(TABLE t, FdCond *pstRrp) +{ + long i, j; + FdKey *pstFd; + TblKey *pstKey = (TblKey *)pGetTblGrp(t); + + if(pstRrp->uFldcmp != lGetGrpNum(t)) + return false; + + for(i = 0; i < pstRrp->uFldcmp; i ++) + { + pstFd = &pstRrp->stFdKey[i]; + for(j = 0; j < lGetGrpNum(t); j ++) + { + if(pstKey[j].m_lFrom == pstFd->uFldpos) + break; + } + + if(j == lGetGrpNum(t)) + return false; + } + + return true; +} + +/************************************************************************************************* + description:Get table name + parameters: + t --table + return: + char* + *************************************************************************************************/ +char* sGetTableName(TABLE t) +{ + return g_stTblDef[t].m_szTable; +} + +/************************************************************************************************* + description:Gets the table partition + parameters: + t --table + return: + char* + *************************************************************************************************/ +char* sGetTablePart(TABLE t, char *pszNode) +{ + if(0x00 == g_stTblDef[t].m_szPart[0]) + strncpy(g_stTblDef[t].m_szPart, pszNode, MAX_FIELD_LEN); + return g_stTblDef[t].m_szPart; +} + +/************************************************************************************************* + description:Stand-alone mode, let stvm keep links improve efficiency + parameters: + pstSavm --stvm handle + return: + *************************************************************************************************/ +void vHoldConnect(SATvm *pstSavm) +{ + pstSavm->m_bHold = TRUE; +} + +/************************************************************************************************* + description:Stand-alone mode, disconnect STVM + parameters: + pstSavm --stvm handle + return: + *************************************************************************************************/ +void vHoldRelease(SATvm *pstSavm) +{ + TABLE t; + RunTime *pstRun = NULL; + + pstSavm->m_bHold = FALSE; + for(t = 0; t < TVM_MAX_TABLE; t ++) + { + pstRun = (RunTime *)pGetRunTime(pstSavm, t); + if(RES_REMOT_SID == pstRun->m_lLocal) + { + pstRun->m_lState = RESOURCE_INIT; + continue; + } + + pstRun->m_lCurType = 0; + pstRun->m_lCurLine = 0; + pstRun->m_pvCurAddr = NULL; + TFree(pstRun->pstVoid); + + if(pstRun->m_pvAddr) + shmdt(pstRun->m_pvAddr); + pstRun->m_pvAddr = NULL; + pstRun->m_bAttch = FALSE; + } + + return ; +} + +/************************************************************************************************* + description:Release the table resources + parameters: + pstSavm --stvm handle + t --table + bHold + return: + *************************************************************************************************/ +void _vTblRelease(SATvm *pstSavm, TABLE t, bool bHold) +{ + RunTime *pstRun = (RunTime *)pGetRunTime(pstSavm, t); + + TFree(pstRun->pstVoid); + if(bHold) return ; + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + pstRun->m_lState = RESOURCE_INIT; + return ; + } + + pstRun->m_lCurType = 0; + pstRun->m_lCurLine = 0; + pstRun->m_pvCurAddr = NULL; + + if(pstRun->m_pvAddr) + shmdt(pstRun->m_pvAddr); + pstRun->m_pvAddr = NULL; + pstRun->m_bAttch = FALSE; +} + +/************************************************************************************************* + description:Close the table resources + parameters: + pstSavm --stvm handle + t --table + return: + *************************************************************************************************/ +void vTblDisconnect(SATvm *pstSavm, TABLE t) +{ + _vTblRelease(pstSavm, t, pstSavm->m_bHold); +} + +/************************************************************************************************* + description:Forced to close the table resources + parameters: + pstSavm --stvm handle + t --table + return: + *************************************************************************************************/ +void vForceDisconnect(SATvm *pstSavm, TABLE t) +{ + _vTblRelease(pstSavm, t, false); +} + +/************************************************************************************************* + description:API - begin work + parameters: + pstSavm --stvm handle + return: + *************************************************************************************************/ +void vBeginWork(SATvm *pstSavm) +{ + if(!pstSavm) return ; + + pstSavm->m_lErrno = 0; + pstSavm->m_lEffect = 0; + pstSavm->m_bWork = true; +} + +/************************************************************************************************* + description:API - end work + parameters: + pstSavm --stvm handle + return: + *************************************************************************************************/ +void vEndWork(SATvm *pstSavm) +{ + if(!pstSavm) return ; + + pstSavm->m_lErrno = 0; + pstSavm->m_lEffect = 0; + pstSavm->m_bWork = false; + lCommitWork(pstSavm); +} + +/************************************************************************************************* + description:Save abnormal transaction data + parameters: + pstWork --work + return: + *************************************************************************************************/ +void vBackupWork(TWork *pstWork) +{ + FILE *fp = NULL; + char szPath[512]; + + memset(szPath, 0, sizeof(szPath)); + snprintf(szPath, sizeof(szPath), "%s/%s", getenv("TVMDBD"), WORK_ERROR_LOG); + + if(NULL == (fp = fopen(szPath, "ab"))) + return ; + + fwrite(pstWork, FPOS(TWork, m_lOperate) + FLEN(TWork, m_lOperate), 1, fp); + if(OPERATE_UPDATE == pstWork->m_lOperate) + fwrite(pstWork->m_pvNew, pstWork->m_lRowSize, 1, fp); + fwrite(pstWork->m_pvData, pstWork->m_lRowSize, 1, fp); + fclose(fp); +} + +/************************************************************************************************* + description:API - rollback work + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lRollbackWork(SATvm *pstSavm) +{ + TWork *pstWork = NULL; + size_t lRow = 0, lErrno = 0; + CMList *pstNode = NULL, *pstList = NULL; + + pstSavm->m_lEffect = 0; + if(!pstSavm || !pstSavm->m_bWork) + { + pstSavm->m_lErrno = WORK_NOT_OPEN; + return RC_FAIL; + } + + // In order to roll back from the tail to the front + for(pstNode = pGetCMTail(pstSavm->m_pstWork); pstNode; ) + { + if(NULL == (pstWork = (TWork *)pstNode->m_psvData)) + { + pstNode = pstNode->pstLast; + continue; + } + + if(RC_SUCC != lInitSATvm(pstSavm, pstWork->m_table)) + { + lErrno = pstSavm->m_lErrno; + vBackupWork(pstWork); + if(pstNode->pstLast) + pstNode->pstLast->pstNext = pstNode->pstNext; + else + pstSavm->m_pstWork = pstNode->pstNext; + + if(pstNode->pstNext) + pstNode->pstNext->pstLast = pstNode->pstLast; + pstList = pstNode; + pstNode = pstNode->pstLast; + if(pstWork) + { + TFree(pstWork->m_pvNew); + TFree(pstWork->m_pvData); + } + TFree(pstList->m_psvData); + TFree(pstList); + continue; + } + + pstSavm->m_bPrew = true; // Transaction is turned on + pstSavm->lSize = pstWork->m_lRowSize; + if(OPERATE_UPDATE == pstWork->m_lOperate) + { + pstSavm->lFind = FIRST_ROW; + pstSavm->pstVoid = (void *)pstWork->m_pvNew; + memcpy(&pstSavm->stCond, &pstWork->m_stUpdt, sizeof(FdCond)); + memcpy(&pstSavm->stUpdt, &pstWork->m_stCond, sizeof(FdCond)); + if(RC_SUCC != lUpdate(pstSavm, (void *)pstWork->m_pvData)) + { + vBackupWork(pstWork); + lErrno = pstSavm->m_lErrno; + } + else + lRow += pstSavm->m_lEffect; + } + else if(OPERATE_DELETE == pstWork->m_lOperate) + { + pstSavm->lFind = FIRST_ROW; + pstSavm->pstVoid = (void *)pstWork->m_pvData; + memcpy(&pstSavm->stCond, &pstWork->m_stCond, sizeof(FdCond)); + if(RC_SUCC != lInsert(pstSavm)) + { + vBackupWork(pstWork); + lErrno = pstSavm->m_lErrno; + } + else + lRow += pstSavm->m_lEffect; + } + else if(OPERATE_INSERT == pstWork->m_lOperate) + { + pstSavm->pstVoid = (void *)pstWork->m_pvData; + memcpy(&pstSavm->stCond, &pstWork->m_stCond, sizeof(FdCond)); + if(RC_SUCC != lDelete(pstSavm)) + { + vBackupWork(pstWork); + lErrno = pstSavm->m_lErrno; + } + else + lRow += pstSavm->m_lEffect; + } + + // delete this node + if(pstNode->pstLast) + pstNode->pstLast->pstNext = pstNode->pstNext; + else + pstSavm->m_pstWork = pstNode->pstNext; + + if(pstNode->pstNext) + pstNode->pstNext->pstLast = pstNode->pstLast; + pstList = pstNode; + pstNode = pstNode->pstLast; + if(pstWork) + { + TFree(pstWork->m_pvNew); + TFree(pstWork->m_pvData); + pstSavm->pstVoid = NULL; + } + TFree(pstList->m_psvData); + TFree(pstList); + } + + pstSavm->lFind = 0; + pstSavm->m_lEffect = lRow; +// pstSavm->m_pstWork = NULL; + pstSavm->m_bPrew = false; // Transaction is turned off + pstSavm->m_lErrno = lErrno; + + return RC_SUCC; +} + +/************************************************************************************************* + description:API - commit work + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lCommitWork(SATvm *pstSavm) +{ + TWork *pstWork = NULL; + CMList *pstNode = NULL, *pstList = NULL; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + for(pstNode = pstSavm->m_pstWork; pstNode; ) + { + if(NULL == (pstWork = (TWork *)pstNode->m_psvData)) + { + pstNode = pstNode->pstNext; + continue; + } + + if(pstNode->pstLast) + pstNode->pstLast->pstNext = pstNode->pstNext; + else + pstSavm->m_pstWork = pstNode->pstNext; + + if(pstNode->pstNext) + pstNode->pstNext->pstLast = pstNode->pstLast; + pstList = pstNode; + pstNode = pstNode->pstNext; + if(pstWork) + { + TFree(pstWork->m_pvNew); + TFree(pstWork->m_pvData); + } + TFree(pstList->m_psvData); + TFree(pstList); + } +// pstSavm->m_bPrew = false; + + return RC_SUCC; +} + +/************************************************************************************************* + description:Record the transaction + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lRecordWork(SATvm *pstSavm, void *pvoData, long lOperate) +{ + TWork stWork; + + // where transaction is on, do not record the transaction itself + if(!pstSavm->m_bWork || pstSavm->m_bPrew) + return RC_SUCC; + + memset(&stWork, 0, sizeof(TWork)); + stWork.m_lOperate = lOperate; + stWork.m_lRowSize = pstSavm->lSize; + stWork.m_table = pstSavm->tblName; + if(NULL == (stWork.m_pvData = (void *)malloc(pstSavm->lSize))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + if(OPERATE_UPDATE == lOperate) + { + if(NULL == (stWork.m_pvNew = (void *)malloc(pstSavm->lSize))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + memcpy(stWork.m_pvNew, pstSavm->pstVoid, pstSavm->lSize); + vCondInsInit(&stWork.m_stUpdt, pstSavm->tblName); + + memcpy(stWork.m_pvData, pvoData, pstSavm->lSize); + memcpy(&stWork.m_stCond, &pstSavm->stUpdt, sizeof(FdCond)); + } + else if(OPERATE_INSERT == lOperate) + { + memcpy(stWork.m_pvData, pvoData, pstSavm->lSize); + vCondInsInit(&stWork.m_stCond, pstSavm->tblName); + } + else + { + memcpy(stWork.m_pvData, pvoData, pstSavm->lSize); + memcpy(&stWork.m_stCond, &pstSavm->stCond, sizeof(FdCond)); + } + + if(NULL == (pstSavm->m_pstWork = pInsertList(pstSavm->m_pstWork, &stWork, sizeof(TWork)))) + return RC_FAIL; + + return RC_SUCC; +} + +/************************************************************************************************* + description:Initialize the second level cache + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lInitSvCache(SATvm *pstSavm) +{ + size_t lOut = 0, i; + RunTime *pstRun = NULL; + TIndex *pstIndex = NULL; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + if(RC_SUCC != lExportTable(SYS_TVM_INDEX, &lOut, (void *)&pstIndex)) + return RC_FAIL; + + for(i = 0; i < lOut; i ++) + { + pstRun = (RunTime *)pGetRunTime(pstSavm, pstIndex[i].m_table); + pstRun->m_lState = RESOURCE_ABLE; + pstRun->m_shmID = pstIndex[i].m_shmID; + pstRun->m_semID = pstIndex[i].m_semID; + pstRun->m_lLocal = pstIndex[i].m_lLocal; + } + + pstSavm->m_bCache = TRUE; + TFree(pstIndex); + + return RC_SUCC; +} + +/************************************************************************************************* + description:Gets the STVM handle by partition + parameters: + pstSavm --stvm handle + pstTable --table name + pstPart --table part + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +void* pPartSATvm(SATvm *pstSavm, char *pszTable, char *pszPart) +{ + TABLE i; + TIndex stIndex; + RunTime *pstRun = NULL; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return NULL; + } + + memset(&stIndex, 0, sizeof(TIndex)); + strncpy(stIndex.m_szPart, pszPart, sizeof(stIndex.m_szPart)); + strncpy(stIndex.m_szTable, pszTable, sizeof(stIndex.m_szTable)); + + pstSavm->bSearch = TYPE_SYSTEM; + conditinit(pstSavm, stIndex, SYS_TVM_INDEX) + stringset(pstSavm, stIndex, m_szPart, pszPart); + stringset(pstSavm, stIndex, m_szTable, pszTable); + if(RC_SUCC != lSelect(pstSavm, (void *)&stIndex)) + { + if(NO_DATA_FOUND == pstSavm->m_lErrno) + pstSavm->m_lErrno = TBL_NOT_FOUND; + return NULL; + } + + pstSavm->pstVoid = NULL; + pstSavm->tblName = stIndex.m_table; + + pstRun = (RunTime *)pGetRunTime(pstSavm, pstSavm->tblName); + pstRun->m_shmID = stIndex.m_shmID; + pstRun->m_semID = stIndex.m_semID; + pstRun->m_lLocal = stIndex.m_lLocal; + return pstSavm; +} + +/************************************************************************************************* + description:Gets the table STVM handle. + parameters: + pstSavm --stvm handle + t --table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lInitSATvm(SATvm *pstSavm, TABLE t) +{ + TIndex stIndex; + RunTime *pstRun = NULL; + + pstSavm->tblName = t; + pstRun = (RunTime *)pGetRunTime(pstSavm, t); + if(pstRun->m_bAttch && pstRun->m_pvAddr) + return RC_SUCC; + + if(RESOURCE_ABLE == pstRun->m_lState) + { + pstSavm->pstVoid = NULL; + pstSavm->bSearch = TYPE_CLIENT; + return RC_SUCC; + } + + pstSavm->bSearch = TYPE_SYSTEM; + conditinit(pstSavm, stIndex, SYS_TVM_INDEX) + numberset(pstSavm, stIndex, m_table, t) + if(RC_SUCC != lSelect(pstSavm, (void *)&stIndex)) + { + if(NO_DATA_FOUND == pstSavm->m_lErrno) + pstSavm->m_lErrno = TBL_NOT_FOUND; + return RC_FAIL; + } + + pstSavm->tblName = t; + pstSavm->pstVoid = NULL; + strcpy(pstSavm->m_szNode, stIndex.m_szOwner); + + pstRun->m_shmID = stIndex.m_shmID; + pstRun->m_semID = stIndex.m_semID; + pstRun->m_lLocal = stIndex.m_lLocal; + pstRun->m_lRowSize = stIndex.m_lRowSize; + return RC_SUCC; +} + +/************************************************************************************************* + description:Gets the table STVM handle. + parameters: + pstSavm --stvm handle + return: + void* --success + *************************************************************************************************/ +void* pInitSATvm(TABLE t) +{ + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + if(RC_SUCC != lInitSATvm(pstSavm, t)) + return NULL; + + return pstSavm; +} + +/************************************************************************************************* + description:Gets the KEY value for the connection to create the Shared memory + parameters: + pstSavm --stvm handle + return: + tKey + *************************************************************************************************/ +key_t yGetIPCPath(SATvm *pstSavm, Benum em) +{ + key_t tKey = 0; + char szPath[512]; + + memset(szPath, 0, sizeof(szPath)); + snprintf(szPath, sizeof(szPath), "%s", getenv("TVMDBD")); + + if(-1 == (tKey = ftok(szPath, em))) + { + pstSavm->m_lErrno = GENER_KEY_ERR; + return RC_FAIL; + } + + return tKey; +} + +/************************************************************************************************* + description:Connect to Shared memory click test + parameters: + pstSavm --stvm handle + t --table + return: + void* --success + *************************************************************************************************/ +void* pInitHitTest(SATvm *pstSavm, TABLE t) +{ + RunTime *pstRun = (RunTime *)pGetRunTime(pstSavm, t); + + if(RES_REMOT_SID == pstRun->m_lLocal || (pstRun->m_bAttch && pstRun->m_pvAddr)) + return pstRun; + + pstRun->m_pvAddr = (void* )shmat(pstRun->m_shmID, NULL, 0); + if(NULL == pstRun->m_pvAddr || (void *)(-1) == (void *)pstRun->m_pvAddr) + { + if(EACCES == errno) + pstSavm->m_lErrno = SHM_ERR_ACCES; + else if(ENOMEM == errno) + pstSavm->m_lErrno = SHM_ERR_NOMEM; + else + pstSavm->m_lErrno = SHM_ERR_INVAL; + return NULL; + } + + pstSavm->m_lErrno = 0; + pstSavm->m_lEffect= 0; + pstRun->m_bAttch = TRUE; + pstSavm->lSize = lGetRowSize(t); + memcpy((void *)pGetTblDef(t), pstRun->m_pvAddr, sizeof(TblDef)); + + return pstRun; +} + +/************************************************************************************************* + description:Connect to Shared memory + parameters: + pstSavm --stvm handle + t --table + return: + void* --success + *************************************************************************************************/ +void* pInitMemTable(SATvm *pstSavm, TABLE t) +{ + RunTime *pstRun = (RunTime *)pGetRunTime(pstSavm, t); + + if(RES_REMOT_SID == pstRun->m_lLocal) // remote + return pstRun; + + pstSavm->m_lErrno = 0; + pstSavm->m_lEffect = 0; + if(pstRun->m_bAttch && pstRun->m_pvAddr) + { + pstSavm->bSearch = TYPE_CLIENT; + return pstRun; + } + + if(TYPE_SYSTEM == pstSavm->bSearch) + { + pstSavm->bSearch = TYPE_CLIENT; + if(RC_FAIL == (pstSavm->m_yKey = yGetIPCPath(pstSavm, IPC_SHM))) + return NULL; + pstRun->m_shmID = shmget(pstSavm->m_yKey, 0, IPC_CREAT|0600); + + if(pstRun->m_shmID < 0) + { + switch(errno) + { + case EEXIST: + pstSavm->m_lErrno = SHM_ERR_EXIST; + break; + case EIDRM: + pstSavm->m_lErrno = SHM_ERR_EIDRM; + break; + case EACCES: + pstSavm->m_lErrno = SHM_ERR_ACCES; + break; + case ENOMEM: + pstSavm->m_lErrno = SHM_ERR_NOMEM; + break; + default: + pstSavm->m_lErrno = SHM_ERR_INVAL; + break; + } + return NULL; + } + } + + pstRun->m_pvAddr = (void* )shmat(pstRun->m_shmID, NULL, 0); + if(NULL == pstRun->m_pvAddr || (void *)(-1) == (void *)pstRun->m_pvAddr) + { + if(EACCES == errno) + pstSavm->m_lErrno = SHM_ERR_ACCES; + else if(ENOMEM == errno) + pstSavm->m_lErrno = SHM_ERR_NOMEM; + else + pstSavm->m_lErrno = SHM_ERR_INVAL; + return NULL; + } + + pstRun->m_bAttch = TRUE; + + memcpy((void *)pGetTblDef(t), pstRun->m_pvAddr, sizeof(TblDef)); + + if(pstSavm->lSize != lGetRowSize(t)) + { + vTblDisconnect(pstSavm, t); + pstSavm->m_lErrno = VER_NOT_MATCH; + return NULL; + } + + return pstRun; +} + +/************************************************************************************************* + description:Create a memory table space + parameters: + pstSavm --stvm handle + t --table + lSize --The block size + bCreate + return: + void* --success + *************************************************************************************************/ +void* pCreateBlock(SATvm *pstSavm, TABLE t, size_t lSize, bool bCreate) +{ + RunTime *pstRun = NULL; + + if(!pstSavm || lSize <= 0) + { + pstSavm->m_lErrno = BLCK_SIZE_ERR; + return NULL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, t); + memset(pstRun, 0, sizeof(RunTime)); + + if(!bCreate) + { + pstSavm->m_yKey = IPC_PRIVATE; + pstSavm->m_ySey = IPC_PRIVATE; + } + else + { + if(RC_FAIL == (pstSavm->m_yKey = yGetIPCPath(pstSavm, IPC_SHM))) + return NULL; + + if(RC_FAIL == (pstSavm->m_ySey = yGetIPCPath(pstSavm, IPC_SEM))) + return NULL; + } + + pstRun->m_shmID = shmget(pstSavm->m_yKey, lSize, IPC_CREAT|IPC_EXCL|0600); + if(pstRun->m_shmID < 0) + { + switch(errno) + { + case EEXIST: + pstSavm->m_lErrno = SHM_ERR_EXIST; + break; + case EIDRM: + pstSavm->m_lErrno = SHM_ERR_EIDRM; + break; + case EACCES: + pstSavm->m_lErrno = SHM_ERR_ACCES; + break; + case ENOMEM: + pstSavm->m_lErrno = SHM_ERR_NOMEM; + break; + default: + pstSavm->m_lErrno = SHM_ERR_INVAL; + break; + } + return NULL; + } + + pstRun->m_pvAddr = (void* )shmat(pstRun->m_shmID, NULL, 0); + if(NULL == pstRun->m_pvAddr || (void *)(-1) == (void *)pstRun->m_pvAddr) + { + if(EACCES == errno) + pstSavm->m_lErrno = SHM_ERR_ACCES; + else if(ENOMEM == errno) + pstSavm->m_lErrno = SHM_ERR_NOMEM; + else + pstSavm->m_lErrno = SHM_ERR_INVAL; + return NULL; + } + +// memset(pstRun->m_pvAddr, 0, lSize); + pstRun->m_bAttch = TRUE; + + return pstRun; +} + +/************************************************************************************************* + description:add New index field + parameters: + t --table + type --type + from --from position + len --length + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lAddIdxField(TABLE t, long type, long lFrom, long lLen, long lAttr) +{ + long lIdx = 0; + TblKey *pstKey = NULL; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + if(UNQIUE == type) + { + for(lIdx = 0, pstKey = pGetTblIdx(t); lIdx < lGetIdxNum(t); lIdx++) + { + if((pstKey[lIdx].m_lFrom == lFrom) && pstKey[lIdx].m_lLen == lLen) + return RC_SUCC; + } + + if(MAX_FILED_IDX <= lGetIdxNum(t)) + { + pstSavm->m_lErrno = IDX_DEF_SPILL; + return RC_FAIL; + } + + ((TblDef *)pGetTblDef(t))->m_lIdxLen += lLen; + if(MAX_INDEX_LEN < (((TblDef *)pGetTblDef(t))->m_lIdxLen)) + { + pstSavm->m_lErrno = IDX_LEN_SPILL; + return RC_FAIL; + } + + pstKey[lGetIdxNum(t)].m_lFrom = lFrom; + pstKey[lGetIdxNum(t)].m_lLen = lLen; + pstKey[lGetIdxNum(t)].m_lAttr = lAttr; + ((TblDef *)pGetTblDef(t))->m_lIdxUp ++; + ((TblDef *)pGetTblDef(t))->m_lIType |= type; + + return RC_SUCC; + } + else if(NORMAL == type || HASHID == type) + { + for(lIdx = 0, pstKey = pGetTblGrp(t); lIdx < lGetGrpNum(t); lIdx++) + { + if((pstKey[lIdx].m_lFrom == lFrom) && pstKey[lIdx].m_lLen == lLen) + return RC_SUCC; + } + + if(MAX_FILED_IDX <= lGetGrpNum(t)) + { + pstSavm->m_lErrno = GRP_DEF_SPILL; + return RC_FAIL; + } + + ((TblDef *)pGetTblDef(t))->m_lGrpLen += lLen; + if(MAX_INDEX_LEN < (((TblDef *)pGetTblDef(t))->m_lGrpLen)) + { + pstSavm->m_lErrno = GRP_LEN_SPILL; + return RC_FAIL; + } + + pstKey[lGetGrpNum(t)].m_lFrom = lFrom; + pstKey[lGetGrpNum(t)].m_lLen = lLen; + pstKey[lGetGrpNum(t)].m_lAttr = lAttr; + ((TblDef *)pGetTblDef(t))->m_lGrpUp ++; + ((TblDef *)pGetTblDef(t))->m_lIType |= type; + + return RC_SUCC; + } + + pstSavm->m_lErrno = IDX_TYP_NODEF; + + return RC_FAIL; +} + +/************************************************************************************************* + description:set index field + parameters: + t --table + type --type + from --from position + len --length + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lSetTableIdx(TABLE t, long lFrom, long lLen, char *pszDesc, long lAttr, long lType) +{ + long lIdx = 0; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + TblKey *pstKey = (TblKey *)pGetTblKey(t); + + for(lIdx = 0; lIdx < lGetFldNum(t); lIdx ++) + { + if((pstKey[lIdx].m_lFrom == lFrom) && pstKey[lIdx].m_lLen == lLen) + return RC_SUCC; + } + + if(MAX_FILED_NUM <= lGetFldNum(t)) + { + pstSavm->m_lErrno = FLD_DEF_SPILL; + return RC_FAIL; + } + + pstKey[lGetFldNum(t)].m_lFrom = lFrom; + pstKey[lGetFldNum(t)].m_lLen = lLen; + pstKey[lGetFldNum(t)].m_lAttr = lAttr; + pstKey[lGetFldNum(t)].m_lIsPk = lType; + strncpy(pstKey[lGetFldNum(t)].m_szField, pszDesc, sizeof(pstKey[lGetFldNum(t)].m_szField)); + ((TblDef *)pGetTblDef(t))->m_lIdxNum ++; + + return RC_SUCC; +} + +/************************************************************************************************* + description:find filed key + parameters: + pstIdx --field list + lNum --number + pszField --field name + return: + TblKey* + *************************************************************************************************/ +TblKey* pFindField(TblKey *pstIdx, long lNum, char *pszField) +{ + register int i; + + for(i = 0; i < lNum; i ++) + { + if(!strcmp(pstIdx[i].m_szField, pszField)) + return &pstIdx[i]; + } + + return NULL; +} + +/************************************************************************************************* + description:insert table field + parameters: + pstSavm --stvm handle + t --table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lInsertField(SATvm *pstSavm, TABLE t) +{ + TField stField; + long i, lIdx = lGetFldNum(t); + TblKey *pstIdx = pGetTblKey(t); + + if(NULL == (pstSavm = (SATvm *)pInitSATvm(SYS_TVM_FIELD))) + return RC_FAIL; + + insertinit(pstSavm, stField, SYS_TVM_FIELD) + for(i = 0; i < lIdx; i ++) + { + memset(&stField, 0, sizeof(TField)); + stField.m_table = t; + stField.m_lSeq = i + 1; + stField.m_lAttr = pstIdx[i].m_lAttr; + stField.m_lFrom = pstIdx[i].m_lFrom; + stField.m_lLen = pstIdx[i].m_lLen; + stField.m_lIsPk = pstIdx[i].m_lIsPk; + strncpy(stField.m_szOwner, TVM_NODE_INFO, sizeof(stField.m_szOwner)); + strncpy(stField.m_szTable, sGetTableName(t), sizeof(stField.m_szTable)); + strncpy(stField.m_szField, pstIdx[i].m_szField, sizeof(stField.m_szField)); + + if(RC_SUCC != lInsert(pstSavm)) + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Merge valid data to update fields + parameters: + pstSavm --stvm handle + s + p + eType + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lMergeTruck(SATvm *pstSavm, FdCond *pstCond, char *p, char *pvData) +{ + register int i = 0; + FdKey *pFdKey; + + if(0 == pstCond->uFldcmp) + { + pstSavm->m_lErrno = UPDFD_NOT_SET; + return RC_FAIL; + } + + for(i = 0; i < pstCond->uFldcmp; i ++) + { + pFdKey = &pstCond->stFdKey[i]; + memcpy(pvData + pFdKey->uFldpos, p + pFdKey->uFldpos, pFdKey->uFldlen); + } +} + +/************************************************************************************************* + description:Returns the record of the extremum field + parameters: + s --original date + p --records to be compared + pstKey --field key + eType --MATCH_MAX or MATCH_MIN + return: + void* + *************************************************************************************************/ +void* pvCompExtrem(void *s, void *p, TblKey *pstKey, Uenum eType) +{ + if(!p) return s; + + if(eType & MATCH_MAX) + { + switch(pstKey->m_lAttr) + { + case FIELD_DOUB: + switch(pstKey->m_lLen) + { + case 4: + if(*((float *)(p + pstKey->m_lFrom)) < *((float *)(s + pstKey->m_lFrom))) + return s; + return p; + case 8: + if(*((double *)(p + pstKey->m_lFrom)) < *((double *)(s + pstKey->m_lFrom))) + return s; + return p; + default: + return p; + } + return p; + case FIELD_LONG: + switch(pstKey->m_lLen) + { + case 2: + if(*((sint *)(p + pstKey->m_lFrom)) < *((sint *)(s + pstKey->m_lFrom))) + return s; + return p; + case 4: + if(*((int *)(p + pstKey->m_lFrom)) < *((int *)(s + pstKey->m_lFrom))) + return s; + return p; + case 8: + if(*((llong *)(p + pstKey->m_lFrom)) < *((llong *)(s + pstKey->m_lFrom))) + return s; + return p; + default: + return p; + } + return p; + case FIELD_CHAR: + if(0 < memcmp(s + pstKey->m_lFrom, p + pstKey->m_lFrom, pstKey->m_lLen)) + return s; + return p; + default: + return p; + } + } + else + { + switch(pstKey->m_lAttr) + { + case FIELD_DOUB: + switch(pstKey->m_lLen) + { + case 4: + if(*((float *)(p + pstKey->m_lFrom)) < *((float *)(s + pstKey->m_lFrom))) + return p; + return s; + case 8: + if(*((double *)(p + pstKey->m_lFrom)) < *((double *)(s + pstKey->m_lFrom))) + return p; + return s; + default: + return p; + } + return p; + case FIELD_LONG: + switch(pstKey->m_lLen) + { + case 2: + if(*((sint *)(p + pstKey->m_lFrom)) < *((sint *)(s + pstKey->m_lFrom))) + return p; + return s; + case 4: + if(*((int *)(p + pstKey->m_lFrom)) < *((int *)(s + pstKey->m_lFrom))) + return p; + return s; + case 8: + if(*((llong *)(p + pstKey->m_lFrom)) < *((llong *)(s + pstKey->m_lFrom))) + return p; + return s; + default: + return p; + } + return p; + case FIELD_CHAR: + if(0 < memcmp(s + pstKey->m_lFrom, p + pstKey->m_lFrom, pstKey->m_lLen)) + return p; + return s; + default: + return p; + } + } + + return p; +} + +/************************************************************************************************* + description:Match table field values + parameters: + pstCon --condit field + s --original date + p --records to be compared + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lFeildMatch(FdCond *pstCond, void *s, void *p) +{ + register int i; + FdKey *pFdKey; + + if(!p) return RC_MATCH; + + for(i = 0; i < pstCond->uFldcmp; i ++) + { + pFdKey = &pstCond->stFdKey[i]; + if(memcmp(s + pFdKey->uFldpos, p + pFdKey->uFldpos, pFdKey->uFldlen)) + return RC_MISMA; + } + + return RC_MATCH; +} + +/************************************************************************************************* + description:Gets the index group space size + parameters: + lRow --rows + return: + size_t + *************************************************************************************************/ +size_t lGetGroupTruck(size_t lRow, size_t *plOfs) +{ + *plOfs = sizeof(SHTree) * lRow; + return (sizeof(SHTree) + sizeof(SHList)) * lRow; +} + +/************************************************************************************************* + description:Gets the tree node space size + parameters: + rows + return: + size_t + *************************************************************************************************/ +size_t lGetTreeTruck(size_t lRow) +{ + return sizeof(SHTree) * lRow; +} + +/************************************************************************************************* + description:insert table field + parameters: + pstSavm --stvm handle + row --row + return: + size_t + *************************************************************************************************/ +size_t lInitialTable(TABLE t, size_t lRow) +{ + size_t lSize = sizeof(TblDef), lIdxOfs = 0; + + g_stTblDef[t].m_lMaxRow = lRow; + + // set NIL + g_stTblDef[t].m_lNodeNil = FPOS(TblDef, m_stNil); + memset(&g_stTblDef[t].m_stNil, 0, sizeof(SHTree)); + g_stTblDef[t].m_stNil.m_eColor = COLOR_BLK; + g_stTblDef[t].m_stNil.m_lSePos = g_stTblDef[t].m_lNodeNil; + + if(HAVE_UNIQ_IDX(t)) + { + g_stTblDef[t].m_lTreePos = lSize; + g_stTblDef[t].m_lTreeRoot = lSize; + lSize += lGetTreeTruck(lRow); + } + else + { + g_stTblDef[t].m_lTreePos = 0; + g_stTblDef[t].m_lTreeRoot = 0; + } + + if(HAVE_NORL_IDX(t) || HAVE_HASH_IDX(t)) + { + g_stTblDef[t].m_lGroupPos = lSize; + g_stTblDef[t].m_lGroupRoot = lSize; + lSize += lGetGroupTruck(lRow, &g_stTblDef[t].m_lListPos); + g_stTblDef[t].m_lListOfs = g_stTblDef[t].m_lGroupPos + g_stTblDef[t].m_lListPos; + } + else + { + g_stTblDef[t].m_lListPos = 0; + g_stTblDef[t].m_lListOfs = 0; + g_stTblDef[t].m_lGroupPos = 0; + g_stTblDef[t].m_lGroupRoot= 0; + } + + g_stTblDef[t].m_lData = lSize; + lSize += g_stTblDef[t].m_lTruck * lRow; + + return lSize; +} + +/************************************************************************************************* + description:count list + parameters: + pvAddr --Adress + pstList --SHList + return: + size_t + *************************************************************************************************/ +size_t lGetListCount(void *pvAddr, SHList *pstList) +{ + size_t lCount; + + if(!pstList || SELF_POS_UNUSE == pstList->m_lPos) + return 0; + + for(lCount = 1; SELF_POS_UNUSE != pstList->m_lNext; + pstList = (SHList *)pGetNode(pvAddr, pstList->m_lNext)) + ++ lCount; + + return lCount; +} + +/************************************************************************************************* + description:Initialize the index group + parameters: + pvData --address + t --table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lInitailGroup(SATvm *pstSavm, void *pvData, TABLE t) +{ + long lRow = 0; + void *psData = NULL; + SHTree *pstTree = NULL; + SHList *pstList = NULL; + + if(!pvData) + { + pstSavm->m_lErrno = SHMT_NOT_INIT; + return RC_FAIL; + } + + if(lGetGrpNum(t) <= 0) return RC_SUCC; + + for(psData = pvData + lGetListPos(t); lRow < lGetTblRow(t); lRow ++) + { + pstTree = (SHTree *)(pvData + lRow * sizeof(SHTree)); + memset(pstTree, 0, sizeof(SHTree)); + pstTree->m_lSePos = SELF_POS_UNUSE; + pstTree->m_lData = SELF_POS_UNUSE; + + pstList = (SHList *)(psData + lRow * sizeof(SHList)); + pstList->m_lPos = SELF_POS_UNUSE; + pstList->m_lNode = SELF_POS_UNUSE; + pstList->m_lData = lGetTblData(t) + lGetRowTruck(t) * lRow; + pstList->m_lNext = SELF_POS_UNUSE; + pstList->m_lLast = SELF_POS_UNUSE; + } + ((TblDef *)pGetTblDef(t))->m_lGroupRoot = lGetGrpPos(t); + + return RC_SUCC; +} + +/************************************************************************************************* + description:Initialize the index tree + parameters: + pstSavm --stvm handle + pvData --address + t --table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lInitailTree(SATvm *pstSavm, void *pvData, TABLE t) +{ + long lRow = 0; + SHTree *pstTree = NULL; + + if(!pvData) + { + pstSavm->m_lErrno = SHMT_NOT_INIT; + return RC_FAIL; + } + + if(lGetIdxNum(t) <= 0) return RC_SUCC; + + for(lRow = 0; lRow < lGetTblRow(t); lRow ++) + { + pstTree = (SHTree *)(pvData + lRow * sizeof(SHTree)); + memset(pstTree, 0, sizeof(SHTree)); + pstTree->m_lSePos = SELF_POS_UNUSE; + pstTree->m_lData = lGetTblData(t) + lGetRowTruck(t) * lRow; + } + ((TblDef *)pGetTblDef(t))->m_lTreeRoot = lGetIdxPos(t); + + return RC_SUCC; +} + +/************************************************************************************************* + description:Calculate the hash value + parameters: + s --key + n --length + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +uint uGetHash(char *s, long n) +{ + uint hash = 0; + static uint i, seed = 131; + + for(i = 0; i < n; i ++) + hash = hash * seed + (*s++); + + return (hash & 0x7FFFFFFF); +} + +/************************************************************************************************* + description:Gets the address of the offset + parameters: + lOffset --key + return: + void* + *************************************************************************************************/ +void* pGetNode(void *pvData, size_t lOffset) +{ + return (void *)(pvData + lOffset); +} + +/************************************************************************************************* + description:Create node + parameters: + pvData --address + t --length + lOffset --offset address + return: + SHTree* + *************************************************************************************************/ +SHTree* pCreateNode(void *pvData, TABLE t, size_t lOffset) +{ + return (SHTree *)(pvData + lOffset); +} + +/************************************************************************************************* + description:Create index node + parameters: + pvData --address memory + t --table + pstGroup --tree node + lGroup --Group offset + ppstTruck --Data truck + return: + SHTree* + *************************************************************************************************/ +SHTree* pCreateGroup(void *pvData, TABLE t, SHTree *pstGroup, size_t lGroup, SHTruck **ppstTruck) +{ + size_t lOffset = 0; + SHList *pstList = NULL, *pstNode = NULL; + + if(!pstGroup) pstGroup = (SHTree *)(pvData + lGroup); + lOffset = lGetListOfs(t) + sizeof(SHList) * ((TblDef *)pvData)->m_lValid; + pstList = (SHList *)pGetNode(pvData, lOffset); + pstList->m_lPos = lOffset; + *ppstTruck = (PSHTruck)pGetNode(pvData, pstList->m_lData); + + if(pstGroup->m_lData == SELF_POS_UNUSE) + { + pstList->m_lNode = lGroup; + pstGroup->m_lData = pstList->m_lPos; + } + else + { + pstNode = (SHList *)pGetNode(pvData, pstGroup->m_lData); + +#if 0 + pstList->m_lNext = pstNode->m_lNext; + pstList->m_lLast = pstNode->m_lPos; + if(SELF_POS_UNUSE != pstNode->m_lNext) + ((SHList *)pGetNode(pvData, pstNode->m_lNext))->m_lLast = pstList->m_lPos; + pstNode->m_lNext = pstList->m_lPos; +#else + pstGroup->m_lData = pstList->m_lPos; + pstList->m_lNode = pstGroup->m_lSePos; + pstList->m_lNext = pstNode->m_lPos; + pstNode->m_lLast = pstList->m_lPos; +#endif + } + + return pstGroup; +} + +/************************************************************************************************* + description:reset data list + parameters: + pvData --address memory + t --table + pstTree --tree node + plOut + return: + *************************************************************************************************/ +void vResetList(void *pvData, TABLE t, SHTree *pstTree, long *plOut) +{ + size_t lOffset, lNext; + SHList *pstList = NULL, *pstTail = NULL; + + + return ; +#if 0 + if(pstTree->m_lData <= SELF_POS_UNUSE) + return ; + +fprintf(stderr, "vResetList error \n"); +exit(-1); + + lOffset = lGetListOfs(t) + lGetTblValid(t) * sizeof(SHList); + // 将链表中的数据向前移动,将后面空间释放出来待下次使用, 同时 g_lTreeNode 个数减一 + for(pstList = (SHList *)pGetNode(pvData, pstTree->m_lData); SELF_POS_UNUSE != pstList->m_lPos; + (*plOut) ++, pstList = (SHList *)pGetNode(pvData, lNext)) + { + lNext = pstList->m_lNext; + + lOffset -= sizeof(SHList); + pstTail = (SHList *)pGetNode(pvData, lOffset); + if(pstList == pstTail) + { + pstTail->m_lPos = SELF_POS_UNUSE; + pstTail->m_lNode = SELF_POS_UNUSE; + pstTail->m_lNext = SELF_POS_UNUSE; + pstTail->m_lLast = SELF_POS_UNUSE; + if(SELF_POS_UNUSE == lNext) break; + continue; + } + + if(SELF_POS_UNUSE != pstTail->m_lLast) + ((SHList *)pGetNode(pvData, pstTail->m_lLast))->m_lNext = pstList->m_lPos; + memcpy(pstList, pstTail, sizeof(SHList)); + pstTail->m_lPos = SELF_POS_UNUSE; + pstTail->m_lNode = SELF_POS_UNUSE; + pstTail->m_lNext = SELF_POS_UNUSE; + pstTail->m_lLast = SELF_POS_UNUSE; + if(SELF_POS_UNUSE == lNext) break; + } +#endif + + pstTree->m_lData = SELF_POS_UNUSE; +} + +/************************************************************************************************* + description:Release the deleted node + parameters: + pstSavm --stvm handle + pvData --address memory + pstRoot --tree root + pstTree --tree node + pstSon --child node + return: + SHTree* + *************************************************************************************************/ +SHTree* pReleaseNode(void *pvData, TABLE t, SHTree *pstRoot, SHTree *pstTree, SHTree **ppstSon) +{ + size_t lSePos = 0, lData, lVaild; + SHTree *pstTail = NULL, *pstNode = NULL; + + if(!pstTree || ((TblDef *)pvData)->m_lValid < 1) + return pstRoot; + + lData = pstTree->m_lData; // backup lData + lVaild = ((TblDef *)pvData)->m_lValid - 1; + pstTail = (SHTree *)(pvData + lGetIdxPos(t) + lVaild * sizeof(SHTree)); + if(pstTail == pstTree) // The tail node is exactly deleted + { + memset(pstTail, 0, sizeof(SHTree)); + pstTail->m_lData = lData; + return pstRoot; + } + + if(ppstSon) + { + if(*ppstSon == pstTail) // move Son(tail) node + *ppstSon = pstTree; + else if(pstTree->m_lParent == pstTail->m_lSePos) + ((SHTree *)*ppstSon)->m_lParent = pstTree->m_lSePos; + } + + lSePos = pstTail->m_lSePos; // backup lSePos + pstTail->m_lSePos = pstTree->m_lSePos; + memcpy((void *)pstTree, (void *)pstTail, sizeof(SHTree)); + memset(pstTail, 0, sizeof(SHTree)); + pstTail->m_lData = lData; + + // modify parent and child node + if(NODE_NULL != pstTree->m_lParent) + { + pstNode = (SHTree *)pGetNode(pvData, pstTree->m_lParent); + if(lSePos == pstNode->m_lLeft) + pstNode->m_lLeft = pstTree->m_lSePos; + else + pstNode->m_lRight = pstTree->m_lSePos; + } + else // May be the tail of the root moved + { + pstRoot = pstTree; + } + + if(NODE_NULL != pstTree->m_lLeft) + { + pstNode = (SHTree *)pGetNode(pvData, pstTree->m_lLeft); + pstNode->m_lParent = pstTree->m_lSePos; + } + + if(NODE_NULL != pstTree->m_lRight) + { + pstNode = (SHTree *)pGetNode(pvData, pstTree->m_lRight); + pstNode->m_lParent = pstTree->m_lSePos; + } + + return pstRoot; +} + +/************************************************************************************************* + description:Release deleted data block space + parameters: + pvAddr --address memory + t --table + pstTruck --Data truck + bErase --erase + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lReleaseTruck(void *pvAddr, TABLE t, SHTruck *pstTruck, bool bErase) +{ + size_t lOffset = 0; + SHTruck *pstTail = NULL; + + if(bErase) + { + memset(pstTruck, 0, lGetRowTruck(t)); + return RC_SUCC; + } + + if(((TblDef *)pvAddr)->m_lValid < 1) + return RC_SUCC; + + lOffset = lGetTblData(t) + lGetRowTruck(t) * (((TblDef *)pvAddr)->m_lValid - 1); + pstTail = (PSHTruck)pGetNode(pvAddr, lOffset); + if(pstTruck == pstTail) + { + memset(pstTail, 0, lGetRowTruck(t)); + return RC_SUCC; + } + + memcpy(pstTruck, pstTail, lGetRowTruck(t)); + memset(pstTail, 0, lGetRowTruck(t)); + + return RC_SUCC; +} + +/************************************************************************************************* + description:Release index node + parameters: + pvData --address memory + t --table + pstRoot --tree root + pstTree --tree node + pstSon --child node + plOut + return: + SHTree* + *************************************************************************************************/ +SHTree* pReleaseGroup(void *pvData, TABLE t, SHTree *pstRoot, SHTree *pstTree, SHTree **ppstSon, + long *plOut) +{ + size_t lSePos = 0, lVaild; + SHTree *pstTail = NULL, *pstNode = NULL; + + if(!pstTree || ((TblDef *)pvData)->m_lGroup < 1) + return pstRoot; + +// vResetList(pvData, t, pstTree, plOut); + + lVaild = -- ((TblDef *)pvData)->m_lGroup; + pstTail = (SHTree *)(pvData + lGetGrpPos(t) + lVaild * sizeof(SHTree)); + if(pstTail == pstTree) + { + memset(pstTail, 0, sizeof(SHTree)); + return pstRoot; + } + + if(ppstSon) + { + if(*ppstSon == pstTail) // move Son(tail) node + *ppstSon = pstTree; + else if(pstTree->m_lParent == pstTail->m_lSePos) + ((SHTree *)*ppstSon)->m_lParent = pstTree->m_lSePos; + } + + lSePos = pstTail->m_lSePos; // backup SePos + pstTail->m_lSePos = pstTree->m_lSePos; + memcpy((void *)pstTree, (void *)pstTail, sizeof(SHTree)); + memset(pstTail, 0, sizeof(SHTree)); + ((SHList *)pGetNode(pvData, pstTree->m_lData))->m_lNode = pstTree->m_lSePos; + + if(NODE_NULL != pstTree->m_lParent) + { + pstNode = (SHTree *)pGetNode(pvData, pstTree->m_lParent); + if(lSePos == pstNode->m_lLeft) + pstNode->m_lLeft = pstTree->m_lSePos; + else + pstNode->m_lRight = pstTree->m_lSePos; + } + else + { + pstRoot = pstTree; + } + + if(NODE_NULL != pstTree->m_lLeft) + { + pstNode = (SHTree *)pGetNode(pvData, pstTree->m_lLeft); + pstNode->m_lParent = pstTree->m_lSePos; + } + + if(NODE_NULL != pstTree->m_lRight) + { + pstNode = (SHTree *)pGetNode(pvData, pstTree->m_lRight); + pstNode->m_lParent = pstTree->m_lSePos; + } + + return pstRoot; +} + +/************************************************************************************************* + description:Release list node + parameters: + pvData --address memory + t --table + pstTree --tree node + pstList --data list + lOffset --Data offset + plNext --lNext offset + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lReleaseList(void *pvData, TABLE t, SHTree *pstTree, SHList *pstList, size_t lOffset, + size_t *plNext) +{ + size_t lData; + SHList *pstTail = NULL; + + pstTail = (SHList *)pGetNode(pvData, lOffset); + if(SELF_POS_UNUSE == pstTail->m_lPos) + return RC_FAIL; + + if(pstTree->m_lData == pstList->m_lPos) + { + pstTree->m_lData = pstList->m_lNext; + if(SELF_POS_UNUSE != pstList->m_lNext) + { + ((SHList *)pGetNode(pvData, pstList->m_lNext))->m_lLast = SELF_POS_UNUSE; + ((SHList *)pGetNode(pvData, pstList->m_lNext))->m_lNode = pstTree->m_lSePos; + } + } + else + { + ((SHList *)pGetNode(pvData, pstList->m_lLast))->m_lNext = pstList->m_lNext; + if(SELF_POS_UNUSE != pstList->m_lNext) + ((SHList *)pGetNode(pvData, pstList->m_lNext))->m_lLast = pstList->m_lLast; + } + + if(pstTail == pstList) + { + // save lData + pstList->m_lPos = SELF_POS_UNUSE; + pstList->m_lNode = SELF_POS_UNUSE; + pstList->m_lNext = SELF_POS_UNUSE; + pstList->m_lLast = SELF_POS_UNUSE; + return RC_SUCC; + } + + // If the pstTail node is the next scan node + if(pstTail->m_lPos == pstList->m_lNext) + *plNext = pstList->m_lPos; + + lData = pstList->m_lData; + if(pstTail->m_lPos == pstTree->m_lData) + pstTree->m_lData = pstList->m_lPos; + else + { + if(SELF_POS_UNUSE == pstTail->m_lLast) + ((SHTree *)pGetNode(pvData, pstTail->m_lNode))->m_lData = pstList->m_lPos; + } + + if(SELF_POS_UNUSE != pstTail->m_lLast) + ((SHList *)pGetNode(pvData, pstTail->m_lLast))->m_lNext = pstList->m_lPos; + if(SELF_POS_UNUSE != pstTail->m_lNext) + ((SHList *)pGetNode(pvData, pstTail->m_lNext))->m_lLast = pstList->m_lPos; + + pstList->m_lNode = pstTail->m_lNode; + pstList->m_lNext = pstTail->m_lNext; + pstList->m_lData = pstTail->m_lData; + pstList->m_lLast = pstTail->m_lLast; + + pstTail->m_lData = lData; + pstTail->m_lPos = SELF_POS_UNUSE; + pstTail->m_lNode = SELF_POS_UNUSE; + pstTail->m_lNext = SELF_POS_UNUSE; + pstTail->m_lLast = SELF_POS_UNUSE; + + return RC_SUCC; +} + +/************************************************************************************************* + description:Left-Rotate the red-black tree node (pstTree) + parameters: + pvData --address memory + pstRoot --tree root + pstTree --tree node + return: + SHTree* + + Schematic: + root root + / / + tree node + / \ --(L--R)--> / \ # + lA node tree rC + / \ / \ + lB rC lA lB + *************************************************************************************************/ +SHTree* _pLeftRotation(void *pvData, SHTree *pstRoot, SHTree *pstTree) +{ + SHTree *pstCur = NULL, *pstNode = (SHTree *)pGetNode(pvData, pstTree->m_lRight); + + // set "pstNode's left child" as "pstTree's right child" + // if the "pstNode's left is not null", set "pstTree" as father of the left child of pstNode + pstTree->m_lRight = pstNode->m_lLeft; + if(NODE_NULL != pstNode->m_lLeft) + { + pstCur = (SHTree *)pGetNode(pvData, pstNode->m_lLeft); + pstCur->m_lParent = pstTree->m_lSePos; + } + + // Set "pstTree's father" as "pstNode's father" + pstNode->m_lParent = pstTree->m_lParent; + + if(NODE_NULL == pstTree->m_lParent) + pstRoot = pstNode; // create new Root + else + { + pstCur = (SHTree *)pGetNode(pvData, pstTree->m_lParent); + if(pstCur->m_lLeft == pstTree->m_lSePos) + pstCur->m_lLeft = pstNode->m_lSePos; + else + pstCur->m_lRight = pstNode->m_lSePos; + } + + // set "pstTree" as "pstNode's left child" + pstNode->m_lLeft = pstTree->m_lSePos; + + // set "pstTree's father" as "pstNode” + pstTree->m_lParent = pstNode->m_lSePos; + + return pstRoot; +} + +/************************************************************************************************* + description:Right-Rotate the red-black tree node (pstTree) + parameters: + pvData --address memory + pstRoot --tree root + pstTree --tree node + return: + SHTree* + + Schematic: + root root + / / + tree node + / \ --(R--R)--> / \ # + node rC lA tree + / \ / \ # + lA rB rB rC + *************************************************************************************************/ +SHTree* _pRightRotation(void *pvData, SHTree *pstRoot, SHTree *pstTree) +{ + SHTree *pstCur = NULL, *pstNode = (SHTree *)pGetNode(pvData, pstTree->m_lLeft); + + // set "pstNode's right child" as "pstTree's left child" + // if the "pstNode's right is not null, set "pstTree" as father of the right child of pstNode + pstTree->m_lLeft = pstNode->m_lRight; + if(NODE_NULL != pstNode->m_lRight) + { + pstCur = (SHTree *)pGetNode(pvData, pstNode->m_lRight); + pstCur->m_lParent = pstTree->m_lSePos; + } + + // set "pstTree's parent" as "pstNode's parent" + pstNode->m_lParent = pstTree->m_lParent; + if(NODE_NULL == pstTree->m_lParent) + pstRoot = pstNode; + else + { + pstCur = (SHTree *)pGetNode(pvData, pstTree->m_lParent); + if(pstCur->m_lLeft == pstTree->m_lSePos) + pstCur->m_lLeft = pstNode->m_lSePos; + else + pstCur->m_lRight = pstNode->m_lSePos; + } + + // set "pstTree" as "pstNode's right child" + pstNode->m_lRight = pstTree->m_lSePos; + // set "pstTree's parent as "pstNode" + pstTree->m_lParent = pstNode->m_lSePos; + + return pstRoot; +} + +/************************************************************************************************* + description:Get extreme values in RBTree traversal + parameters: + uEnum + pvData --addree memory + pstTree --tree node + return: + SHTree* + *************************************************************************************************/ +SHTree* pExtremeTree(Uenum uEnum, void *pvData, SHTree *pstTree) +{ + if(SELF_POS_UNUSE == pstTree->m_lSePos || NODE_NULL == pstTree->m_lSePos) + return NULL; + + if(uEnum & MATCH_MAX) + { + while(SELF_POS_UNUSE != pstTree->m_lRight && NODE_NULL != pstTree->m_lRight) + pstTree = (SHTree *)pGetNode(pvData, pstTree->m_lRight); + } + else + { + while(SELF_POS_UNUSE != pstTree->m_lLeft && NODE_NULL != pstTree->m_lLeft) + pstTree = (SHTree *)pGetNode(pvData, pstTree->m_lLeft); + } + + if(SELF_POS_UNUSE == pstTree->m_lSePos && NODE_NULL == pstTree->m_lSePos) + pstTree = NULL; + + return pstTree; +} + +/************************************************************************************************* + description:Specify the KEY value in the RBTree traversal + parameters: + pvData --addree memory + psTree --tree node + psvIdx --index value + lIdx --value length + return: + SHTree* + *************************************************************************************************/ +SHTree* pSearchTree(void *pvData, SHTree *pstTree, void *psvIdx, long lIdx) +{ + if(SELF_POS_UNUSE == pstTree->m_lSePos || NODE_NULL == pstTree->m_lSePos) + return NULL; + + if(!memcmp(pstTree->m_szIdx, psvIdx, lIdx)) + return pstTree; + + if(0 < memcmp(pstTree->m_szIdx, psvIdx, lIdx)) + return pSearchTree(pvData, (SHTree *)pGetNode(pvData, pstTree->m_lLeft), psvIdx, lIdx); + else + return pSearchTree(pvData, (SHTree *)pGetNode(pvData, pstTree->m_lRight), psvIdx, lIdx); +} + +/************************************************************************************************* + description:Gets a list of data sets + parameters: + pvData --addree memory + psTree --tree node + psvIdx --index value + lIdx --value length + return: + SHList* + *************************************************************************************************/ +SHList *pSearchGroup(void *pvData, SHTree *pstTree, void *psvIdx, long lIdx) +{ + if(NULL == (pstTree = pSearchTree(pvData, pstTree, psvIdx, lIdx))) + return NULL; + + // If the group information exists in an abnormal situation, + // but there are numerous references, then the group should be deleted. + if(SELF_POS_UNUSE == pstTree->m_lData) + return NULL; + + return (SHList *)pGetNode(pvData, pstTree->m_lData); +} + +/************************************************************************************************* + description:Restore the new RBTree imbalance problem + parameters: + pvData --addree memory + pstRoot --root node + pstCur --tree node + return: + SHTree* + *************************************************************************************************/ +SHTree* _pFixupInsert(void *pvData, SHTree *pstRoot, SHTree *pstCur) +{ + SHTree *pstParent = NULL, *pstUncle = NULL, *pstGrand = NULL; + + while((pstParent = (SHTree *)pGetNode(pvData, pstCur->m_lParent)) && IS_RED(pstParent)) + { + pstGrand = (SHTree *)pGetNode(pvData, pstParent->m_lParent); + if(pstParent->m_lSePos == pstGrand->m_lLeft) + { + pstUncle = (SHTree *)pGetNode(pvData, pstGrand->m_lRight); + if((NODE_NULL != pstUncle->m_lSePos) && IS_RED(pstUncle)) + { + pstUncle->m_eColor = COLOR_BLK; + pstParent->m_eColor = COLOR_BLK; + pstGrand->m_eColor = COLOR_RED; + pstCur = pstGrand; + continue; + } + + if(pstCur->m_lSePos == pstParent->m_lRight) + { + pstRoot = _pLeftRotation(pvData, pstRoot, pstParent); + pstParent = pstCur; + } + + pstParent->m_eColor = COLOR_BLK; + pstGrand->m_eColor = COLOR_RED; + pstRoot = _pRightRotation(pvData, pstRoot, pstGrand); + } + else + { + pstUncle = (SHTree *)pGetNode(pvData, pstGrand->m_lLeft); + if((NODE_NULL != pstUncle->m_lSePos) && IS_RED(pstUncle)) + { + pstUncle->m_eColor = COLOR_BLK; + pstParent->m_eColor = COLOR_BLK; + pstGrand->m_eColor = COLOR_RED; + pstCur = pstGrand; + continue; + } + + if(pstCur->m_lSePos == pstParent->m_lLeft) + { + pstRoot = _pRightRotation(pvData, pstRoot, pstParent); + pstParent = pstCur; + } + + pstParent->m_eColor = COLOR_BLK; + pstGrand->m_eColor = COLOR_RED; + pstRoot = _pLeftRotation(pvData, pstRoot, pstGrand); + } + } + + pstRoot->m_eColor = COLOR_BLK; // set root is black + + return pstRoot; +} + +/************************************************************************************************* + description:Insert the new node into r-btree and return the root node + parameters: + pstSavm --stvm handle + pstRoot --tree Root + psvIdx --index value + lIdx --value length + ppstTruck --data truck + return: + SHTree* + *************************************************************************************************/ +SHTree* pInsertTree(SATvm *pstSavm, SHTree *pstRoot, void *psvIdx, long lIdx, SHTruck **ppstTruck) +{ + int nRet = 0; + size_t lOffset; + SHTree *pstNode = NULL, *pstCur = NULL, *pstTree = pstRoot; + void *pvData = NULL, *pvAddr = pGetAddr(pstSavm, pstSavm->tblName); + + while(SELF_POS_UNUSE != pstTree->m_lSePos && NODE_NULL != pstTree->m_lSePos) + { + pstNode = pstTree; + nRet = memcmp(pstTree->m_szIdx, psvIdx, lIdx); + if(0 < nRet) + { + if(NODE_NULL == pstTree->m_lLeft) + break; + pstTree = (SHTree *)pGetNode(pvAddr, pstTree->m_lLeft); + } + else if(0 > nRet) + { + if(NODE_NULL == pstTree->m_lRight) + break; + pstTree = (SHTree *)pGetNode(pvAddr, pstTree->m_lRight); + } + else + { + pstSavm->m_lErrno = UNIQ_IDX_REPT; + return NULL; + } + } + + lOffset = sizeof(SHTree) * ((TblDef *)pvAddr)->m_lValid + lGetIdxPos(pstSavm->tblName); + if(NULL == (pstCur = pCreateNode(pvAddr, pstSavm->tblName, lOffset))) + { + pstSavm->m_lErrno = IDX_SPC_SPILL; + return NULL; + } + + if(*ppstTruck && (*ppstTruck != (PSHTruck)pGetNode(pvAddr, pstCur->m_lData))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return NULL; + } + else + { + *ppstTruck = (PSHTruck)pGetNode(pvAddr, pstCur->m_lData); + if(!IS_TRUCK_NULL(*ppstTruck)) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return NULL; + } + } + + pstCur->m_lIdx = lIdx; + pstCur->m_lSePos = lOffset; + pstCur->m_lParent = NODE_NULL; + memcpy(pstCur->m_szIdx, psvIdx, pstCur->m_lIdx); + // set parent node and left -right node is NIL + pstCur->m_lLeft = pstCur->m_lRight = NODE_NULL; + + if(pstNode != NULL) + { + pstCur->m_eColor = COLOR_RED; + pstCur->m_lParent = pstNode->m_lSePos; + if(0 < memcmp(pstNode->m_szIdx, pstCur->m_szIdx, pstCur->m_lIdx)) + pstNode->m_lLeft = pstCur->m_lSePos; + else + pstNode->m_lRight = pstCur->m_lSePos; + } + else + { + pstRoot = pstCur; + pstCur->m_eColor = COLOR_BLK; + return pstRoot; + } + + return _pFixupInsert(pvAddr, pstRoot, pstCur); +} + +/************************************************************************************************* + description:Insert values and handle collisions according to the hash table + parameters: + pstSavm --stvm handle + pvAddr --address memory + t --table + pstTree --tree node + lGroup --group offset + ppstTruck --data truck + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long __lInsertHash(SATvm *pstSavm, void *pvAddr, TABLE t, SHTree *pstTree, size_t lGroup, + SHTruck **ppstTruck) +{ + size_t lOffset; + SHTruck *pstTruck = NULL; + SHList *pstList = NULL, *pstNode = NULL; + + lOffset = lGetListOfs(t) + sizeof(SHList) * ((TblDef *)pvAddr)->m_lValid; + pstList = (SHList *)pGetNode(pvAddr, lOffset); + pstList->m_lPos = lOffset; + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + + // If the data space has been found in the previous only index creation, recheck it + if(!IS_TRUCK_NULL(pstTruck) || ((*ppstTruck) && (*ppstTruck != pstTruck))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + *ppstTruck = pstTruck; + if(SELF_POS_UNUSE == pstTree->m_lSePos || NODE_NULL == pstTree->m_lSePos) + { + pstTree->m_lSePos= lGroup; + pstTree->m_lData = pstList->m_lPos; + pstList->m_lNode = pstTree->m_lSePos; + } + else + { + pstNode = (SHList *)pGetNode(pvAddr, pstTree->m_lData); + + pstList->m_lNext = pstNode->m_lNext; + pstList->m_lLast = pstNode->m_lPos; + if(SELF_POS_UNUSE != pstNode->m_lNext) + ((SHList *)pGetNode(pvAddr, pstNode->m_lNext))->m_lLast = pstList->m_lPos; + pstNode->m_lNext = pstList->m_lPos; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Insert the group node into r-btree and return the root node + parameters: + pstSavm --stvm handle + pstRoot --tree Root + psvIdx --index value + lIdx --value length + ppstTruck --data truck + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +SHTree* pInsertGroup(SATvm *pstSavm, SHTree *pstRoot, void *psvIdx, long lIdx, SHTruck **ppstTruck) +{ + int nRet = 0; + size_t lOffset; + SHTruck *pstTruck = NULL; + void *pvData = pGetAddr(pstSavm, pstSavm->tblName); + SHTree *pstNode = NULL, *pstCur = NULL, *pstTree = pstRoot; + + while(SELF_POS_UNUSE != pstTree->m_lSePos && NODE_NULL != pstTree->m_lSePos) + { + pstNode = pstTree; + nRet = memcmp(pstTree->m_szIdx, psvIdx, lIdx); + if(0 < nRet) + { + if(NODE_NULL == pstTree->m_lLeft) + break; + pstTree = (SHTree *)pGetNode(pvData, pstTree->m_lLeft); + } + else if(0 > nRet) + { + if(NODE_NULL == pstTree->m_lRight) + break; + pstTree = (SHTree *)pGetNode(pvData, pstTree->m_lRight); + } + else + { + pCreateGroup(pvData, pstSavm->tblName, pstTree, 0, &pstTruck); + if(!IS_TRUCK_NULL(pstTruck) || ((*ppstTruck) && (*ppstTruck != pstTruck))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return NULL; + } + + return pstRoot; + } + } + + lOffset = sizeof(SHTree) * ((TblDef *)pvData)->m_lGroup + lGetGrpPos(pstSavm->tblName); + if(NULL == (pstCur = pCreateGroup(pvData, pstSavm->tblName, NULL, lOffset, &pstTruck))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return pstRoot; + } + + // If the data space has been found in the previous only index creation, recheck it + if(!IS_TRUCK_NULL(pstTruck) || ((*ppstTruck) && (*ppstTruck != pstTruck))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return NULL; + } + + ((TblDef *)pvData)->m_lGroup ++; + *ppstTruck = pstTruck; + + pstCur->m_lIdx = lIdx; + pstCur->m_lSePos = lOffset; + pstCur->m_lParent = NODE_NULL; + memcpy(pstCur->m_szIdx, psvIdx, pstCur->m_lIdx); + pstCur->m_lLeft = pstCur->m_lRight = NODE_NULL; + if(pstNode != NULL) + { + pstCur->m_eColor = COLOR_RED; + pstCur->m_lParent = pstNode->m_lSePos; + if(0 < memcmp(pstNode->m_szIdx, pstCur->m_szIdx, pstCur->m_lIdx)) + pstNode->m_lLeft = pstCur->m_lSePos; + else + pstNode->m_lRight = pstCur->m_lSePos; + } + else + { + pstRoot = pstCur; + pstCur->m_eColor = COLOR_BLK; + return pstRoot; + } + + return _pFixupInsert(pvData, pstRoot, pstCur); +} + +/************************************************************************************************* + description:Repair deletion causes RBTree imbalance + parameters: + pvData --stvm handle + pstRoot --tree Root + psTree --tree node + return: + SHTree* + *************************************************************************************************/ +SHTree* _pFixupDelete(void *pvData, SHTree *pstRoot, SHTree *pstTree) +{ + SHTree *pstParent = NULL, *pstBrother = NULL, *pstLeft = NULL, *pstRight = NULL; + + while(COLOR_BLK == pstTree->m_eColor && (pstRoot != pstTree)) + { + pstParent = (SHTree *)pGetNode(pvData, pstTree->m_lParent); + + if(pstTree->m_lSePos == pstParent->m_lLeft) + { + pstBrother = (SHTree *)pGetNode(pvData, pstParent->m_lRight); + + if(COLOR_RED == pstBrother->m_eColor) + { + pstParent->m_eColor = COLOR_RED; + pstBrother->m_eColor = COLOR_BLK; + pstRoot = _pLeftRotation(pvData, pstRoot, pstParent); + + // New sibling nodes. That's what it looks like + pstBrother = (SHTree *)pGetNode(pvData, pstParent->m_lRight); + } + if(NODE_NULL == pstBrother->m_lSePos) + return pstRoot; + + pstLeft = (SHTree *)pGetNode(pvData, pstBrother->m_lLeft); + pstRight = (SHTree *)pGetNode(pvData, pstBrother->m_lRight); + if(COLOR_BLK == pstLeft->m_eColor && COLOR_BLK == pstRight->m_eColor) + { + pstBrother->m_eColor = COLOR_RED; + pstTree = pstParent; + } + else + { + /* 3: Brothers node is black (default), the left node of the brother + node is red, the right child node is black: to the brother as the + fulcrum, right-Rotate*/ + if(COLOR_BLK == pstRight->m_eColor) + { + pstLeft->m_eColor = COLOR_BLK; + pstBrother->m_eColor = COLOR_RED; + pstRoot = _pRightRotation(pvData, pstRoot, pstBrother); + + /* The changed right child of the parent node serves as a new + brother node*/ + pstBrother = (SHTree *)pGetNode(pvData, pstParent->m_lRight); + pstRight = (SHTree *)pGetNode(pvData, pstBrother->m_lRight); + } + + /* 4: Brothers node is black (default), brother node right child + node is red: parent as a fulcrum, left-Rotate */ + pstBrother->m_eColor = pstParent->m_eColor; + pstParent->m_eColor = COLOR_BLK; + pstRight->m_eColor = COLOR_BLK; + pstRoot = _pLeftRotation(pvData, pstRoot, pstParent); + pstTree = pstRoot; + } + } + else // pstTree is pstParent right child + { + pstBrother = (SHTree *)pGetNode(pvData, pstParent->m_lLeft); + if(COLOR_RED == pstBrother->m_eColor) + { + pstParent->m_eColor = COLOR_RED; + pstBrother->m_eColor = COLOR_BLK; + pstRoot = _pRightRotation(pvData, pstRoot, pstParent); + + // New Brothers node. In fact, the effect is left-handed + pstBrother = (SHTree *)pGetNode(pvData, pstParent->m_lLeft); + } + if(NODE_NULL == pstBrother->m_lSePos) + return pstRoot; + + /* Brothers node is black (default), and the two nodes of the + brother node are black */ + pstLeft = (SHTree *)pGetNode(pvData, pstBrother->m_lLeft); + pstRight = (SHTree *)pGetNode(pvData, pstBrother->m_lRight); + if(COLOR_BLK == pstLeft->m_eColor && COLOR_BLK == pstRight->m_eColor) + { + pstBrother->m_eColor = COLOR_RED; + pstTree = pstParent; + } + else + { + /* Brothers node is black (default), the right node of the brother + node is red, the left child node is black: + the brother as a fulcrum, left-rotate*/ + if(COLOR_BLK == pstLeft->m_eColor) + { + pstRight->m_eColor = COLOR_BLK; + pstBrother->m_eColor = COLOR_RED; + pstRoot = _pLeftRotation(pvData, pstRoot, pstBrother); + + // The changed right child of the parent node serves as a new brother node + pstBrother = (SHTree *)pGetNode(pvData, pstParent->m_lLeft); + pstLeft = (SHTree *)pGetNode(pvData, pstBrother->m_lLeft); + } + + /* Brothers node is black (default), brother node left child node is red: + parent as the fulcrum, right-handed processing */ + pstBrother->m_eColor = pstParent->m_eColor; + pstParent->m_eColor = COLOR_BLK; + pstLeft->m_eColor = COLOR_BLK; + pstRoot = _pRightRotation(pvData, pstRoot, pstParent); + pstTree = pstRoot; + } + } + } + + pstTree->m_eColor = COLOR_BLK; + + return pstRoot; +} + +/************************************************************************************************* + description:Remove the execution index from RBTree + parameters: + pvData --addree memory + t --table + pstRoot --tree root + pstTree --tree node + return: + SHTree* + *************************************************************************************************/ +SHTree* _pDeleteTree(void *pvData, TABLE t, SHTree *pstRoot, SHTree *pstTree) +{ + size_t lData; + SHTree *pstChild = NULL, *pstParent = NULL, *pstNext = NULL; + + // If there is a left node or a right node, notice that no node defaults to NIL + // for right node processing + if(NODE_NULL == pstTree->m_lLeft || NODE_NULL == pstTree->m_lRight) + { + if(NODE_NULL == pstTree->m_lLeft) + pstNext = (SHTree *)pGetNode(pvData, pstTree->m_lRight); + else + pstNext = (SHTree *)pGetNode(pvData, pstTree->m_lLeft); + + // The child node points to the parent of the node to be deleted + pstNext->m_lParent = pstTree->m_lParent; + if(NODE_NULL == pstTree->m_lParent) + pstRoot = pstNext; + else + { + pstParent = (SHTree *)pGetNode(pvData, pstTree->m_lParent); + if(pstParent->m_lLeft == pstTree->m_lSePos) + pstParent->m_lLeft = pstNext->m_lSePos; + else + pstParent->m_lRight = pstNext->m_lSePos; + } + + // If you delete the red node, it does not affect the tree structure + if(pstTree->m_eColor == COLOR_RED) + return pReleaseNode(pvData, t, pstRoot, pstTree, NULL); + + pstRoot = pReleaseNode(pvData, t, pstRoot, pstTree, &pstNext); + + return _pFixupDelete(pvData, pstRoot, pstNext); + } + + pstNext = (SHTree *)pGetNode(pvData, pstTree->m_lRight); + // Left and right children of deleted node D are not leaf nodes + while(NODE_NULL != pstNext->m_lLeft) + pstNext = (SHTree *)pGetNode(pvData, pstNext->m_lLeft); + + pstChild = (SHTree *)pGetNode(pvData, pstNext->m_lRight); + pstParent = (SHTree *)pGetNode(pvData, pstNext->m_lParent); + + pstChild->m_lParent = pstParent->m_lSePos; + if(pstNext->m_lSePos == pstParent->m_lLeft) + pstParent->m_lLeft = pstChild->m_lSePos; + else + pstParent->m_lRight = pstChild->m_lSePos; + + lData = pstTree->m_lData; + pstTree->m_lData = pstNext->m_lData; + pstNext->m_lData = lData; + memcpy(pstTree->m_szIdx, pstNext->m_szIdx, pstNext->m_lIdx); + + if(pstNext->m_eColor == COLOR_RED) + return pReleaseNode(pvData, t, pstRoot, pstNext, NULL); + + pstRoot = pReleaseNode(pvData, t, pstRoot, pstNext, &pstChild); + + return _pFixupDelete(pvData, pstRoot, pstChild); +} + +/************************************************************************************************* + description:Remove the query index from RBTree + parameters: + pvData --address memory + t --table + pstRoot --tree Root + pstTree --tree node + lOut + return: + SHTree* + *************************************************************************************************/ +SHTree* _pDeleteGroup(void *pvData, TABLE t, SHTree *pstRoot, SHTree *pstTree, long *plOut) +{ + size_t lData = 0; + SHTree *pstChild = NULL, *pstParent = NULL, *pstNext = NULL; + + // If there is a left node or a right node, notice that no node defaults to NIL + // for right node processing + if(NODE_NULL == pstTree->m_lLeft || NODE_NULL == pstTree->m_lRight) + { + if(NODE_NULL == pstTree->m_lLeft) + pstNext = (SHTree *)pGetNode(pvData, pstTree->m_lRight); + else + pstNext = (SHTree *)pGetNode(pvData, pstTree->m_lLeft); + + // The child node points to the parent of the node to be deleted + pstNext->m_lParent = pstTree->m_lParent; + if(NODE_NULL == pstTree->m_lParent) + pstRoot = pstNext; + else + { + pstParent = (SHTree *)pGetNode(pvData, pstTree->m_lParent); + if(pstParent->m_lLeft == pstTree->m_lSePos) + pstParent->m_lLeft = pstNext->m_lSePos; + else + pstParent->m_lRight = pstNext->m_lSePos; + } + + if(pstTree->m_eColor == COLOR_RED) + return pReleaseGroup(pvData, t, pstRoot, pstTree, NULL, plOut); + + pstRoot = pReleaseGroup(pvData, t, pstRoot, pstTree, &pstNext, plOut); + return _pFixupDelete(pvData, pstRoot, pstNext); + } + + pstNext = (SHTree *)pGetNode(pvData, pstTree->m_lRight); + while(NODE_NULL != pstNext->m_lLeft) + pstNext = (SHTree *)pGetNode(pvData, pstNext->m_lLeft); + + pstChild = (SHTree *)pGetNode(pvData, pstNext->m_lRight); + pstParent = (SHTree *)pGetNode(pvData, pstNext->m_lParent); + + pstChild->m_lParent = pstParent->m_lSePos; + if(pstNext->m_lSePos == pstParent->m_lLeft) + pstParent->m_lLeft = pstChild->m_lSePos; + else + pstParent->m_lRight = pstChild->m_lSePos; + + lData = pstTree->m_lData; + pstTree->m_lData = pstNext->m_lData; + pstNext->m_lData = lData; // set lData to the Release the node + memcpy(pstTree->m_szIdx, pstNext->m_szIdx, pstNext->m_lIdx); + ((SHList *)pGetNode(pvData, pstTree->m_lData))->m_lNode = pstTree->m_lSePos; + + if(pstNext->m_eColor == COLOR_RED) + return pReleaseGroup(pvData, t, pstRoot, pstNext, NULL, plOut); + + pstRoot = pReleaseGroup(pvData, t, pstRoot, pstNext, &pstChild, plOut); + + return _pFixupDelete(pvData, pstRoot, pstChild); +} + +/************************************************************************************************* + description:Remove the execution index from RBTree + parameters: + pstSavm --stvm handle + pstRoot --tree Root + psvIdx --index value + lIdx --value length + *plData --data offset + return: + SHTree* + *************************************************************************************************/ +SHTree* pDeleteTree(SATvm *pstSavm, SHTree *pstRoot, void *psvIdx, long lIdx, size_t *plData) +{ + SHTree *pstTree = NULL; + void *pvData = pGetAddr(pstSavm, pstSavm->tblName); + + if(NULL == (pstTree = pSearchTree(pvData, pstRoot, psvIdx, lIdx))) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return NULL; + } + + *plData = pstTree->m_lData; + + return _pDeleteTree(pvData, pstSavm->tblName, pstRoot, pstTree); +} + +/************************************************************************************************* + description:Remove the index from the hash table + parameters: + pstSavm --stvm handle + pvAddr --memory address + pstTree --tree node + lData --data offset + pvData --data truck + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lPurgedHash(SATvm *pstSavm, void *pvAddr, SHTree *pstTree, void *pvData) +{ + SHList *pstList = NULL; + SHTruck *pstTruck = NULL; + size_t lNext = 0, lOffset; + + pstList = (SHList *)pGetNode(pvAddr, pstTree->m_lData); + lOffset = lGetListOfs(pstSavm->tblName) + ((TblDef *)pvAddr)->m_lValid * sizeof(SHList); + for(;SELF_POS_UNUSE != pstList->m_lPos; pstList = (SHList *)pGetNode(pvAddr, lNext)) + { + lNext = pstList->m_lNext; + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + if(memcmp(pstTruck->m_pvData, pvData, pstSavm->lSize)) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + lOffset -= sizeof(SHList); + if(RC_SUCC != lReleaseList(pvAddr, pstSavm->tblName, pstTree, pstList, lOffset, &lNext)) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(SELF_POS_UNUSE == pstTree->m_lData) + pstTree->m_lSePos = SELF_POS_UNUSE; + + return RC_SUCC; + } + + return RC_FAIL; +} + +/************************************************************************************************* + description:Remove the execution index from RBTree + parameters: + pstSavm --stvm handle + pstRoot --tree Root + psvIdx --index value + lIdx --value length + pvData --data truck + plOut --lOffset + eType + return: + SHTree* + *************************************************************************************************/ +SHTree* _pRemoveGroup(SATvm *pstSavm, SHTree *pstRoot, void *psvIdx, long lIdx, void *pvData, + long *plOut, long eType) +{ + SHList *pstList = NULL; + SHTree *pstTree = NULL; + SHTruck *pstTruck = NULL; + size_t lNext = 0, lOffset; + void *pvAddr = pGetAddr(pstSavm, pstSavm->tblName); + + if(NULL == (pstTree = pSearchTree(pvAddr, pstRoot, psvIdx, lIdx))) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return NULL; + } + + if(SELF_POS_UNUSE == pstTree->m_lData) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return _pDeleteGroup(pvAddr, pstSavm->tblName, pstRoot, pstTree, plOut); + } + + pstList = (SHList *)pGetNode(pvAddr, pstTree->m_lData); + + lOffset = lGetListOfs(pstSavm->tblName) + ((TblDef *)pvAddr)->m_lValid * sizeof(SHList); + for(*plOut = 0; SELF_POS_UNUSE != pstList->m_lPos; pstList = (SHList *)pGetNode(pvAddr, lNext)) + { + lNext = pstList->m_lNext; + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + if(0 == eType) + { + if(memcmp(pvData, (void *)&pstList->m_lData, sizeof(pstList->m_lData))) + { + if(SELF_POS_UNUSE == lNext) break; + continue; + } + } + else + { + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pvData)) + { + if(SELF_POS_UNUSE == lNext) break; + continue; + } + } + + (*plOut) ++; + lOffset -= sizeof(SHList); + + // lNext may be tail node, just moved, here need to update lNext + if(RC_SUCC != lReleaseList(pvAddr, pstSavm->tblName, pstTree, pstList, lOffset, &lNext)) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return pstRoot; + } + + if(SELF_POS_UNUSE == lNext || 0 == eType) break; + } + + if(SELF_POS_UNUSE != pstTree->m_lData) + return pstRoot; + else + return _pDeleteGroup(pvAddr, pstSavm->tblName, pstRoot, pstTree, plOut); +} + +/************************************************************************************************* + description:Remove the execution index from RBTree by Offset + parameters: + pstSavm --stvm handle + pstRoot --tree Root + psvIdx --index value + lIdx --value length + pvData --data truck + plOut --lOffset + eType + return: + SHTree* + *************************************************************************************************/ +SHTree* pDeleteGroup(SATvm *pstSavm, SHTree *pstRoot, void *psvIdx, long lIdx, void *pvData, + long *plOut) +{ + return _pRemoveGroup(pstSavm, pstRoot, psvIdx, lIdx, pvData, plOut, 0); +} + +/************************************************************************************************* + description:Remove the index from RBTree + parameters: + pstSavm --stvm handle + pstRoot --tree Root + psvIdx --index value + lIdx --value length + pvData --data truck + plOut --lOffset + eType + return: + SHTree* + *************************************************************************************************/ +SHTree* pRemoveGroup(SATvm *pstSavm, SHTree *pstRoot, void *psvIdx, long lIdx, void *pvData, + long *plOut) +{ + return _pRemoveGroup(pstSavm, pstRoot, psvIdx, lIdx, pvData, plOut, 1); +} + +/************************************************************************************************* + description:Remove the corresponding data from Hash + parameters: + pstSavm --stvm handle + pvAddr --memory address + pstTree --tree node + t --table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long __lDeleteHash(SATvm *pstSavm, void *pvAddr, SHTree *pstTree, TABLE t) +{ + SHTree *pstRoot = NULL; + SHList *pstList = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + size_t lNext = 0, lOffset, lData = 0; + RWLock *prwLock = (RWLock *)pGetRWLock(pvAddr); + + pstSavm->m_lEType = EXE_PLAN_GRP; + if(RC_SUCC != pthread_rwlock_wrlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DOWR_ERR; + return RC_FAIL; + } + + pstList = (SHList *)pGetNode(pvAddr, pstTree->m_lData); + lOffset = lGetListOfs(t) + ((TblDef *)pvAddr)->m_lValid * sizeof(SHList); + for(pstSavm->m_lEffect = 0; SELF_POS_UNUSE != pstList->m_lPos; + pstList = (SHList *)pGetNode(pvAddr, lNext)) + { + lNext = pstList->m_lNext; + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + if(SELF_POS_UNUSE == pstList->m_lNext) break; + continue; + } + + if(HAVE_UNIQ_IDX(t)) + { + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetIdxNum(t), pGetTblIdx(t), pstTruck->m_pvData, szIdx)) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == (pstRoot = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lTreeRoot))) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + pstRoot = pDeleteTree(pstSavm, pstRoot, szIdx, lGetIdxLen(t), &lData); + if(!pstRoot || pstList->m_lData != lData) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + ((TblDef *)pvAddr)->m_lTreeRoot = pstRoot->m_lSePos; + } + + pstSavm->m_lEffect ++; + lOffset -= sizeof(SHList); + if(RC_SUCC != lReleaseList(pvAddr, t, pstTree, pstList, lOffset, &lNext)) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(SELF_POS_UNUSE == pstTree->m_lData) + pstTree->m_lSePos = SELF_POS_UNUSE; + + if(RC_SUCC != lRecordWork(pstSavm, pstTruck->m_pvData, OPERATE_DELETE)) + { + pthread_rwlock_unlock(prwLock); + return RC_FAIL; + } + + lReleaseTruck(pvAddr, t, pstTruck, TRUE); + ((TblDef *)pvAddr)->m_lValid --; + + if(SELF_POS_UNUSE == lNext) break; + if(FIRST_ROW & pstSavm->lFind) break; + } + + pthread_rwlock_unlock(prwLock); + + return RC_SUCC; +} + +/************************************************************************************************* + description:Delete Hash table points to the data + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lDeleteHash(SATvm *pstSavm, void *pvAddr, TABLE t) +{ + size_t lIdx; + SHTree *pstTree = NULL; + char szIdx[MAX_INDEX_LEN]; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetGrpNum(t), pGetTblGrp(t), pstSavm->pstVoid, szIdx)) + return RC_CONTU; + + lIdx = uGetHash(szIdx, lGetGrpLen(t)) % ((TblDef *)pvAddr)->m_lMaxRow; + pstTree = pvAddr + ((TblDef *)pvAddr)->m_lGroupRoot + lIdx * sizeof(SHTree); + if(NULL == pstTree || SELF_POS_UNUSE == pstTree->m_lData) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + return __lDeleteHash(pstSavm, pvAddr, pstTree, t); +} + +/************************************************************************************************* + description:For the unique index traversal of data deleted + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + psvIdx --index value + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long __lDeleteIndex(SATvm *pstSavm, void *pvAddr, TABLE t, void *psvIdx) +{ + long lRow = 0; + size_t lData, lIdx; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + SHTree *pstRoot = NULL, *pstTree = NULL; + RWLock *prwLock = (RWLock *)pGetRWLock(pvAddr); + + if(RC_SUCC != pthread_rwlock_wrlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DOWR_ERR; + return RC_FAIL; + } + + pstSavm->m_lEType = EXE_PLAN_IDX; + if(NULL == (pstRoot = pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lTreeRoot))) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == (pstTree = pSearchTree(pvAddr, pstRoot, psvIdx, lGetIdxLen(t)))) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + lData = pstTree->m_lData; + pstTruck = (PSHTruck)pGetNode(pvAddr, pstTree->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + if(NULL == (pstRoot = _pDeleteTree(pvAddr, pstSavm->tblName, pstRoot, pstTree))) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + ((TblDef *)pvAddr)->m_lTreeRoot = pstRoot->m_lSePos; + + if(HAVE_NORL_IDX(t)) + { + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetGrpNum(t), pGetTblGrp(t), pstTruck->m_pvData, szIdx)) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == (pstRoot = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lGroupRoot))) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == (pstRoot = pDeleteGroup(pstSavm, pstRoot, szIdx, lGetGrpLen(t), &lData, &lRow))) + { + pthread_rwlock_unlock(prwLock); + return RC_FAIL; + } + + if(1 != lRow) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + ((TblDef *)pvAddr)->m_lGroupRoot = pstRoot->m_lSePos; + } + else if(HAVE_HASH_IDX(t)) + { + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetGrpNum(t), pGetTblGrp(t), pstTruck->m_pvData, szIdx)) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + lIdx = uGetHash(szIdx, lGetGrpLen(t)) % ((TblDef *)pvAddr)->m_lMaxRow; + pstRoot = pvAddr + ((TblDef *)pvAddr)->m_lGroupRoot + lIdx * sizeof(SHTree); + if(NULL == pstRoot || SELF_POS_UNUSE == pstRoot->m_lData) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(RC_SUCC != _lPurgedHash(pstSavm, pvAddr, pstRoot, pstTruck->m_pvData)) + { + pthread_rwlock_unlock(prwLock); + return RC_FAIL; + } + } + + if(RC_SUCC != lRecordWork(pstSavm, pstTruck->m_pvData, OPERATE_DELETE)) + { + pthread_rwlock_unlock(prwLock); + return RC_FAIL; + } + + lReleaseTruck(pvAddr, t, pstTruck, TRUE); + pthread_rwlock_unlock(prwLock); + + pstSavm->m_lEffect = 1; + ((TblDef *)pvAddr)->m_lValid --; + + return RC_SUCC; +} + +/************************************************************************************************* + description:delete The unique index truck data + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lDeleteIndex(SATvm *pstSavm, void *pvAddr, TABLE t) +{ + char szIdx[MAX_INDEX_LEN]; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetIdxNum(t), pGetTblIdx(t), pstSavm->pstVoid, szIdx)) + return RC_CONTU; + + return __lDeleteIndex(pstSavm, pvAddr, t, (void *)szIdx); +} + +/************************************************************************************************* + description:Delete the data that matches conditions + parameters: + pstSavm --stvm handle + pvAddr --memory address + pstTree --tree node + t --table + psvIdx --index value + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long __lDeleteGroup(SATvm *pstSavm, void *pvAddr, TABLE t, void *psvIdx) +{ + SHList *pstList = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + size_t lNext = 0, lOffset, lData = 0; + RWLock *prwLock = (RWLock *)pGetRWLock(pvAddr); + SHTree *pstRoot = NULL, *pstTree = NULL, *pstIRoot = NULL; + + pstSavm->m_lEType = EXE_PLAN_GRP; + if(RC_SUCC != pthread_rwlock_wrlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DOWR_ERR; + return RC_FAIL; + } + + if(NULL == (pstRoot = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lGroupRoot))) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == (pstTree = pSearchTree(pvAddr, pstRoot, psvIdx, lGetGrpLen(t)))) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + if(SELF_POS_UNUSE == pstTree->m_lData) + { + pstRoot = _pDeleteGroup(pvAddr, t, pstRoot, pstTree, &pstSavm->m_lEffect); + ((TblDef *)pvAddr)->m_lGroupRoot = pstRoot->m_lSePos; + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_SUCC; + } + + pstList = (SHList *)pGetNode(pvAddr, pstTree->m_lData); + lOffset = lGetListOfs(t) + ((TblDef *)pvAddr)->m_lValid * sizeof(SHList); + for(pstSavm->m_lEffect = 0; SELF_POS_UNUSE != pstList->m_lPos; + pstList = (SHList *)pGetNode(pvAddr, lNext)) + { + lNext = pstList->m_lNext; + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + if(SELF_POS_UNUSE == pstList->m_lNext) break; + continue; + } + + if(HAVE_UNIQ_IDX(t)) + { + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetIdxNum(t), pGetTblIdx(t), pstTruck->m_pvData, szIdx)) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == (pstIRoot = pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lTreeRoot))) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + pstIRoot = pDeleteTree(pstSavm, pstIRoot, szIdx, lGetIdxLen(t), &lData); + if(!pstIRoot || pstList->m_lData != lData) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + ((TblDef *)pvAddr)->m_lTreeRoot = pstIRoot->m_lSePos; + } + + pstSavm->m_lEffect ++; + lOffset -= sizeof(SHList); + if(RC_SUCC != lReleaseList(pvAddr, t, pstTree, pstList, lOffset, &lNext)) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(RC_SUCC != lRecordWork(pstSavm, pstTruck->m_pvData, OPERATE_DELETE)) + { + pthread_rwlock_unlock(prwLock); + return RC_FAIL; + } + + lReleaseTruck(pvAddr, t, pstTruck, TRUE); + ((TblDef *)pvAddr)->m_lValid --; + + if(SELF_POS_UNUSE == lNext) break; + if(FIRST_ROW & pstSavm->lFind) break; + } + + if(SELF_POS_UNUSE == pstTree->m_lData) + { + pstRoot = _pDeleteGroup(pvAddr, pstSavm->tblName, pstRoot, pstTree, &pstSavm->m_lEffect); + ((TblDef *)pvAddr)->m_lGroupRoot = pstRoot->m_lSePos; + } + + pthread_rwlock_unlock(prwLock); + + return RC_SUCC; +} + +/************************************************************************************************* + description:Delete the data that matches conditions + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lDeleteGroup(SATvm *pstSavm, void *pvAddr, TABLE t) +{ + char szIdx[MAX_INDEX_LEN]; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetGrpNum(t), pGetTblGrp(t), pstSavm->pstVoid, szIdx)) + return RC_CONTU; + + return __lDeleteGroup(pstSavm, pvAddr, t, (void *)szIdx); +} + +/************************************************************************************************* + description:Delete the truck that matches conditions + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lDeleteTruck(SATvm *pstSavm, void *pvAddr, TABLE t) +{ + bool bIsIdx = FALSE; + SHTree *pstRoot = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + RWLock *prwLock = (RWLock *)pGetRWLock(pvAddr); + size_t lData = 0, lOffset = lGetTblData(t), lIdx; + long lRow, lValid = ((TblDef *)pvAddr)->m_lValid; + + if(HAVE_INDEX(t)) bIsIdx = TRUE; + + if(RC_SUCC != pthread_rwlock_wrlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DOWR_ERR; + return RC_FAIL; + } + + pstSavm->m_lEType = EXE_PLAN_ALL; + for(lRow = 0, pstSavm->m_lEffect = 0, pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset); + (lRow < lValid) && (lOffset < lGetTableSize(t)); pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset)) + { + if(IS_TRUCK_NULL(pstTruck)) + { + lOffset += lGetRowTruck(t); + continue; + } + + ++ lRow; + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + lOffset += lGetRowTruck(t); + continue; + } + + pstSavm->m_lEffect ++; + if(HAVE_UNIQ_IDX(t)) + { + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetIdxNum(t), pGetTblIdx(t), pstTruck->m_pvData, szIdx)) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == (pstRoot = pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lTreeRoot))) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + pstRoot = pDeleteTree(pstSavm, pstRoot, szIdx, lGetIdxLen(t), &lData); + if(!pstRoot || lOffset != lData) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + ((TblDef *)pvAddr)->m_lTreeRoot = pstRoot->m_lSePos; + } + + if(HAVE_NORL_IDX(t)) + { + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetGrpNum(t), pGetTblGrp(t), pstTruck->m_pvData, szIdx)) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == (pstRoot = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lGroupRoot))) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + pstRoot = pDeleteGroup(pstSavm, pstRoot, szIdx, lGetGrpLen(t), &lOffset, (long *)&lData); + if(!pstRoot) return RC_FAIL; + if(1 != lData) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + ((TblDef *)pvAddr)->m_lGroupRoot = pstRoot->m_lSePos; + } + else if(HAVE_HASH_IDX(t)) + { + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetGrpNum(t), pGetTblGrp(t), pstTruck->m_pvData, szIdx)) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + lIdx = uGetHash(szIdx, lGetGrpLen(t)) % ((TblDef *)pvAddr)->m_lMaxRow; + pstRoot = pvAddr + ((TblDef *)pvAddr)->m_lGroupRoot + lIdx * sizeof(SHTree); + if(NULL == pstRoot || SELF_POS_UNUSE == pstRoot->m_lData) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(RC_SUCC != _lPurgedHash(pstSavm, pvAddr, pstRoot, pstTruck->m_pvData)) + { + pthread_rwlock_unlock(prwLock); + return RC_FAIL; + } + } + + if(bIsIdx) lOffset += lGetRowTruck(t); + + if(RC_SUCC != lRecordWork(pstSavm, pstTruck->m_pvData, OPERATE_DELETE)) + { + pthread_rwlock_unlock(prwLock); + return RC_FAIL; + } + + lReleaseTruck(pvAddr, t, pstTruck, bIsIdx); + ((TblDef *)pvAddr)->m_lValid --; + if(FIRST_ROW & pstSavm->lFind) break; + } + pthread_rwlock_unlock(prwLock); + + if(0 == pstSavm->m_lEffect) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:API - delete + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lDelete(SATvm *pstSavm) +{ + long lRet; + RunTime *pstRun = NULL; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + if(NULL == (pstRun = (RunTime *)pInitMemTable(pstSavm, pstSavm->tblName))) + return RC_FAIL; + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + Tremohold(pstSavm, pstRun); + return _lDeleteByRt(pstSavm); + } + + if(((TblDef *)pstRun->m_pvAddr)->m_lValid <= 0) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + vTblDisconnect(pstSavm, pstSavm->tblName); + return RC_FAIL; + } + + if(!pstSavm->pstVoid) + { + lRet = _lDeleteTruck(pstSavm, pstRun->m_pvAddr, pstSavm->tblName); + vTblDisconnect(pstSavm, pstSavm->tblName); + return lRet; + } + + if(HAVE_UNIQ_IDX(pstSavm->tblName)) + { + lRet = _lDeleteIndex(pstSavm, pstRun->m_pvAddr, pstSavm->tblName); + if(RC_CONTU != lRet) + { + vTblDisconnect(pstSavm, pstSavm->tblName); + return lRet; + } + } + + if(HAVE_NORL_IDX(pstSavm->tblName)) + { + lRet = _lDeleteGroup(pstSavm, pstRun->m_pvAddr, pstSavm->tblName); + if(RC_CONTU != lRet) + { + vTblDisconnect(pstSavm, pstSavm->tblName); + return lRet; + } + } + else if(HAVE_HASH_IDX(pstSavm->tblName)) + { + lRet = _lDeleteHash(pstSavm, pstRun->m_pvAddr, pstSavm->tblName); + if(RC_CONTU != lRet) + { + vTblDisconnect(pstSavm, pstSavm->tblName); + return lRet; + } + } + + lRet = _lDeleteTruck(pstSavm, pstRun->m_pvAddr, pstSavm->tblName); + vTblDisconnect(pstSavm, pstSavm->tblName); + return lRet; +} + +/************************************************************************************************* + description:Statistical compliance record + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + plCount --index value + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lCountIndex(SATvm *pstSavm, void *pvAddr, TABLE t, size_t *plCount) +{ + SHTree *pstTree = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetIdxNum(t), pGetTblIdx(t), pstSavm->pstVoid, szIdx)) + return RC_CONTU; + + pstSavm->m_lEType = EXE_PLAN_IDX; + if(NULL == (pstTree = pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lTreeRoot))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == (pstTree = pSearchTree(pvAddr, pstTree, szIdx, lGetIdxLen(t)))) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + pstTruck = (PSHTruck)pGetNode(pvAddr, pstTree->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + pstSavm->m_lEffect = *plCount = 1; + return RC_SUCC; +} + +/************************************************************************************************* + description:The statistics matches the index record + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + plCount + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lCountGroup(SATvm *pstSavm, void *pvAddr, TABLE t, size_t *plCount) +{ + size_t lNext; + SHList *pstList = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + SHTree *pstRoot = NULL, *pstTree = NULL; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetGrpNum(t), pGetTblGrp(t), pstSavm->pstVoid, szIdx)) + return RC_CONTU; + + *plCount = 0; + if(NULL == (pstRoot = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lGroupRoot))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == (pstTree = pSearchTree(pvAddr, pstRoot, szIdx, lGetGrpLen(t)))) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_SUCC; + } + + pstList = (SHList *)pGetNode(pvAddr, pstTree->m_lData); + if(lGetGrpNum(t) == pstSavm->stCond.uFldcmp) + { + *plCount = lGetListCount(pvAddr, pstList); + pstSavm->m_lEffect = *plCount; + return RC_SUCC; + } + + for(; SELF_POS_UNUSE != pstList->m_lPos; pstList = (SHList *)pGetNode(pvAddr, lNext)) + { + lNext = pstList->m_lNext; + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + if(SELF_POS_UNUSE == pstList->m_lNext) break; + continue; + } + + (*plCount) ++; + if(SELF_POS_UNUSE == lNext) break; + } + + if(0 == (pstSavm->m_lEffect = *plCount)) + pstSavm->m_lErrno = NO_DATA_FOUND; + + return RC_SUCC; +} + +/************************************************************************************************* + description:The statistics matches the hash record + parameters: + pstSavm --stvm handle + pvAddr --memory address + pstTree --tree node + t --table + psvIdx --index value + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lCountHash(SATvm *pstSavm, void *pvAddr, TABLE t, size_t *plCount) +{ + size_t lIdx, lNext; + SHList *pstList = NULL; + SHTruck *pstTruck = NULL; + SHTree *pstTree = NULL; + char szIdx[MAX_INDEX_LEN]; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetGrpNum(t), pGetTblGrp(t), pstSavm->pstVoid, szIdx)) + return RC_CONTU; + + *plCount = 0; + lIdx = uGetHash(szIdx, lGetGrpLen(t)) % ((TblDef *)pvAddr)->m_lMaxRow; + pstTree = pvAddr + ((TblDef *)pvAddr)->m_lGroupRoot + lIdx * sizeof(SHTree); + if(NULL == pstTree || SELF_POS_UNUSE == pstTree->m_lData) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_SUCC; + } + + for(pstList = (SHList *)pGetNode(pvAddr, pstTree->m_lData); + SELF_POS_UNUSE != pstList->m_lPos; pstList = (SHList *)pGetNode(pvAddr, lNext)) + { + lNext = pstList->m_lNext; + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + if(SELF_POS_UNUSE == pstList->m_lNext) break; + continue; + } + + (*plCount) ++; + if(SELF_POS_UNUSE == lNext) break; + } + + if(0 == (pstSavm->m_lEffect = *plCount)) + pstSavm->m_lErrno = NO_DATA_FOUND; + + return RC_SUCC; +} + +/************************************************************************************************* + description:The statistics matches the truck record + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + plCount --count + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lCountTruck(SATvm *pstSavm, void *pvAddr, TABLE t, size_t *plCount) +{ + SHTruck *pstTruck = NULL; + FdCond *pstCond = &pstSavm->stCond; + size_t lRow = 0, lOffset = lGetTblData(t); + + for(*plCount = 0; (lRow < ((TblDef *)pvAddr)->m_lValid) && (lOffset < lGetTableSize(t)); + lOffset += lGetRowTruck(t)) + { + pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset); + if(IS_TRUCK_NULL(pstTruck)) + continue; + + ++ lRow; + if(RC_MISMA == lFeildMatch(pstCond, pstTruck->m_pvData, pstSavm->pstVoid)) + continue; + + (*plCount) ++; + } + + if(0 == (pstSavm->m_lEffect = *plCount)) + pstSavm->m_lErrno = NO_DATA_FOUND; + + return RC_SUCC; +} + +/************************************************************************************************* + description:API - lCount + parameters: + pstSavm --stvm handle + plCount --count + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lCount(SATvm *pstSavm, size_t *plCount) +{ + long lRet; + RunTime *pstRun = NULL; + RWLock *prwLock = NULL; + + if(!pstSavm || !plCount) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + if(NULL == (pstRun = (RunTime *)pInitMemTable(pstSavm, pstSavm->tblName))) + return RC_FAIL; + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + Tremohold(pstSavm, pstRun); + return _lCountByRt(pstSavm, plCount); + } + + if(((TblDef *)pstRun->m_pvAddr)->m_lValid <= 0) + { + *plCount = 0; + vTblDisconnect(pstSavm, pstSavm->tblName); + return RC_SUCC; + } + + if(!pstSavm->pstVoid || pstSavm->stCond.uFldcmp == 0) + { + *plCount = ((TblDef *)pstRun->m_pvAddr)->m_lValid; + pstSavm->m_lEffect = *plCount; + vTblDisconnect(pstSavm, pstSavm->tblName); + return RC_SUCC; + } + + if(HAVE_UNIQ_IDX(pstSavm->tblName)) + { + lRet = _lCountIndex(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, plCount); + if(RC_CONTU != lRet) + { + pstSavm->m_lEType = EXE_PLAN_IDX; + vTblDisconnect(pstSavm, pstSavm->tblName); + return lRet; + } + } + + if(HAVE_NORL_IDX(pstSavm->tblName)) + { + lRet = _lCountGroup(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, plCount); + if(RC_CONTU != lRet) + { + pstSavm->m_lEType = EXE_PLAN_GRP; + vTblDisconnect(pstSavm, pstSavm->tblName); + return lRet; + } + } + else if(HAVE_HASH_IDX(pstSavm->tblName)) + { + lRet = _lCountHash(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, plCount); + if(RC_CONTU != lRet) + { + pstSavm->m_lEType = EXE_PLAN_GRP; + vTblDisconnect(pstSavm, pstSavm->tblName); + return lRet; + } + } + + pstSavm->m_lEType = EXE_PLAN_ALL; + lRet = _lCountTruck(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, plCount); + vTblDisconnect(pstSavm, pstSavm->tblName); + return lRet; +} + +/************************************************************************************************* + description:Rebuild unique index + parameters: + pstSavm --stvm handle + pstRoot --tree root + psvIdx --index value + lIdx --index length + lRow --rows + lData --data offset + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +SHTree* pRebuildTree(SATvm *pstSavm, SHTree *pstRoot, void *psvIdx, long lIdx, long lRow, size_t lData) +{ + int nRet = 0; + size_t lOffset, lPos = 0, lNext = 0; + void *pvData = NULL, *pvAddr = pGetAddr(pstSavm, pstSavm->tblName); + SHTree *pstNode = NULL, *pstCur = NULL, *pstNext = NULL, *pstTree = pstRoot; + + while(SELF_POS_UNUSE != pstTree->m_lSePos && NODE_NULL != pstTree->m_lSePos) + { + pstNode = pstTree; + nRet = memcmp(pstTree->m_szIdx, psvIdx, lIdx); + if(0 < nRet) + { + if(NODE_NULL == pstTree->m_lLeft) + break; + pstTree = (SHTree *)pGetNode(pvAddr, pstTree->m_lLeft); + } + else if(0 > nRet) + { + if(NODE_NULL == pstTree->m_lRight) + break; + pstTree = (SHTree *)pGetNode(pvAddr, pstTree->m_lRight); + } + else + { + pstSavm->m_lErrno = UNIQ_IDX_REPT; + return NULL; + } + } + + lOffset = sizeof(SHTree) * lRow + lGetIdxPos(pstSavm->tblName); + if(NULL == (pstCur = pCreateNode(pvAddr, pstSavm->tblName, lOffset))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return NULL; + } + + lPos = pstCur->m_lData; + pstCur->m_lIdx = lIdx; + pstCur->m_lSePos = lOffset; + pstCur->m_lData = lData; + pstCur->m_lParent = NODE_NULL; + memcpy(pstCur->m_szIdx, psvIdx, pstCur->m_lIdx); + pstCur->m_lLeft = pstCur->m_lRight = NODE_NULL; + + if(lData != lPos) + { + lNext = (lData - lGetTblData(pstSavm->tblName)) / lGetRowTruck(pstSavm->tblName); + pstNext = (SHTree *)pGetNode(pvAddr, lNext * sizeof(SHTree) + lGetIdxPos(pstSavm->tblName)); + pstNext->m_lData = lPos; + } + + if(pstNode != NULL) + { + pstCur->m_eColor = COLOR_RED; + pstCur->m_lParent = pstNode->m_lSePos; + if(0 < memcmp(pstNode->m_szIdx, pstCur->m_szIdx, pstCur->m_lIdx)) + pstNode->m_lLeft = pstCur->m_lSePos; + else + pstNode->m_lRight = pstCur->m_lSePos; + } + else + { + pstRoot = pstCur; + pstCur->m_eColor = COLOR_BLK; + return pstRoot; + } + + return _pFixupInsert(pvAddr, pstRoot, pstCur); +} + +/************************************************************************************************* + description:Rebuild the index node + parameters: + pvAddr --memory address + t --table + pstGroup --group node + lGroup --group offset + lRow --rows + lData --data offset + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +SHTree* _pRebuildGroup(void *pvAddr, TABLE t, SHTree *pstGroup, long lGroup, long lRow, size_t lData) +{ + size_t lOffset = 0, lPos = 0, lNext = 0; + SHList *pstList = NULL, *pstNode = NULL, *pstNext = NULL; + + if(!pstGroup) pstGroup = (SHTree *)(pvAddr + lGroup); + lOffset = lGetListOfs(t) + sizeof(SHList) * lRow; + pstList = (SHList *)pGetNode(pvAddr, lOffset); + pstList->m_lPos = lOffset; + lPos = pstList->m_lData; + pstList->m_lData= lData; + + if(lData != lPos) + { + lNext = (lData - lGetTblData(t)) / lGetRowTruck(t); + pstNext = (SHList *)pGetNode(pvAddr, lNext * sizeof(SHList) + lGetListOfs(t)); + pstNext->m_lData = lPos; + } + + if(pstGroup->m_lData == SELF_POS_UNUSE) + { + pstList->m_lNode = lGroup; + pstGroup->m_lData = pstList->m_lPos; + } + else + { + pstNode = (SHList *)pGetNode(pvAddr, pstGroup->m_lData); + + pstList->m_lNext = pstNode->m_lNext; + pstList->m_lLast = pstNode->m_lPos; + if(SELF_POS_UNUSE != pstNode->m_lNext) + ((SHList *)pGetNode(pvAddr, pstNode->m_lNext))->m_lLast = pstList->m_lPos; + pstNode->m_lNext = pstList->m_lPos; + } + + return pstGroup; +} + +/************************************************************************************************* + description:Rebuild the hash index node + parameters: + pstSavm --stvm handle + t --table + pvAddr --Memory address + pstTree --tree node + lRow --rows + lData --data offset + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lRebuildHash(SATvm *pstSavm, TABLE t, void *pvAddr, SHTree *pstTree, size_t lRow, size_t lData) +{ + size_t lOffset = 0, lPos, lNext; + SHList *pstList = NULL, *pstNode = NULL, *pstNext = NULL; + + lOffset = lGetListOfs(t) + sizeof(SHList) * lRow; + pstList = (SHList *)pGetNode(pvAddr, lOffset); + pstList->m_lPos = lOffset; + lPos = pstList->m_lData; + pstList->m_lData= lData; + + if(lData != lPos) + { + lNext = (lData - lGetTblData(t)) / lGetRowTruck(t); + pstNext = (SHList *)pGetNode(pvAddr, lNext * sizeof(SHList) + lGetListOfs(t)); + pstNext->m_lData = lPos; + } + + if(SELF_POS_UNUSE == pstTree->m_lSePos || NODE_NULL == pstTree->m_lSePos) + { + pstTree->m_lSePos= (void *)pstTree - pvAddr; + pstList->m_lNode = pstTree->m_lSePos; + pstTree->m_lData = pstList->m_lPos; + } + else + { + pstNode = (SHList *)pGetNode(pvAddr, pstTree->m_lData); + + pstList->m_lNext = pstNode->m_lNext; + pstList->m_lLast = pstNode->m_lPos; + if(SELF_POS_UNUSE != pstNode->m_lNext) + ((SHList *)pGetNode(pvAddr, pstNode->m_lNext))->m_lLast = pstList->m_lPos; + pstNode->m_lNext = pstList->m_lPos; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Rebuild the index + parameters: + pstSavm --stvm handle + pstRoot --root node + psvIdx --index values + lRow --rows + lData --data offset + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +SHTree* pRebuildGroup(SATvm *pstSavm, SHTree *pstRoot, char *psvIdx, long lIdx, long lRow, size_t lData) +{ + int nRet; + size_t lOffset; + SHTruck *pstTruck = NULL; + void *pvAddr = pGetAddr(pstSavm, pstSavm->tblName); + SHTree *pstNode = NULL, *pstCur = NULL, *pstTree = pstRoot; + + while(SELF_POS_UNUSE != pstTree->m_lSePos && NODE_NULL != pstTree->m_lSePos) + { + pstNode = pstTree; + nRet = memcmp(pstTree->m_szIdx, psvIdx, lIdx); + if(0 < nRet) + { + if(NODE_NULL == pstTree->m_lLeft) + break; + pstTree = (SHTree *)pGetNode(pvAddr, pstTree->m_lLeft); + } + else if(0 > nRet) + { + if(NODE_NULL == pstTree->m_lRight) + break; + pstTree = (SHTree *)pGetNode(pvAddr, pstTree->m_lRight); + } + else + { + _pRebuildGroup(pvAddr, pstSavm->tblName, pstTree, 0, lRow, lData); + return pstRoot; + } + } + + lOffset = sizeof(SHTree) * ((TblDef *)pvAddr)->m_lGroup + lGetGrpPos(pstSavm->tblName); + if(NULL == (pstCur = _pRebuildGroup(pvAddr, pstSavm->tblName, NULL, lOffset, lRow, lData))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return pstRoot; + } + + pstCur->m_lIdx = lIdx; + pstCur->m_lSePos = lOffset; + pstCur->m_lParent = NODE_NULL; + memcpy(pstCur->m_szIdx, psvIdx, pstCur->m_lIdx); + pstCur->m_lLeft = pstCur->m_lRight = NODE_NULL; + ((TblDef *)pvAddr)->m_lGroup ++; + + if(pstNode != NULL) + { + pstCur->m_eColor = COLOR_RED; + pstCur->m_lParent = pstNode->m_lSePos; + if(0 < memcmp(pstNode->m_szIdx, pstCur->m_szIdx, pstCur->m_lIdx)) + pstNode->m_lLeft = pstCur->m_lSePos; + else + pstNode->m_lRight = pstCur->m_lSePos; + } + else + { + pstRoot = pstCur; + pstCur->m_eColor = COLOR_BLK; + return pstRoot; + } + + return _pFixupInsert(pvAddr, pstRoot, pstCur); +} + +/************************************************************************************************* + description:API - truncate (without transactions) + parameters: + pstSavm --stvm handle + t --table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTruncate(SATvm *pstSavm, TABLE t) +{ + void *pvData = NULL; + RunTime *pstRun = NULL; + RWLock *prwLock = NULL; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + if(NULL == (pstRun = (RunTime *)pInitHitTest(pstSavm, t))) + return RC_FAIL; + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + Tremohold(pstSavm, pstRun); + return _lTruncateByRt(pstSavm, t); + } + + prwLock = (RWLock *)pGetRWLock(pstRun->m_pvAddr); + if(RC_SUCC != pthread_rwlock_wrlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DOWR_ERR; + vTblDisconnect(pstSavm, pstSavm->tblName); + return RC_FAIL; + } + + if(RC_SUCC != lInitailTree(pstSavm, (void *)pGetNode(pstRun->m_pvAddr, lGetIdxPos(t)), t)) + { + pthread_rwlock_unlock(prwLock); + vTblDisconnect(pstSavm, t); + return RC_FAIL; + } + + if(RC_SUCC != lInitailGroup(pstSavm, (void *)pGetNode(pstRun->m_pvAddr, lGetGrpPos(t)), t)) + { + pthread_rwlock_unlock(prwLock); + vTblDisconnect(pstSavm, t); + return RC_FAIL; + } + + pstSavm->m_lEffect = ((TblDef *)pstRun->m_pvAddr)->m_lValid; + pvData = (void *)pGetNode(pstRun->m_pvAddr, lGetTblData(t)); + memset(pvData, 0, lGetTableSize(t) - lGetTblData(t)); + ((TblDef *)pstRun->m_pvAddr)->m_lGroup = 0; + ((TblDef *)pstRun->m_pvAddr)->m_lValid = 0; + + pthread_rwlock_unlock(prwLock); + vTblDisconnect(pstSavm, t); + + return RC_SUCC; +} + +/************************************************************************************************* + description:Index reconstruction based on data area data + parameters: + pstSavm --stvm handle + pvAddr --memory address + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lRebuildIndex(SATvm *pstSavm, void *pvAddr) +{ + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + TABLE t = pstSavm->tblName; + SHTree *pstIRoot = NULL, *pstGRoot = NULL; + size_t lRow = 0, lOffset = lGetTblData(t), lIdx; + + if(RC_SUCC != lInitailTree(pstSavm, (void *)pGetNode(pvAddr, lGetIdxPos(t)), t)) + return RC_FAIL; + + if(RC_SUCC != lInitailGroup(pstSavm, (void *)pGetNode(pvAddr, lGetGrpPos(t)), t)) + return RC_FAIL; + + ((TblDef *)pvAddr)->m_lGroup = 0; + ((TblDef *)pvAddr)->m_lGroupRoot = ((TblDef *)pvAddr)->m_lGroupPos; + pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset); + for(lRow = 0; (lRow < ((TblDef *)pvAddr)->m_lValid) && (lOffset < lGetTableSize(t)); + lOffset += lGetRowTruck(t), pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset)) + { + if(IS_TRUCK_NULL(pstTruck)) + continue; + + if(HAVE_UNIQ_IDX(t)) + { + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetIdxNum(t), pGetTblIdx(t), pstTruck->m_pvData, szIdx)) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + pstIRoot = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lTreeRoot); + pstIRoot = pRebuildTree(pstSavm, pstIRoot, szIdx, lGetIdxLen(t), lRow, lOffset); + if(!pstIRoot) return RC_FAIL; + + ((TblDef *)pvAddr)->m_lTreeRoot = pstIRoot->m_lSePos; + } + + if(HAVE_NORL_IDX(t)) + { + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetGrpNum(t), pGetTblGrp(t), pstTruck->m_pvData, szIdx)) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + pstGRoot = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lGroupRoot); + pstGRoot = pRebuildGroup(pstSavm, pstGRoot, szIdx, lGetGrpLen(t), lRow, lOffset); + if(!pstGRoot) return RC_FAIL; + + ((TblDef *)pvAddr)->m_lGroupRoot = pstGRoot->m_lSePos; + } + else if(HAVE_HASH_IDX(t)) + { + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetGrpNum(t), pGetTblGrp(t), pstTruck->m_pvData, szIdx)) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + lIdx = uGetHash(szIdx, lGetGrpLen(t)) % ((TblDef *)pvAddr)->m_lMaxRow; + pstGRoot = pvAddr + ((TblDef *)pvAddr)->m_lGroupPos + lIdx * sizeof(SHTree); + if(NULL == pstGRoot) return RC_FAIL; + + if(RC_SUCC != lRebuildHash(pstSavm, t, pvAddr, pstGRoot, lRow, lOffset)) + return RC_FAIL; + } + + lRow ++; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:The index rebuild + parameters: + pstSavm --stvm handle + t --table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lRebuildIndex(SATvm *pstSavm, TABLE t) +{ + long lRet; + RunTime *pstRun = NULL; + RWLock *prwLock = NULL; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + if(RC_SUCC != lInitSATvm(pstSavm, t)) + return RC_FAIL; + + if(NULL == (pstRun = (RunTime *)pInitHitTest(pstSavm, pstSavm->tblName))) + return RC_FAIL; + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + pstSavm->m_lErrno = RMT_NOT_SUPPT; + return RC_FAIL; + } + + if(!HAVE_INDEX(pstSavm->tblName)) + { + vTblDisconnect(pstSavm, pstSavm->tblName); + return RC_SUCC; + } + + prwLock = (RWLock *)pGetRWLock(pstRun->m_pvAddr); + if(RC_SUCC != pthread_rwlock_wrlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DOWR_ERR; + vTblDisconnect(pstSavm, pstSavm->tblName); + return RC_FAIL; + } + + pstSavm->lSize = lGetRowSize(t); + lRet = _lRebuildIndex(pstSavm, pstRun->m_pvAddr); + pthread_rwlock_unlock(prwLock); + vTblDisconnect(pstSavm, pstSavm->tblName); + + return lRet; +} + +/************************************************************************************************* + description:Select the table data according to the hash + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + psvOut --result data + plData --offset + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lSelectHash(SATvm *pstSavm, void *pvAddr, TABLE t, void *psvOut, size_t *plData) +{ + size_t lData, lIdx; + SHTree *pstTree = NULL; + SHList *pstList = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN], *pvData = NULL; + RWLock *prwLock = (RWLock *)pGetRWLock(pvAddr); + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetGrpNum(t), pGetTblGrp(t), pstSavm->pstVoid, szIdx)) + return RC_CONTU; + + lIdx = uGetHash(szIdx, lGetGrpLen(t)) % ((TblDef *)pvAddr)->m_lMaxRow; + pstTree = pvAddr + ((TblDef *)pvAddr)->m_lGroupRoot + lIdx * sizeof(SHTree); + if(NULL == pstTree || SELF_POS_UNUSE == pstTree->m_lData) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + if(RC_SUCC != pthread_rwlock_rdlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DORD_ERR; + return RC_FAIL; + } + + pstList = (SHList *)pGetNode(pvAddr, pstTree->m_lData); + for(pstSavm->m_lEType = EXE_PLAN_GRP; SELF_POS_UNUSE != pstList->m_lPos; + pstList = (SHList *)pGetNode(pvAddr, pstList->m_lNext)) + { + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + if(RC_MATCH == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + if(1 < (++ pstSavm->m_lEffect)) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = MORE_ROWS_SEL; + return RC_FAIL; + } + + *plData = pstList->m_lData; + pvData = pstTruck->m_pvData; + if(FIRST_ROW & pstSavm->lFind) break; + } + + if(SELF_POS_UNUSE == pstList->m_lNext) break; + } + + if(0 == pstSavm->m_lEffect) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + memcpy(psvOut, pvData, lGetRowSize(pstSavm->tblName)); + pthread_rwlock_unlock(prwLock); + pstTruck->m_lTimes ++; + return RC_SUCC; +} + +/************************************************************************************************* + description:Select the table data according to the index + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + psvOut --result data + plData --offset + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lSelectGroup(SATvm *pstSavm, void *pvAddr, TABLE t, void *psvOut, size_t *plData) +{ + void *pvData = NULL; + SHList *pstList = NULL; + SHTree *pstTree = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + RWLock *prwLock = (RWLock *)pGetRWLock(pvAddr); + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetGrpNum(t), pGetTblGrp(t), pstSavm->pstVoid, szIdx)) + return RC_CONTU; + + if(RC_SUCC != pthread_rwlock_rdlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DORD_ERR; + return RC_FAIL; + } + + if(NULL == (pstTree = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lGroupRoot))) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == (pstList = pSearchGroup(pvAddr, pstTree, szIdx, lGetGrpLen(t)))) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_CONTU; + } + + for(pstSavm->m_lEType = EXE_PLAN_GRP; SELF_POS_UNUSE != pstList->m_lPos; + pstList = (SHList *)pGetNode(pvAddr, pstList->m_lNext)) + { + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + if(RC_MATCH == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + if(1 < (++ pstSavm->m_lEffect)) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = MORE_ROWS_SEL; + return RC_FAIL; + } + + *plData = pstList->m_lData; + pvData = pstTruck->m_pvData; + if(FIRST_ROW & pstSavm->lFind) break; + } + + if(SELF_POS_UNUSE == pstList->m_lNext) break; + } + + if(0 == pstSavm->m_lEffect) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + memcpy(psvOut, pvData, lGetRowSize(pstSavm->tblName)); + pthread_rwlock_unlock(prwLock); + pstTruck->m_lTimes ++; + + return RC_SUCC; +} + +/************************************************************************************************* + description:Select the table data according to the truck + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + psvOut --result data + plData --offset + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lSelectTruck(SATvm *pstSavm, void *pvAddr, TABLE t, void *psvOut, size_t *plData) +{ + void *pvData = NULL; + SHTruck *pstTruck = NULL; + size_t lRow = 0, lOffset = lGetTblData(t); + RWLock *prwLock = (RWLock *)pGetRWLock(pvAddr); + + if(RC_SUCC != pthread_rwlock_rdlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DORD_ERR; + return RC_FAIL; + } + + pstSavm->m_lEType = EXE_PLAN_ALL; + pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset); + for(lRow = 0; (lRow < ((TblDef *)pvAddr)->m_lValid) && (lOffset < lGetTableSize(t)); + pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset)) + { + if(IS_TRUCK_NULL(pstTruck)) + { + lOffset += lGetRowTruck(t); + continue; + } + + lRow ++; + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + lOffset += lGetRowTruck(t); + continue; + } + + if(1 < (++ pstSavm->m_lEffect)) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = MORE_ROWS_SEL; + return RC_FAIL; + } + + *plData = lOffset; + lOffset+= lGetRowTruck(t); + pvData = pstTruck->m_pvData; + if(FIRST_ROW & pstSavm->lFind) break; + } + + if(0 == pstSavm->m_lEffect) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + memcpy(psvOut, pvData, lGetRowSize(pstSavm->tblName)); + pthread_rwlock_unlock(prwLock); + pstTruck->m_lTimes ++; + return RC_SUCC; +} + +/************************************************************************************************* + description:Select the table data according to the Unique index + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + psvOut --result data + plData --offset + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lSelectIndex(SATvm *pstSavm, void *pvAddr, TABLE t, void *psvOut, size_t *plData) +{ + SHTree *pstTree = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + RWLock *prwLock = (RWLock *)pGetRWLock(pvAddr); + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetIdxNum(t), pGetTblIdx(t), pstSavm->pstVoid, szIdx)) + return RC_CONTU; + + if(RC_SUCC != pthread_rwlock_rdlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DORD_ERR; + return RC_FAIL; + } + + pstSavm->m_lEType = EXE_PLAN_IDX; + if(NULL == (pstTree = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lTreeRoot))) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + pstTree = (SHTree *)pSearchTree(pvAddr, pstTree, szIdx, lGetIdxLen(pstSavm->tblName)); + if(!pstTree) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + pstTruck = (PSHTruck)pGetNode(pvAddr, pstTree->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + memcpy(psvOut, pstTruck->m_pvData, lGetRowSize(pstSavm->tblName)); + pthread_rwlock_unlock(prwLock); + pstTruck->m_lTimes ++; + pstSavm->m_lEffect = 1; + *plData = pstTree->m_lData; + + return RC_SUCC; +} + +/************************************************************************************************* + description:Group the table data according to the index + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + plData --offset + ppsvOut --result data list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lGroupIndex(SATvm *pstSavm, void *pvAddr, TABLE t, size_t *plOut, void **ppsvOut) +{ + SHTree *pstTree = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetIdxNum(t), pGetTblIdx(t), pstSavm->pstVoid, szIdx)) + return RC_CONTU; + + if(NULL == (pstTree = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lTreeRoot))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + pstTree = (SHTree *)pSearchTree(pvAddr, pstTree, szIdx, lGetIdxLen(pstSavm->tblName)); + if(!pstTree) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + pstTruck = (PSHTruck)pGetNode(pvAddr, pstTree->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + *plOut = 0; + return lInsertLstgrp(pstSavm, &pstSavm->stUpdt, pstTruck->m_pvData, t, plOut, ppsvOut); +} + +/************************************************************************************************* + description:Group the group tree + parameters: + pstSavm --stvm handle + pvAddr --memory address + pstree --tree node + plData --offset + ppsvOut --result data list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lGroupTree(SATvm *pstSavm, void *pvAddr, SHTree *pstTree, FdCond *pstRrp, size_t *plOut, + void **ppsvOut) +{ + size_t lCount; + SHList *pstList = NULL; + SHTruck *pstTruck = NULL; + + if(SELF_POS_UNUSE == pstTree->m_lSePos || NODE_NULL == pstTree->m_lSePos) + return RC_SUCC; + + pstList = (SHList *)pGetNode(pvAddr, pstTree->m_lData); + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + lCount = lGetListCount(pvAddr, pstList); + + if(!bRepeatLstgrp(pstRrp, pstTruck->m_pvData, pstSavm->tblName, *plOut, *ppsvOut)) + { + if(RC_SUCC != lInsertLstgrp(pstSavm, &pstSavm->stUpdt, pstTruck->m_pvData, + pstSavm->tblName, plOut, ppsvOut)) + return RC_FAIL; + } + + if(RC_SUCC != _lGroupTree(pstSavm, pvAddr, (SHTree *)pGetNode(pvAddr, pstTree->m_lLeft), + pstRrp, plOut, ppsvOut)) + return RC_FAIL; + + return _lGroupTree(pstSavm, pvAddr, (SHTree *)pGetNode(pvAddr, pstTree->m_lRight), pstRrp, + plOut, ppsvOut); +} + +/************************************************************************************************* + description:Group the table data according to the group tree + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + plData --offset + ppsvOut --result data list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lGroupGroup(SATvm *pstSavm, void *pvAddr, TABLE t, size_t *plOut, void **ppsvOut) +{ + SHList *pstList = NULL; + SHTree *pstTree = NULL; + SHTruck *pstTruck = NULL; + FdCond *pstRrp = &pstSavm->stUpdt; + char *pszIdx, szIdx[MAX_INDEX_LEN]; + + if(NULL == (pstTree = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lGroupRoot))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(bIsGroupFld(t, pstRrp) && NULL == pstSavm->pstVoid) + return _lGroupTree(pstSavm, pvAddr, pstTree, pstRrp, plOut, ppsvOut); + + memset(szIdx, 0, sizeof(szIdx)); + pszIdx = pGetIndex(&pstSavm->stCond, lGetGrpNum(t), pGetTblGrp(t), pstSavm->pstVoid, szIdx); + if(!pszIdx) return RC_CONTU; + + if(NULL == (pstList = pSearchGroup(pvAddr, pstTree, szIdx, lGetGrpLen(t)))) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_CONTU; + } + + for(*plOut = 0; SELF_POS_UNUSE != pstList->m_lPos; + pstList = (SHList *)pGetNode(pvAddr, pstList->m_lNext)) + { + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + if(SELF_POS_UNUSE == pstList->m_lNext) break; + continue; + } + + if(bRepeatLstgrp(pstRrp, pstTruck->m_pvData, t, *plOut, *ppsvOut)) + { + if(SELF_POS_UNUSE == pstList->m_lNext) break; + continue; + } + + if(RC_SUCC != lInsertLstgrp(pstSavm, &pstSavm->stUpdt, pstTruck->m_pvData, t, + plOut, ppsvOut)) + return RC_FAIL; + + pstSavm->m_lEffect ++; + if(SELF_POS_UNUSE == pstList->m_lNext) break; + } + + if(0 == pstSavm->m_lEffect) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Group the table data according to the hash + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + plData --offset + ppsvOut --result data list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lGroupHash(SATvm *pstSavm, void *pvAddr, TABLE t, size_t *plOut, void **ppsvOut) +{ + size_t lIdx; + SHTree *pstTree = NULL; + SHList *pstList = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + FdCond *pstRrp = &pstSavm->stUpdt; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetGrpNum(t), pGetTblGrp(t), pstSavm->pstVoid, szIdx)) + return RC_CONTU; + + lIdx = uGetHash(szIdx, lGetGrpLen(t)) % ((TblDef *)pvAddr)->m_lMaxRow; + pstTree = pvAddr + ((TblDef *)pvAddr)->m_lGroupRoot + lIdx * sizeof(SHTree); + if(NULL == pstTree || SELF_POS_UNUSE == pstTree->m_lData) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + for(*plOut = 0, pstList = (SHList *)pGetNode(pvAddr, pstTree->m_lData); + SELF_POS_UNUSE != pstList->m_lPos; pstList = (SHList *)pGetNode(pvAddr, pstList->m_lNext)) + { + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + if(SELF_POS_UNUSE == pstList->m_lNext) break; + continue; + } + + if(bRepeatLstgrp(pstRrp, pstTruck->m_pvData, t, *plOut, *ppsvOut)) + { + if(SELF_POS_UNUSE == pstList->m_lNext) break; + continue; + } + + if(RC_SUCC != lInsertLstgrp(pstSavm, &pstSavm->stUpdt, pstTruck->m_pvData, t, + plOut, ppsvOut)) + return RC_FAIL; + + pstSavm->m_lEffect ++; + if(SELF_POS_UNUSE == pstList->m_lNext) break; + } + + if(0 == pstSavm->m_lEffect) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Group the table data according to the truck + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + plData --offset + ppsvOut --result data list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lGroupTruck(SATvm *pstSavm, void *pvAddr, TABLE t, size_t *plOut, void **ppsvOut) +{ + SHTruck *pstTruck = NULL; + FdCond *pstRrp = &pstSavm->stUpdt; + size_t lRow = 0, lOffset = lGetTblData(t); + + pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset); + for(*plOut = 0; (lRow < ((TblDef *)pvAddr)->m_lValid) && (lOffset < lGetTableSize(t)); + pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset)) + { + if(IS_TRUCK_NULL(pstTruck)) + { + lOffset += lGetRowTruck(t); + continue; + } + + lRow ++; + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + lOffset += lGetRowTruck(t); + continue; + } + + if(bRepeatLstgrp(pstRrp, pstTruck->m_pvData, t, *plOut, *ppsvOut)) + { + lOffset += lGetRowTruck(t); + continue; + } + + if(RC_FAIL == lInsertLstgrp(pstSavm, pstRrp, pstTruck->m_pvData, t, plOut, ppsvOut)) + return RC_FAIL; + + lOffset += lGetRowTruck(t); + } + + if(0 == (pstSavm->m_lEffect = *plOut)) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Group the table data according to the index + parameters: + pstSavm --stvm handle + t --table + plData --offset + ppsvOut --result data list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lGroup(SATvm *pstSavm, RunTime *pstRun, size_t *plOut, void **ppsvOut) +{ + long lRet; + RWLock *prwLock = (RWLock *)pGetRWLock(pstRun->m_pvAddr); + + if(RC_SUCC != pthread_rwlock_rdlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DORD_ERR; + return RC_FAIL; + } + + if(HAVE_UNIQ_IDX(pstSavm->tblName)) + { + lRet = _lGroupIndex(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, plOut, ppsvOut); + if(RC_CONTU != lRet) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lEType = EXE_PLAN_IDX; + return lRet; + } + } + + if(HAVE_NORL_IDX(pstSavm->tblName)) + { + lRet = _lGroupGroup(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, plOut, ppsvOut); + if(RC_CONTU != lRet) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lEType = EXE_PLAN_GRP; + return lRet; + } + } + else if(HAVE_HASH_IDX(pstSavm->tblName)) + { + lRet = _lGroupHash(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, plOut, ppsvOut); + if(RC_CONTU != lRet) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lEType = EXE_PLAN_GRP; + return lRet; + } + } + + pstSavm->m_lEType = EXE_PLAN_ALL; + lRet = _lGroupTruck(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, plOut, ppsvOut); + pthread_rwlock_unlock(prwLock); + return lRet; +} + +/************************************************************************************************* + description:Group the table data according to the index + parameters: + pstSavm --stvm handle + plOut --number + ppsvOut --result data list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lGroup(SATvm *pstSavm, size_t *plOut, void **ppsvOut) +{ + RunTime *pstRun = NULL; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + if(NULL == (pstRun = (RunTime *)pInitMemTable(pstSavm, pstSavm->tblName))) + return RC_FAIL; + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + Tremohold(pstSavm, pstRun); + return _lGroupByRt(pstSavm, plOut, ppsvOut); + } + + if(RC_FAIL == _lGroup(pstSavm, pstRun, plOut, ppsvOut)) + { + vTblDisconnect(pstSavm, pstSavm->tblName); + return RC_FAIL; + } + + vTblDisconnect(pstSavm, pstSavm->tblName); + return lSortRowList(pstSavm, *plOut, *ppsvOut, lGetRowSize(pstSavm->tblName)); +} + +/************************************************************************************************* + description:Query the table data according to the Unique index + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + plData --offset + ppsvOut --result data list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lQueryIndex(SATvm *pstSavm, void *pvAddr, TABLE t, size_t *plOut, void **ppsvOut) +{ + SHTree *pstTree = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetIdxNum(t), pGetTblIdx(t), pstSavm->pstVoid, szIdx)) + return RC_CONTU; + + if(NULL == (pstTree = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lTreeRoot))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + pstTree = (SHTree *)pSearchTree(pvAddr, pstTree, szIdx, lGetIdxLen(pstSavm->tblName)); + if(!pstTree) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + pstTruck = (PSHTruck)pGetNode(pvAddr, pstTree->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == (*ppsvOut = (char *)realloc(*ppsvOut, lGetRowSize(pstSavm->tblName)))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + pstTruck->m_lTimes ++; + *plOut = pstSavm->m_lEffect = 1; + memcpy(*ppsvOut, pstTruck->m_pvData, lGetRowSize(pstSavm->tblName)); + + return RC_SUCC; +} + +/************************************************************************************************* + description:Query the table data according to the hash + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + plOut --number + ppsvOut --result data list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lQueryHash(SATvm *pstSavm, void *pvAddr, TABLE t, size_t *plOut, void **ppsvOut) +{ + SHTree *pstTree = NULL; + SHList *pstList = NULL; + SHTruck *pstTruck = NULL; + size_t lData, lIdx, lPos; + char szIdx[MAX_INDEX_LEN]; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetGrpNum(t), pGetTblGrp(t), pstSavm->pstVoid, szIdx)) + return RC_CONTU; + + lIdx = uGetHash(szIdx, lGetGrpLen(t)) % ((TblDef *)pvAddr)->m_lMaxRow; + pstTree = pvAddr + ((TblDef *)pvAddr)->m_lGroupRoot + lIdx * sizeof(SHTree); + if(NULL == pstTree || SELF_POS_UNUSE == pstTree->m_lData) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + pstList = (SHList *)pGetNode(pvAddr, pstTree->m_lData); + for(*plOut = 0, lPos = 0; SELF_POS_UNUSE != pstList->m_lPos; + pstList = (SHList *)pGetNode(pvAddr, pstList->m_lNext)) + { + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + if(SELF_POS_UNUSE == pstList->m_lNext) break; + continue; + } + + pstTruck->m_lTimes ++; + lPos = (++ (*plOut)) * lGetRowSize(t); + if(NULL == (*ppsvOut = (char *)realloc(*ppsvOut, lPos))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + memcpy(*ppsvOut + (lPos - lGetRowSize(t)), pstTruck->m_pvData, lGetRowSize(t)); + if(SELF_POS_UNUSE == pstList->m_lNext) break; + } + + if(0 == (pstSavm->m_lEffect = *plOut)) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Query the table data according to the group + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + plOut --number + ppsvOut --result data list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lQueryGroup(SATvm *pstSavm, void *pvAddr, TABLE t, size_t *plOut, void **ppsvOut) +{ + size_t lPos; + TblKey *pstIdx = NULL; + SHList *pstList = NULL; + SHTree *pstTree = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetGrpNum(t), pGetTblGrp(t), pstSavm->pstVoid, szIdx)) + return RC_CONTU; + + if(NULL == (pstTree = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lGroupRoot))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == (pstList = pSearchGroup(pvAddr, pstTree, szIdx, lGetGrpLen(t)))) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_CONTU; + } + + for(*plOut = 0, lPos = 0; SELF_POS_UNUSE != pstList->m_lPos; + pstList = (SHList *)pGetNode(pvAddr, pstList->m_lNext)) + { + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + if(SELF_POS_UNUSE == pstList->m_lNext) break; + continue; + } + + pstTruck->m_lTimes ++; + lPos = (++ (*plOut)) * lGetRowSize(t); + if(NULL == (*ppsvOut = (char *)realloc(*ppsvOut, lPos))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + memcpy(*ppsvOut + (lPos - lGetRowSize(t)), pstTruck->m_pvData, lGetRowSize(t)); + if(SELF_POS_UNUSE == pstList->m_lNext) break; + } + + if(0 == (pstSavm->m_lEffect = *plOut)) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Query the table data according to the truck + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + plOut --number + ppsvOut --result data list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lQueryTruck(SATvm *pstSavm, void *pvAddr, TABLE t, size_t *plOut, void **ppsvOut) +{ + SHTruck *pstTruck = NULL; + size_t lRow = 0, lOffset = lGetTblData(t), lPos = 0; + + pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset); + for(lRow = 0, *plOut = 0; (lRow < ((TblDef *)pvAddr)->m_lValid) && (lOffset < lGetTableSize(t)); + pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset)) + { + if(IS_TRUCK_NULL(pstTruck)) + { + lOffset += lGetRowTruck(t); + continue; + } + + lRow ++; + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + lOffset += lGetRowTruck(t); + continue; + } + + lPos = (++ (*plOut)) * lGetRowSize(t); + if(NULL == (*ppsvOut = (char *)realloc(*ppsvOut, lPos))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + memcpy(*ppsvOut + (lPos - lGetRowSize(t)), pstTruck->m_pvData, lGetRowSize(t)); + lOffset += lGetRowTruck(t); + } + + if(0 == (pstSavm->m_lEffect = *plOut)) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Query the table data + parameters: + pstSavm --stvm handle + pstRun --table handle + plOut --number + ppsvOut --result data list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lQuery(SATvm *pstSavm, RunTime *pstRun, size_t *plOut, void **ppsvOut) +{ + long lRet; + RWLock *prwLock = (RWLock *)pGetRWLock(pstRun->m_pvAddr); + + if(RC_SUCC != pthread_rwlock_rdlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DORD_ERR; + return RC_FAIL; + } + + if(HAVE_UNIQ_IDX(pstSavm->tblName)) + { + lRet = _lQueryIndex(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, plOut, ppsvOut); + if(RC_CONTU != lRet) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lEType = EXE_PLAN_IDX; + return lRet; + } + } + + if(HAVE_NORL_IDX(pstSavm->tblName)) + { + lRet = _lQueryGroup(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, plOut, ppsvOut); + if(RC_CONTU != lRet) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lEType = EXE_PLAN_GRP; + return lRet; + } + } + else if(HAVE_HASH_IDX(pstSavm->tblName)) + { + lRet = _lQueryHash(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, plOut, ppsvOut); + if(RC_CONTU != lRet) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lEType = EXE_PLAN_GRP; + return lRet; + } + } + + pstSavm->m_lEType = EXE_PLAN_ALL; + lRet = _lQueryTruck(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, plOut, ppsvOut); + pthread_rwlock_unlock(prwLock); + + return lRet; +} + +/************************************************************************************************* + description:API - Query + parameters: + pstSavm --stvm handle + plOut --number + ppsvOut --result data list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lQuery(SATvm *pstSavm, size_t *plOut, void **ppsvOut) +{ + long lRet; + RunTime *pstRun = NULL; + TblKey *pstIdx = NULL; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + if(NULL == (pstRun = (RunTime *)pInitMemTable(pstSavm, pstSavm->tblName))) + return RC_FAIL; + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + Tremohold(pstSavm, pstRun); + return _lQueryByRt(pstSavm, plOut, ppsvOut); + } + + if(RC_SUCC != _lQuery(pstSavm, pstRun, plOut, ppsvOut)) + { + vTblDisconnect(pstSavm, pstSavm->tblName); + return RC_FAIL; + } + + vTblDisconnect(pstSavm, pstSavm->tblName); + return lSortRowList(pstSavm, *plOut, *ppsvOut, lGetRowSize(pstSavm->tblName)); +} + +/************************************************************************************************* + description:Select the table data + parameters: + pstSavm --stvm handle + pstRun --table handle + t --table + ppsvOut --result data list + plData --Offset + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lSelect(SATvm *pstSavm, RunTime *pstRun, TABLE t, void *psvOut, size_t *plData) +{ + long lRet; + + if(HAVE_UNIQ_IDX(pstSavm->tblName)) + { + lRet = _lSelectIndex(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, psvOut, plData); + if(RC_CONTU != lRet) return lRet; + } + + if(HAVE_NORL_IDX(pstSavm->tblName)) + { + lRet = _lSelectGroup(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, psvOut, plData); + if(RC_CONTU != lRet) return lRet; + } + else if(HAVE_HASH_IDX(t)) + { + lRet = _lSelectHash(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, psvOut, plData); + if(RC_CONTU != lRet) return lRet; + } + + return _lSelectTruck(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, psvOut, plData); +} + +/************************************************************************************************* + description:API - Select + parameters: + pstSavm --stvm handle + ppsvOut --result data list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lSelect(SATvm *pstSavm, void *psvOut) +{ + long lRet; + size_t lData = 0; + RunTime *pstRun = NULL; + + if(!pstSavm || !pstSavm->pstVoid) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + if(NULL == (pstRun = (RunTime *)pInitMemTable(pstSavm, pstSavm->tblName))) + return RC_FAIL; + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + Tremohold(pstSavm, pstRun); + return _lSelectByRt(pstSavm, psvOut); + } + + lRet = _lSelect(pstSavm, pstRun, pstSavm->tblName, psvOut, &lData); + vTblDisconnect(pstSavm, pstSavm->tblName); + return lRet; +} + +/************************************************************************************************* + description:Add a unique index + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + ppstTruck --data truck + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lInsertIndex(SATvm *pstSavm, void *pvAddr, TABLE t, SHTruck **ppstTruck) +{ + SHTree *pstRoot = NULL; + char szIdx[MAX_INDEX_LEN]; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == (pstRoot = pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lTreeRoot))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == pPickIndex(lGetIdxNum(t), pGetTblIdx(t), pstSavm->pstVoid, szIdx)) + { + pstSavm->m_lErrno = IDX_FIELD_NIL; + return RC_FAIL; + } + + pstRoot = pInsertTree(pstSavm, pstRoot, szIdx, lGetIdxLen(t), ppstTruck); + if(!pstRoot) return RC_FAIL; + + ((TblDef *)pvAddr)->m_lTreeRoot = pstRoot->m_lSePos; + + return RC_SUCC; +} + +/************************************************************************************************* + description:Add a hash index + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + ppstTruck --data truck + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lInsertHash(SATvm *pstSavm, void *pvAddr, TABLE t, SHTruck **ppstTruck) +{ + size_t lIdx, lOffset; + SHTree *pstTree = NULL; + char szIdx[MAX_INDEX_LEN]; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetGrpNum(t), pGetTblGrp(t), pstSavm->pstVoid, szIdx)) + { + pstSavm->m_lErrno = IDX_FIELD_NIL; + return RC_FAIL; + } + + lIdx = uGetHash(szIdx, lGetGrpLen(t)) % ((TblDef *)pvAddr)->m_lMaxRow; + lOffset = ((TblDef *)pvAddr)->m_lGroupPos + lIdx * sizeof(SHTree); + if(NULL == (pstTree = (SHTree *)(pvAddr + lOffset))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + return __lInsertHash(pstSavm, pvAddr, t, pstTree, lOffset, ppstTruck); +} + +/************************************************************************************************* + description:Add a index + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + ppstTruck --data truck + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lInsertGroup(SATvm *pstSavm, void *pvAddr, TABLE t, SHTruck **ppstTruck) +{ + SHTree *pstRoot = NULL; + char szIdx[MAX_INDEX_LEN]; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == (pstRoot = pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lGroupRoot))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == pPickIndex(lGetGrpNum(t), pGetTblGrp(t), pstSavm->pstVoid, szIdx)) + { + pstSavm->m_lErrno = IDX_FIELD_NIL; + return RC_FAIL; + } + + pstRoot = pInsertGroup(pstSavm, pstRoot, szIdx, lGetGrpLen(t), ppstTruck); + if(!pstRoot) return RC_FAIL; + + ((TblDef *)pvAddr)->m_lGroupRoot = pstRoot->m_lSePos; + + return RC_SUCC; +} + +/************************************************************************************************* + description:Add one data + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + ppstTruck --data truck + uTimes --Click volume + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lInsertTruck(SATvm *pstSavm, void *pvAddr, TABLE t, SHTruck *pstTruck, ulong uTimes) +{ + SHTruck *pvTruck = pstTruck; + + if(!pvTruck) // 说明无索引 + pvTruck = pGetNode(pvAddr, lGetTblData(t) + lGetRowTruck(t) * ((TblDef *)pvAddr)->m_lValid); + + SET_DATA_TRUCK(pvTruck, DATA_TRUCK_NRML); + pvTruck->m_lTimes = uTimes; + memcpy(pvTruck->m_pvData, pstSavm->pstVoid, lGetRowSize(t)); + + ((TblDef *)pvAddr)->m_lValid ++; + pstSavm->m_lEffect = 1; + + return RC_SUCC; +} + +/************************************************************************************************* + description:insert data to table + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + uTimes --Click volume + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long __lInsert(SATvm *pstSavm, void *pvAddr, TABLE t, ulong uTimes) +{ + SHTruck *pstTruck = NULL; + + if(HAVE_UNIQ_IDX(t)) + { + if(RC_SUCC != _lInsertIndex(pstSavm, pvAddr, t, &pstTruck)) + return RC_FAIL; + } + + if(HAVE_NORL_IDX(t)) + { + if(RC_SUCC != _lInsertGroup(pstSavm, pvAddr, t, &pstTruck)) + return RC_FAIL; + } + else if(HAVE_HASH_IDX(t)) + { + if(RC_SUCC != _lInsertHash(pstSavm, pvAddr, t, &pstTruck)) + return RC_FAIL; + } + + return _lInsertTruck(pstSavm, pvAddr, t, pstTruck, uTimes); +} + +/************************************************************************************************* + description:Reset the table lock + parameters: + pstSavm --stvm handle + t --table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lResetLock(SATvm *pstSavm, TABLE t) +{ + RWAttr attr; + RunTime *pstRun = NULL; + RWLock *prwLock = NULL; + + if(RC_SUCC != lInitSATvm(pstSavm, t)) + return RC_FAIL; + + if(NULL == (pstRun = (RunTime *)pInitHitTest(pstSavm, t))) + return RC_FAIL; + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + pstSavm->m_lErrno = RMT_NOT_SUPPT; + return RC_FAIL; + } + + prwLock = (RWLock *)pGetRWLock(pstRun->m_pvAddr); + pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); + pthread_rwlock_init(prwLock, &attr); + vTblDisconnect(pstSavm, t); + + return RC_SUCC; +} + +/************************************************************************************************* + description:API - Insert + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lInsert(SATvm *pstSavm) +{ + long lRet; + RunTime *pstRun = NULL; + RWLock *prwLock = NULL; + + if(!pstSavm || !pstSavm->pstVoid) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + if(NULL == (pstRun = (RunTime *)pInitMemTable(pstSavm, pstSavm->tblName))) + return RC_FAIL; + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + Tremohold(pstSavm, pstRun); + return _lInsertByRt(pstSavm); + } + + if(lGetTblRow(pstSavm->tblName) <= ((TblDef *)pstRun->m_pvAddr)->m_lValid) + { + pstSavm->m_lErrno = DATA_SPC_FULL; + vTblDisconnect(pstSavm, pstSavm->tblName); + return RC_FAIL; + } + + prwLock = (RWLock *)pGetRWLock(pstRun->m_pvAddr); + if(RC_SUCC != pthread_rwlock_wrlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DOWR_ERR; + vTblDisconnect(pstSavm, pstSavm->tblName); + return RC_FAIL; + } + + lRet = __lInsert(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, 0); + pthread_rwlock_unlock(prwLock); + vTblDisconnect(pstSavm, pstSavm->tblName); + if(RC_SUCC != lRet) return RC_FAIL; + + return lRecordWork(pstSavm, pstSavm->pstVoid, OPERATE_INSERT); +} + +/************************************************************************************************* + description:Transaction Flow Add record + parameters: + pstSavm --stvm handle + plOffset --memory address + pllSeq --seqno + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lInsertTrans(SATvm *pstSavm, size_t *plOffset, llSEQ *pllSeq) +{ + size_t lOffset; + RunTime *pstRun = NULL; + RWLock *prwLock = NULL; + SHTruck *pstTruck = NULL; + + if(!pstSavm || !pstSavm->pstVoid) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + if(NULL == (pstRun = (RunTime *)pInitMemTable(pstSavm, pstSavm->tblName))) + return RC_FAIL; + + if(lGetTblRow(pstSavm->tblName) <= ((TblDef *)pstRun->m_pvAddr)->m_lValid) + { + pstSavm->m_lErrno = DATA_SPC_FULL; + vTblDisconnect(pstSavm, pstSavm->tblName); + return RC_FAIL; + } + + prwLock = (RWLock *)pGetRWLock(pstRun->m_pvAddr); + if(RC_SUCC != pthread_rwlock_wrlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DOWR_ERR; + vTblDisconnect(pstSavm, pstSavm->tblName); + return RC_FAIL; + } + + if(HAVE_UNIQ_IDX(pstSavm->tblName)) + { + if(RC_SUCC != _lInsertIndex(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, &pstTruck)) + goto ErrInsert; + } + + if(HAVE_NORL_IDX(pstSavm->tblName)) + { + if(RC_SUCC != _lInsertGroup(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, &pstTruck)) + goto ErrInsert; + } + else if(HAVE_HASH_IDX(pstSavm->tblName)) + { + if(RC_SUCC != _lInsertHash(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, &pstTruck)) + goto ErrInsert; + } + + if(!pstTruck) + { + lOffset = lGetTblData(pstSavm->tblName) + + lGetRowTruck(pstSavm->tblName) * ((TblDef *)pstRun->m_pvAddr)->m_lValid; + pstTruck = pGetNode(pstRun->m_pvAddr, lOffset); + } + + lOffset = (void *)pstTruck->m_pvData - (void *)pstRun->m_pvAddr; + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NRML); + pstTruck->m_lTimes = 0; + memcpy(pstTruck->m_pvData, pstSavm->pstVoid, lGetRowSize(pstSavm->tblName)); + ((TblDef *)pstRun->m_pvAddr)->m_lValid ++; + ((TblDef *)pstRun->m_pvAddr)->m_lExSeQ ++; + if(pllSeq) *pllSeq = ((TblDef *)pstRun->m_pvAddr)->m_lExSeQ; + + pthread_rwlock_unlock(prwLock); + vTblDisconnect(pstSavm, pstSavm->tblName); + pstSavm->m_lEffect = 1; + if(plOffset) *plOffset = lOffset; + + return RC_SUCC; + +ErrInsert: + pthread_rwlock_unlock(prwLock); + vTblDisconnect(pstSavm, pstSavm->tblName); + return RC_FAIL; +} + +/************************************************************************************************* + description:Cursor-fetch the data as unique index + parameters: + pstSavm --stvm handle + pstRun --table handle + t --table + psvout --result data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _llFetchIndex(SATvm *pstSavm, RunTime *pstRun, TABLE t, void *psvOut) +{ + SHTree *pstTree = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + void *pvAddr = pGetAddr(pstSavm, t); + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetIdxNum(t), pGetTblIdx(t), pstRun->pstVoid, szIdx)) + { + pstSavm->m_lErrno = IDX_FIELD_NIL; + return RC_FAIL; + } + + if(NULL == (pstTree = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lTreeRoot))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + pstTree = (SHTree *)pSearchTree(pvAddr, pstTree, szIdx, lGetIdxLen(t)); + if(!pstTree) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_NOTFOUND; + } + + pstTruck = (PSHTruck)pGetNode(pvAddr, pstTree->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstRun->pstVoid)) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + pstRun->m_lCurLine ++; + pstRun->m_pvCurAddr = NULL; + memcpy(psvOut, pstTruck->m_pvData, lGetRowSize(t)); + + return RC_SUCC; +} + +/************************************************************************************************* + description:Cursor-fetch the data as index + parameters: + pstSavm --stvm handle + pstRun --table handle + t --table + psvout --result data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _llFetchGroup(SATvm *pstSavm, RunTime *pstRun, TABLE t, void *psvOut) +{ + SHList *pstList = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + void *pvAddr = pGetAddr(pstSavm, t); + + for(pstList = (SHList *)pstRun->m_pvCurAddr; pstList && (SELF_POS_UNUSE != pstList->m_lPos); + pstList = (SHList *)pGetNode(pvAddr, pstList->m_lNext)) + { + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + if(IS_TRUCK_NULL(pstTruck)) + { + if(SELF_POS_UNUSE == pstList->m_lNext) break; + continue; + } + + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstRun->pstVoid)) + { + if(SELF_POS_UNUSE == pstList->m_lNext) break; + continue; + } + + pstRun->m_lCurLine ++; + memcpy(psvOut, pstTruck->m_pvData, lGetRowSize(t)); + if(SELF_POS_UNUSE == pstList->m_lNext) + pstRun->m_pvCurAddr = NULL; + else + pstRun->m_pvCurAddr = (void *)pGetNode(pvAddr, pstList->m_lNext); + + return RC_SUCC; + } + + return RC_NOTFOUND; +} + +/************************************************************************************************* + description:Cursor-fetch the data as truck + parameters: + pstSavm --stvm handle + pstRun --table handle + t --table + psvout --result data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _llFetchTruck(SATvm *pstSavm, RunTime *pstRun, TABLE t, void *psvOut) +{ + SHTruck *pstTruck = NULL; + long lRow = 0, lOffset; + void *pvAddr = pGetAddr(pstSavm, t); + + if(1 == pstRun->m_lCurLine) + { + lOffset = lGetTblData(t); + pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset); + } + else + { + lOffset = pstRun->m_pvCurAddr - pvAddr; + pstTruck = (PSHTruck)pstRun->m_pvCurAddr; + } + + for(lRow = 0; (lRow < ((TblDef *)pvAddr)->m_lValid) && (lOffset < lGetTableSize(t)); + pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset)) + { + if(IS_TRUCK_NULL(pstTruck)) + { + lOffset += lGetRowTruck(t); + continue; + } + + lRow ++; + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstRun->pstVoid)) + { + lOffset += lGetRowTruck(t); + continue; + } + + pstRun->m_lCurLine ++; + lOffset += lGetRowTruck(t); + pstRun->m_pvCurAddr = pGetNode(pvAddr, lOffset); + memcpy(psvOut, pstTruck->m_pvData, lGetRowSize(t)); + return RC_SUCC; + } + + return RC_NOTFOUND; +} + +/************************************************************************************************* + description:Define the cursor + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTableDeclare(SATvm *pstSavm) +{ + long lIdx; + SHTree *pstTree = NULL; + RunTime *pstRun = NULL; + char szIdx[MAX_INDEX_LEN]; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + if(NULL == (pstRun = (RunTime *)pInitMemTable(pstSavm, pstSavm->tblName))) + return RC_FAIL; + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + pstSavm->m_lErrno = RMT_NOT_SUPPT; + return RC_FAIL; + } + + pstRun->m_lCurLine = 1; + pstRun->m_lCurType = EXE_PLAN_ALL; + pstRun->m_lRowSize = pstSavm->lSize; + pstRun->m_pvCurAddr= pstRun->m_pvAddr; + pstSavm->m_lEType = pstRun->m_lCurType; + + if(!pstSavm->pstVoid) return RC_SUCC; + + pstRun->pstVoid = (char *)malloc(pstSavm->lSize); + memcpy(pstRun->pstVoid, pstSavm->pstVoid, pstSavm->lSize); + if(HAVE_UNIQ_IDX(pstSavm->tblName)) + { + memset(szIdx, 0, sizeof(szIdx)); + if(NULL != pGetIndex(&pstSavm->stCond, lGetIdxNum(pstSavm->tblName), + pGetTblIdx(pstSavm->tblName), pstSavm->pstVoid, szIdx)) + { + pstRun->m_lCurType = EXE_PLAN_IDX; + pstSavm->m_lEType = pstRun->m_lCurType; + return RC_SUCC; + } + } + + if(HAVE_NORL_IDX(pstSavm->tblName)) + { + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetGrpNum(pstSavm->tblName), + pGetTblGrp(pstSavm->tblName), pstSavm->pstVoid, szIdx)) + return RC_SUCC; + + pstRun->m_lCurType = EXE_PLAN_GRP; + pstSavm->m_lEType = pstRun->m_lCurType; + pstRun->m_pvCurAddr = pSearchGroup(pstRun->m_pvAddr, (SHTree *)pGetNode(pstRun->m_pvAddr, + ((TblDef *)pstRun->m_pvAddr)->m_lGroupRoot), szIdx, lGetGrpLen(pstSavm->tblName)); + + return RC_SUCC; + } + else if(HAVE_HASH_IDX(pstSavm->tblName)) + { + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetGrpNum(pstSavm->tblName), + pGetTblGrp(pstSavm->tblName), pstSavm->pstVoid, szIdx)) + return RC_SUCC; + + pstRun->m_lCurType = EXE_PLAN_GRP; + pstSavm->m_lEType = pstRun->m_lCurType; + lIdx = uGetHash(szIdx, lGetGrpLen(pstSavm->tblName)) % ((TblDef *)pstRun->m_pvAddr)->m_lMaxRow; + pstTree = pstRun->m_pvAddr + ((TblDef *)pstRun->m_pvAddr)->m_lGroupRoot + lIdx * sizeof(SHTree); + if(NULL == pstTree || SELF_POS_UNUSE == pstTree->m_lData) + { + pstRun->m_pvCurAddr = NULL; + return RC_SUCC; + } + + pstRun->m_pvCurAddr = (SHList *)pGetNode(pstRun->m_pvAddr, pstTree->m_lData); + return RC_SUCC; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Cursor-fetch the data + parameters: + pstSavm --stvm handle + psvout --result data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lTableFetch(SATvm *pstSavm, void *psvOut) +{ + long lRet; + RunTime *pstRun = NULL; + + if(!pstSavm) + { + pstSavm->m_lErrno = CURS_IS_INVAL; + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, pstSavm->tblName); + if(NULL == pstRun->m_pvCurAddr) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_NOTFOUND; + } + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + pstSavm->m_lErrno = RMT_NOT_SUPPT; + return RC_FAIL; + } + + if(EXE_PLAN_IDX == pstRun->m_lCurType) + lRet = _llFetchIndex(pstSavm, pstRun, pstSavm->tblName, psvOut); + else if(EXE_PLAN_GRP == pstRun->m_lCurType) + lRet = _llFetchGroup(pstSavm, pstRun, pstSavm->tblName, psvOut); + else + lRet = _llFetchTruck(pstSavm, pstRun, pstSavm->tblName, psvOut); + if(RC_NOTFOUND == lRet) + { + pstRun->m_pvCurAddr = NULL; + pstSavm->m_lErrno = NO_DATA_FOUND; + } + + return lRet; +} + +/************************************************************************************************* + description:Cursor-next truck data + parameters: + pstSavm --stvm handle + pstRun --table handle + t --table + psvout --result data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lNextTruck(SATvm *pstSavm, RunTime *pstRun, TABLE t, void **ppvOAddr) +{ + SHTruck *pstTruck = NULL; + long lRow = 0, lOffset; + void *pvAddr = pGetAddr(pstSavm, t); + + if(1 == pstRun->m_lCurLine) + { + lOffset = lGetTblData(t); + pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset); + } + else + { + lOffset = pstRun->m_pvCurAddr - pvAddr; + pstTruck = (PSHTruck)pstRun->m_pvCurAddr; + } + + for(lRow = 0; (lRow < ((TblDef *)pvAddr)->m_lValid) && (lOffset < lGetTableSize(t)); + pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset)) + { + if(IS_TRUCK_NULL(pstTruck)) + { + lOffset += lGetRowTruck(t); + continue; + } + + lRow ++; + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstRun->pstVoid)) + { + lOffset += lGetRowTruck(t); + continue; + } + + pstRun->m_lCurLine ++; + *ppvOAddr = pstTruck->m_pvData; + lOffset += lGetRowTruck(t); + pstRun->m_pvCurAddr = pGetNode(pvAddr, lOffset); + return RC_SUCC; + } + + return RC_NOTFOUND; +} + +/************************************************************************************************* + description:Cursor-next index data + parameters: + pstSavm --stvm handle + pstRun --table handle + t --table + psvout --result data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lNextGroup(SATvm *pstSavm, RunTime *pstRun, TABLE t, void **ppvOAddr) +{ + SHList *pstList = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + void *pvAddr = pGetAddr(pstSavm, t); + + for(pstList = (SHList *)pstRun->m_pvCurAddr; pstList && (SELF_POS_UNUSE != pstList->m_lPos); + pstList = (SHList *)pGetNode(pvAddr, pstList->m_lNext)) + { + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstRun->pstVoid)) + { + if(SELF_POS_UNUSE == pstList->m_lNext) break; + continue; + } + + pstRun->m_lCurLine ++; + *ppvOAddr = pstTruck->m_pvData; + if(SELF_POS_UNUSE == pstList->m_lNext) + pstRun->m_pvCurAddr = NULL; + else + pstRun->m_pvCurAddr = (void *)pGetNode(pvAddr, pstList->m_lNext); + + return RC_SUCC; + } + + return RC_NOTFOUND; +} + +/************************************************************************************************* + description:Cursor-next unique index data + parameters: + pstSavm --stvm handle + pstRun --table handle + t --table + psvout --result data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lNextIndex(SATvm *pstSavm, RunTime *pstRun, TABLE t, void **ppvOAddr) +{ + SHTree *pstTree = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + void *pvAddr = pGetAddr(pstSavm, t); + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetIdxNum(t), pGetTblIdx(t), pstSavm->pstVoid, szIdx)) + { + pstSavm->m_lErrno = IDX_FIELD_NIL; + return RC_FAIL; + } + + if(NULL == (pstTree = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lTreeRoot))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + pstTree = (SHTree *)pSearchTree(pvAddr, pstTree, szIdx, lGetIdxLen(t)); + if(!pstTree) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_NOTFOUND; + } + + pstTruck = (PSHTruck)pGetNode(pvAddr, pstTree->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstRun->pstVoid)) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + pstRun->m_lCurLine ++; + pstRun->m_pvCurAddr = NULL; + *ppvOAddr = pstTruck->m_pvData; + return RC_SUCC; +} + +/************************************************************************************************* + description:Cursor-next fetch + parameters: + pstSavm --stvm handle + ppvOAddr --result data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lNextFetch(SATvm *pstSavm, void **ppvOAddr) +{ + long lRet; + RunTime *pstRun = NULL; + + if(!pstSavm) + { + pstSavm->m_lErrno = CURS_IS_INVAL; + return RC_FAIL; + } + + pstRun = (RunTime *)pGetRunTime(pstSavm, pstSavm->tblName); + if(NULL == pstRun->m_pvCurAddr) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_NOTFOUND; + } + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + pstSavm->m_lErrno = RMT_NOT_SUPPT; + return RC_FAIL; + } + + if(EXE_PLAN_IDX == pstRun->m_lCurType) + lRet = _lNextIndex(pstSavm, pstRun, pstSavm->tblName, ppvOAddr); + else if(EXE_PLAN_GRP == pstRun->m_lCurType) + lRet = _lNextGroup(pstSavm, pstRun, pstSavm->tblName, ppvOAddr); + else + lRet = _lNextTruck(pstSavm, pstRun, pstSavm->tblName, ppvOAddr); + if(RC_NOTFOUND == lRet) + { + pstRun->m_pvCurAddr = NULL; + pstSavm->m_lErrno = NO_DATA_FOUND; + } + + return lRet; +} + +/************************************************************************************************* + description:close Cursor + parameters: + pstSavm --stvm handle + return: + *************************************************************************************************/ +void vTableClose(SATvm *pstSavm) +{ + _vTblRelease(pstSavm, pstSavm->tblName, pstSavm->m_bHold); +} + +/************************************************************************************************* + description:Update record hash index + parameters: + pstSavm --stvm handle + pstAddr --table handle + t --table + pstTruck --data truck + lData --offset + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long __lUpdateHash(SATvm *pstSavm, void *pvAddr, TABLE t, SHTruck *pstTruck, size_t lData) +{ + SHList *pstList = NULL; + SHTree *pstTree = NULL; + size_t lIdx, lOld, lOffset, lNext; + char szOld[MAX_INDEX_LEN], szIdx[MAX_INDEX_LEN]; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetGrpNum(t), pGetTblGrp(t), pstSavm->pstVoid, szIdx)) + { + pstSavm->m_lErrno = IDX_FIELD_NIL; + return RC_FAIL; + } + + memset(szOld, 0, sizeof(szOld)); + if(NULL == pPickIndex(lGetGrpNum(t), pGetTblGrp(t), pstTruck->m_pvData, szOld)) + { + pstSavm->m_lErrno = IDX_DATA_MISM; + return RC_FAIL; + } + + lOld = uGetHash(szOld, lGetGrpLen(t)) % ((TblDef *)pvAddr)->m_lMaxRow; + lIdx = uGetHash(szIdx, lGetGrpLen(t)) % ((TblDef *)pvAddr)->m_lMaxRow; + if(lOld == lIdx) return RC_SUCC; + + lOffset = ((TblDef *)pvAddr)->m_lGroupPos + lOld * sizeof(SHTree); + if(NULL == (pstTree = (SHTree *)(pvAddr + lOffset))) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + lOffset = lGetListOfs(t) + ((TblDef *)pvAddr)->m_lValid * sizeof(SHList); + for(pstList = (SHList *)pGetNode(pvAddr, pstTree->m_lData); SELF_POS_UNUSE != pstList->m_lPos; + pstList = (SHList *)pGetNode(pvAddr, lNext)) + { + lNext = pstList->m_lNext; + if(lData != pstList->m_lData) + { + if(SELF_POS_UNUSE == pstList->m_lNext) break; + continue; + } + + lOffset -= sizeof(SHList); + if(RC_SUCC != lReleaseList(pvAddr, t, pstTree, pstList, lOffset, &lNext)) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + ((TblDef *)pvAddr)->m_lValid --; + lOffset = RC_CLOSE; + break; + } + + if(SELF_POS_UNUSE == pstTree->m_lData) + pstTree->m_lSePos = SELF_POS_UNUSE; + + if(RC_CLOSE != lOffset) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + lOffset = ((TblDef *)pvAddr)->m_lGroupPos + lIdx * sizeof(SHTree); + if(NULL == (pstTree = (SHTree *)(pvAddr + lOffset))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(RC_SUCC != __lInsertHash(pstSavm, pvAddr, t, pstTree, lOffset, &pstTruck)) + return RC_FAIL; + + ((TblDef *)pvAddr)->m_lValid ++; + return RC_SUCC; +} + +/************************************************************************************************* + description:Update record index + parameters: + pstSavm --stvm handle + pstAddr --table handle + t --table + pstTruck --data truck + lData --offset + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long __lUpdateGroup(SATvm *pstSavm, void *pvAddr, TABLE t, SHTruck *pstTruck, size_t lData) +{ + SHList *pstList = NULL; + size_t lNext = 0, lOffset; + SHTree *pstRoot, *pstTree = NULL; + char szOld[MAX_INDEX_LEN], szIdx[MAX_INDEX_LEN]; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetGrpNum(t), pGetTblGrp(t), pstSavm->pstVoid, szIdx)) + { + pstSavm->m_lErrno = IDX_FIELD_NIL; + return RC_FAIL; + } + + memset(szOld, 0, sizeof(szOld)); + if(NULL == pPickIndex(lGetGrpNum(t), pGetTblGrp(t), pstTruck->m_pvData, szOld)) + { + pstSavm->m_lErrno = IDX_DATA_MISM; + return RC_FAIL; + } + + if(!memcmp(szIdx, szOld, MAX_INDEX_LEN)) // Index has not changed + return RC_SUCC; + + if(NULL == (pstRoot = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lGroupRoot))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == (pstTree = pSearchTree(pvAddr, pstRoot, szOld, lGetGrpLen(t)))) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + lOffset = lGetListOfs(t) + ((TblDef *)pvAddr)->m_lValid * sizeof(SHList); + for(pstList = (SHList *)pGetNode(pvAddr, pstTree->m_lData); SELF_POS_UNUSE != pstList->m_lPos; + pstList = (SHList *)pGetNode(pvAddr, lNext)) + { + lNext = pstList->m_lNext; + if(lData != pstList->m_lData) + { + if(SELF_POS_UNUSE == pstList->m_lNext) break; + continue; + } + + lOffset -= sizeof(SHList); + if(RC_SUCC != lReleaseList(pvAddr, t, pstTree, pstList, lOffset, &lNext)) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + ((TblDef *)pvAddr)->m_lValid --; + lOffset = RC_CLOSE; + break; + } + + if(SELF_POS_UNUSE == pstTree->m_lData) + { + pstRoot = _pDeleteGroup(pvAddr, pstSavm->tblName, pstRoot, pstTree, &pstSavm->m_lEffect); + ((TblDef *)pvAddr)->m_lGroupRoot = pstRoot->m_lSePos; + } + + if(RC_CLOSE != lOffset) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + if(NULL == (pstRoot = pInsertGroup(pstSavm, pstRoot, szIdx, lGetGrpLen(t), &pstTruck))) + return RC_FAIL; + + ((TblDef *)pvAddr)->m_lValid ++; + ((TblDef *)pvAddr)->m_lGroupRoot = pstRoot->m_lSePos; + + return RC_SUCC; +} + +/************************************************************************************************* + description:Update record unique index + parameters: + pstSavm --stvm handle + pstAddr --table handle + t --table + pstTruck --data truck + lData --offset + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long __lIndexUpdate(SATvm *pstSavm, void *pvAddr, TABLE t, SHTruck *pstTruck, size_t lData) +{ + SHTree *pstRoot, *pstTree = NULL; + char szOld[MAX_INDEX_LEN], szIdx[MAX_INDEX_LEN]; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetIdxNum(t), pGetTblIdx(t), pstSavm->pstVoid, szIdx)) + { + pstSavm->m_lErrno = IDX_FIELD_NIL; + return RC_FAIL; + } + + memset(szOld, 0, sizeof(szOld)); + if(NULL == pPickIndex(lGetIdxNum(t), pGetTblIdx(t), pstTruck->m_pvData, szOld)) + { + pstSavm->m_lErrno = IDX_DATA_MISM; + return RC_FAIL; + } + + if(!memcmp(szIdx, szOld, MAX_INDEX_LEN)) // Index has not changed + return RC_SUCC; + + if(NULL == (pstRoot = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lTreeRoot))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + // frist select, then add The unique index, avoiding the uniqueness error after deletion. + if(NULL != (SHTree *)pSearchTree(pvAddr, pstRoot, szIdx, lGetIdxLen(t))) + { + pstSavm->m_lErrno = UNIQ_IDX_REPT; + return RC_FAIL; + } + + if(NULL == (pstTree = (SHTree *)pSearchTree(pvAddr, pstRoot, szOld, lGetIdxLen(t)))) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + if(lData != pstTree->m_lData) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == (pstRoot = _pDeleteTree(pvAddr, pstSavm->tblName, pstRoot, pstTree))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + ((TblDef *)pvAddr)->m_lValid --; + + if(NULL == (pstRoot = pInsertTree(pstSavm, pstRoot, szIdx, lGetIdxLen(t), &pstTruck))) + return RC_FAIL; + ((TblDef *)pvAddr)->m_lValid ++; + ((TblDef *)pvAddr)->m_lTreeRoot = pstRoot->m_lSePos; + return RC_SUCC; +} + +/************************************************************************************************* + description:Update record unique index + parameters: + pstSavm --stvm handle + pstAddr --table handle + t --table + pvUpdate --update date + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lUpdateIndex(SATvm *pstSavm, void *pvAddr, TABLE t, void *pvUpdate) +{ + size_t lData; + long lRet = RC_SUCC; + void *pvData = NULL; + SHTruck *pstTruck = NULL; + SHTree *pstRoot, *pstTree = NULL; + RWLock *prwLock = (RWLock *)pGetRWLock(pvAddr); + char szOld[MAX_INDEX_LEN], szIdx[MAX_INDEX_LEN]; + + memset(szOld, 0, sizeof(szOld)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetIdxNum(t), pGetTblIdx(t), pstSavm->pstVoid, szOld)) + return RC_CONTU; + + if(NULL == (pvData = (void *)malloc(lGetRowSize(pstSavm->tblName)))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + if(RC_SUCC != pthread_rwlock_wrlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DOWR_ERR; + TFree(pvData); + return RC_FAIL; + } + + pstSavm->m_lEType = EXE_PLAN_IDX; + if(NULL == (pstRoot = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lTreeRoot))) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + TFree(pvData); + return RC_FAIL; + } + + if(NULL == (pstTree = (SHTree *)pSearchTree(pvAddr, pstRoot, szOld, lGetIdxLen(t)))) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = NO_DATA_FOUND; + TFree(pvData); + return RC_FAIL; + } + + lData = pstTree->m_lData; + pstTruck = (PSHTruck)pGetNode(pvAddr, pstTree->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + TFree(pvData); + return RC_FAIL; + } + + memcpy(pvData, pvUpdate, lGetRowSize(pstSavm->tblName)); + memcpy(pvUpdate, pstTruck->m_pvData, lGetRowSize(pstSavm->tblName)); + if(RC_FAIL == lMergeTruck(pstSavm, &pstSavm->stUpdt, pvData, pvUpdate)) + { + pthread_rwlock_unlock(prwLock); + TFree(pvData); + return RC_FAIL; + } + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetIdxNum(t), pGetTblIdx(t), pvUpdate, szIdx)) + { + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = IDX_FIELD_NIL; + TFree(pvData); + return RC_FAIL; + } + + pstSavm->pstVoid = pvUpdate; + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NULL); + if(!memcmp(szIdx, szOld, MAX_INDEX_LEN)) + { + if(HAVE_NORL_IDX(t)) + lRet = __lUpdateGroup(pstSavm, pvAddr, t, pstTruck, lData); + else if(HAVE_HASH_IDX(t)) + lRet = __lUpdateHash(pstSavm, pvAddr, t, pstTruck, lData); + } + else + { + if(NULL != (SHTree *)pSearchTree(pvAddr, pstRoot, szIdx, lGetIdxLen(t))) + { + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NRML); + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = UNIQ_IDX_REPT; + TFree(pvData); + return RC_FAIL; + } + + if(NULL == (pstRoot = _pDeleteTree(pvAddr, pstSavm->tblName, pstRoot, pstTree))) + { + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NRML); + pthread_rwlock_unlock(prwLock); + pstSavm->m_lErrno = SVR_EXCEPTION; + TFree(pvData); + return RC_FAIL; + } + + ((TblDef *)pvAddr)->m_lValid --; + if(NULL == (pstRoot = pInsertTree(pstSavm, pstRoot, szIdx, lGetIdxLen(t), &pstTruck))) + { + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NRML); + pthread_rwlock_unlock(prwLock); + TFree(pvData); + return RC_FAIL; + } + + ((TblDef *)pvAddr)->m_lValid ++; + ((TblDef *)pvAddr)->m_lTreeRoot = pstRoot->m_lSePos; + if(HAVE_NORL_IDX(t)) + lRet = __lUpdateGroup(pstSavm, pvAddr, t, pstTruck, lData); + else if(HAVE_HASH_IDX(t)) + lRet = __lUpdateHash(pstSavm, pvAddr, t, pstTruck, lData); + } + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NRML); + if(RC_SUCC != lRet) + { + pthread_rwlock_unlock(prwLock); + TFree(pvData); + return RC_FAIL; + } + + if(RC_SUCC != lRecordWork(pstSavm, pstTruck->m_pvData, OPERATE_UPDATE)) + { + pthread_rwlock_unlock(prwLock); + TFree(pvData); + return RC_FAIL; + } + + memcpy(pstTruck->m_pvData, pvUpdate, lGetRowSize(t)); + pthread_rwlock_unlock(prwLock); + pstSavm->m_lEffect = 1; + + TFree(pvData); + return RC_SUCC; +} + +/************************************************************************************************* + description:Update record index + parameters: + pstSavm --stvm handle + pstAddr --table handle + t --table + pvUpdate --update date + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lUpdateGroup(SATvm *pstSavm, void *pvAddr, TABLE t, void *pvUpdate) +{ + SHList *pstList = NULL; + SHTruck *pstTruck = NULL; + size_t lOffset, lNext; + SHTree *pstTree, *pstRoot; + void *pvData, *pvCond = NULL; + RWLock *prwLock = (RWLock *)pGetRWLock(pvAddr); + char szOld[MAX_INDEX_LEN], szIdx[MAX_INDEX_LEN]; + + memset(szOld, 0, sizeof(szOld)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetGrpNum(t), pGetTblGrp(t), pstSavm->pstVoid, szOld)) + return RC_CONTU; + + if(NULL == (pvData = (void *)malloc(lGetRowSize(t)))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + if(RC_SUCC != pthread_rwlock_wrlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DOWR_ERR; + TFree(pvData); + return RC_FAIL; + } + + if(NULL == (pstRoot = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lGroupRoot))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + goto GROUP_ERROR; + } + + if(NULL == (pstTree = pSearchTree(pvAddr, pstRoot, szOld, lGetGrpLen(t)))) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + goto GROUP_ERROR; + } + + pstSavm->m_lEffect = 0; + pvCond = pstSavm->pstVoid; + pstSavm->m_lEType = EXE_PLAN_GRP; + for(pstList = (SHList *)pGetNode(pvAddr, pstTree->m_lData); SELF_POS_UNUSE != pstList->m_lPos; + pstList = (SHList *)pGetNode(pvAddr, lNext)) + { + lNext = pstList->m_lNext; + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pvCond)) + { + if(SELF_POS_UNUSE == pstList->m_lNext) break; + continue; + } + + memcpy(pvData, pstTruck->m_pvData, lGetRowSize(t)); + if(RC_FAIL == lMergeTruck(pstSavm, &pstSavm->stUpdt, pvUpdate, pvData)) + goto GROUP_ERROR; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetGrpNum(t), pGetTblGrp(t), pvData, szIdx)) + { + pstSavm->m_lErrno = IDX_FIELD_NIL; + goto GROUP_ERROR; + } + + pstSavm->m_lEffect ++; + pstSavm->pstVoid = pvData; + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NULL); + if(HAVE_UNIQ_IDX(t)) + { + if(RC_SUCC != __lIndexUpdate(pstSavm, pvAddr, t, pstTruck, pstList->m_lData)) + { + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NRML); + goto GROUP_ERROR; + } + } + + if(memcmp(szIdx, szOld, MAX_INDEX_LEN)) + { + -- ((TblDef *)pvAddr)->m_lValid; + lOffset = lGetListOfs(t) + ((TblDef *)pvAddr)->m_lValid * sizeof(SHList); + if(RC_SUCC != lReleaseList(pvAddr, t, pstTree, pstList, lOffset, &lNext)) + { + ((TblDef *)pvAddr)->m_lValid ++; + pstSavm->m_lErrno = SVR_EXCEPTION; + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NRML); + goto GROUP_ERROR; + } + + if(SELF_POS_UNUSE == pstTree->m_lData) + { + pstRoot = _pDeleteGroup(pvAddr, t, pstRoot, pstTree, &pstSavm->m_lEffect); + ((TblDef *)pvAddr)->m_lGroupRoot = pstRoot->m_lSePos; + } + + if(NULL == (pstRoot = pInsertGroup(pstSavm, pstRoot, szIdx, lGetGrpLen(t), &pstTruck))) + { + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NRML); + goto GROUP_ERROR; + } + + ((TblDef *)pvAddr)->m_lValid ++; + ((TblDef *)pvAddr)->m_lGroupRoot = pstRoot->m_lSePos; + } + + if(RC_SUCC != lRecordWork(pstSavm, pstTruck->m_pvData, OPERATE_UPDATE)) + goto GROUP_ERROR; + + memcpy(pstTruck->m_pvData, pvData, lGetRowSize(t)); + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NRML); + + if(FIRST_ROW & pstSavm->lFind) break; + } + pthread_rwlock_unlock(prwLock); + TFree(pvData); + + if(0 == pstSavm->m_lEffect) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + return RC_SUCC; + +GROUP_ERROR: + pthread_rwlock_unlock(prwLock); + TFree(pvData); + return RC_FAIL; +} + +/************************************************************************************************* + description:Update record hash index + parameters: + pstSavm --stvm handle + pstAddr --table handle + t --table + pvUpdate --update date + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lUpdateHash(SATvm *pstSavm, void *pvAddr, TABLE t, void *pvUpdate) +{ + SHList *pstList = NULL; + SHTruck *pstTruck = NULL; + SHTree *pstTree, *pstHash; + void *pvData = NULL, *pvCond; + size_t lOld, lIdx, lOffset, lNext; + RWLock *prwLock = (RWLock *)pGetRWLock(pvAddr); + char szOld[MAX_INDEX_LEN], szIdx[MAX_INDEX_LEN]; + + memset(szOld, 0, sizeof(szOld)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetGrpNum(t), pGetTblGrp(t), pstSavm->pstVoid, szOld)) + return RC_CONTU; + + if(NULL == (pvData = (void *)malloc(lGetRowSize(t)))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + lOld = uGetHash(szOld, lGetGrpLen(t)) % ((TblDef *)pvAddr)->m_lMaxRow; + lOffset = ((TblDef *)pvAddr)->m_lGroupPos + lOld * sizeof(SHTree); + if(NULL == (pstHash = (SHTree *)(pvAddr + lOffset))) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + TFree(pvData); + return RC_FAIL; + } + + if(RC_SUCC != pthread_rwlock_wrlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DOWR_ERR; + TFree(pvData); + return RC_FAIL; + } + + pstSavm->m_lEffect = 0; + pvCond = pstSavm->pstVoid; + pstSavm->m_lEType = EXE_PLAN_GRP; + for(pstList = (SHList *)pGetNode(pvAddr, pstHash->m_lData); SELF_POS_UNUSE != pstList->m_lPos; + pstList = (SHList *)pGetNode(pvAddr, lNext)) + { + lNext = pstList->m_lNext; + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pvCond)) + { + if(SELF_POS_UNUSE == pstList->m_lNext) break; + continue; + } + + memcpy(pvData, pstTruck->m_pvData, lGetRowSize(t)); + if(RC_FAIL == lMergeTruck(pstSavm, &pstSavm->stUpdt, pvUpdate, pvData)) + goto HASH_ERROR; + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pPickIndex(lGetGrpNum(t), pGetTblGrp(t), pvData, szIdx)) + { + pstSavm->m_lErrno = IDX_FIELD_NIL; + goto HASH_ERROR; + } + + pstSavm->m_lEffect ++; + pstSavm->pstVoid = pvData; + lIdx = uGetHash(szIdx, lGetGrpLen(t)) % ((TblDef *)pvAddr)->m_lMaxRow; + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NULL); + if(HAVE_UNIQ_IDX(t)) + { + if(RC_SUCC != __lIndexUpdate(pstSavm, pvAddr, t, pstTruck, pstList->m_lData)) + { + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NULL); + goto HASH_ERROR; + } + } + + // Index does not match, rebuild inde + if(lOld != lIdx) + { + -- ((TblDef *)pvAddr)->m_lValid; + lOffset = lGetListOfs(t) + ((TblDef *)pvAddr)->m_lValid * sizeof(SHList); + if(RC_SUCC != lReleaseList(pvAddr, t, pstHash, pstList, lOffset, &lNext)) + { + ((TblDef *)pvAddr)->m_lValid ++; + pstSavm->m_lErrno = SVR_EXCEPTION; + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NRML); + goto HASH_ERROR; + } + + lOffset = ((TblDef *)pvAddr)->m_lGroupPos + lIdx * sizeof(SHTree); + if(NULL == (pstTree = (SHTree *)(pvAddr + lOffset))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NRML); + goto HASH_ERROR; + } + + if(RC_SUCC != __lInsertHash(pstSavm, pvAddr, t, pstTree, lOffset, &pstTruck)) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NRML); + goto HASH_ERROR; + } + + ((TblDef *)pvAddr)->m_lValid ++; + } + if(RC_SUCC != lRecordWork(pstSavm, pstTruck->m_pvData, OPERATE_UPDATE)) + goto HASH_ERROR; + + memcpy(pstTruck->m_pvData, pvData, lGetRowSize(t)); + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NRML); + + if(FIRST_ROW & pstSavm->lFind) break; + } + pthread_rwlock_unlock(prwLock); + TFree(pvData); + + if(0 == pstSavm->m_lEffect) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + return RC_SUCC; + +HASH_ERROR: + pthread_rwlock_unlock(prwLock); + TFree(pvData); + return RC_FAIL; +} + +/************************************************************************************************* + description:Update record truck + parameters: + pstSavm --stvm handle + pstAddr --table handle + t --table + pvUpdate --update date + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lTruckUpdate(SATvm *pstSavm, void *pvAddr, TABLE t, void *pvUpdate) +{ + long lRet = RC_SUCC; + SHTruck *pstTruck = NULL; + void *pvData = NULL, *pvCond; + size_t lRow, lOffset = lGetTblData(t); + RWLock *prwLock = (RWLock *)pGetRWLock(pvAddr); + + if(NULL == (pvData = (void *)malloc(lGetRowSize(t)))) + { + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + if(RC_SUCC != pthread_rwlock_wrlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DOWR_ERR; + TFree(pvData); + return RC_FAIL; + } + + pstSavm->m_lEffect = 0; + pvCond = pstSavm->pstVoid; + pstSavm->m_lEType = EXE_PLAN_ALL; + pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset); + for(lRow = 0; (lRow < ((TblDef *)pvAddr)->m_lValid) && (lOffset < lGetTableSize(t)); + pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset)) + { + if(IS_TRUCK_NULL(pstTruck)) + { + lOffset += lGetRowTruck(t); + continue; + } + + lRow ++; + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pvCond)) + { + lOffset += lGetRowTruck(t); + continue; + } + + memcpy(pvData, pstTruck->m_pvData, lGetRowSize(t)); + if(RC_FAIL == lMergeTruck(pstSavm, &pstSavm->stUpdt, pvUpdate, pvData)) + goto TRUCK_ERROR; + + pstSavm->m_lEffect ++; + pstSavm->pstVoid = pvData; + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NULL); + if(HAVE_UNIQ_IDX(t)) + { + if(RC_SUCC != __lIndexUpdate(pstSavm, pvAddr, t, pstTruck, lOffset)) + { + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NRML); + goto TRUCK_ERROR; + } + } + + if(HAVE_NORL_IDX(t)) + lRet = __lUpdateGroup(pstSavm, pvAddr, t, pstTruck, lOffset); + else if(HAVE_HASH_IDX(t)) + lRet = __lUpdateHash(pstSavm, pvAddr, t, pstTruck, lOffset); + SET_DATA_TRUCK(pstTruck, DATA_TRUCK_NRML); + if(RC_SUCC != lRet) + goto TRUCK_ERROR; + + if(RC_SUCC != lRecordWork(pstSavm, pstTruck->m_pvData, OPERATE_UPDATE)) + goto TRUCK_ERROR; + + memcpy(pstTruck->m_pvData, pvData, lGetRowSize(t)); + if(FIRST_ROW & pstSavm->lFind) break; + lOffset += lGetRowTruck(t); + } + + pthread_rwlock_unlock(prwLock); + TFree(pvData); + if(0 == pstSavm->m_lEffect) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + return RC_SUCC; + +TRUCK_ERROR: + pthread_rwlock_unlock(prwLock); + TFree(pvData); + return RC_FAIL; +} + +/************************************************************************************************* + description:API - Update + parameters: + pstSavm --stvm handle + pvUpdate --update date + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lUpdate(SATvm *pstSavm, void *pvUpdate) +{ + long lRet; + void *pvData; + RunTime *pstRun = NULL; + + if(!pstSavm || !pvUpdate) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pvData = pstSavm->pstVoid; + if(NULL == (pstRun = (RunTime *)pInitMemTable(pstSavm, pstSavm->tblName))) + return RC_FAIL; + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + Tremohold(pstSavm, pstRun); + return _lUpdateByRt(pstSavm, pvUpdate); + } + + if(HAVE_UNIQ_IDX(pstSavm->tblName)) + { + lRet = _lUpdateIndex(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, pvUpdate); + if(RC_CONTU != lRet) + { + vTblDisconnect(pstSavm, pstSavm->tblName); + pstSavm->pstVoid = pvData; + return lRet; + } + } + + if(HAVE_NORL_IDX(pstSavm->tblName)) + { + lRet = _lUpdateGroup(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, pvUpdate); + if(RC_CONTU != lRet) + { + vTblDisconnect(pstSavm, pstSavm->tblName); + pstSavm->pstVoid = pvData; + return lRet; + } + } + else if(HAVE_HASH_IDX(pstSavm->tblName)) + { + lRet = _lUpdateHash(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, pvUpdate); + if(RC_CONTU != lRet) + { + vTblDisconnect(pstSavm, pstSavm->tblName); + pstSavm->pstVoid = pvData; + return lRet; + } + } + + lRet = _lTruckUpdate(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, pvUpdate); + vTblDisconnect(pstSavm, pstSavm->tblName); + pstSavm->pstVoid = pvData; + return lRet; +} + +/************************************************************************************************* + description:Registry and table fields + parameters: + pstSavm --stvm handle + pstRun --table handle + t --table + lType + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lRegisterTable(SATvm *pstSavm, RunTime *pstRun, TABLE t, long lType) +{ + TIndex stIndex; + TBoot *pstBoot = (TBoot *)pBootInitial(); + + if(TYPE_CLIENT != lType) return RC_SUCC; + + if(RC_SUCC != lInitSATvm(pstSavm, SYS_TVM_INDEX)) + return RC_FAIL; + + if(RC_FAIL == (pstSavm->m_ySey = yGetIPCPath(pstSavm, IPC_SEM))) + return RC_FAIL; + + pstRun->m_semID = semget(pstSavm->m_ySey, pstBoot->m_lMaxTable, IPC_CREAT|0660); + + conditinit(pstSavm, stIndex, SYS_TVM_INDEX); + stIndex.m_lValid = 0; + stIndex.m_yKey = 0; + stIndex.m_table = t; + stIndex.m_lType = lType; + stIndex.m_lMaxRows = lGetTblRow(t); + stIndex.m_lRowSize = lGetRowSize(t); + stIndex.m_shmID = pstRun->m_shmID; + stIndex.m_semID = pstRun->m_semID; + stIndex.m_lLocal = RES_LOCAL_SID; + stIndex.m_lPers = lGetPermit(t); + + strncpy(stIndex.m_szOwner, pstSavm->m_szNode, sizeof(stIndex.m_szOwner)); + strncpy(stIndex.m_szTime, sGetUpdTime(), sizeof(stIndex.m_szTime)); + strncpy(stIndex.m_szTable, sGetTableName(t), sizeof(stIndex.m_szTable)); + strncpy(stIndex.m_szPart, sGetTablePart(t, pstSavm->m_szNode), sizeof(stIndex.m_szPart)); + + if(RC_SUCC != lInsert(pstSavm)) + { + if(UNIQ_IDX_REPT == pstSavm->m_lErrno) + pstSavm->m_lErrno = TBL_ARD_EXIST; + return RC_FAIL; + } + + if(RC_SUCC != lInsertField(pstSavm, t)) + return RC_FAIL; + + if(TVM_BOOT_SIMPLE != pstBoot->m_lBootType) + lRefreshNotify(pstSavm, pstBoot->m_lBootPort); + return RC_SUCC; +} + +/************************************************************************************************* + description:Define the customer table + parameters: + pstSavm --stvm handle + t --table + lRow --table maxrows + bCreate --create type + lType --table type + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lCustomTable(SATvm *pstSavm, TABLE t, size_t lRow, bool bCreate, long lType) +{ + RWAttr attr; + RunTime *pstRun = NULL; + RWLock *prwLock = NULL; + + pstSavm->tblName = t; + ((TblDef *)pGetTblDef(t))->m_lTable = lInitialTable(t, lRow); + if(NULL == (pstRun = (RunTime *)pCreateBlock(pstSavm, t, ((TblDef *)pGetTblDef(t))->m_lTable, + bCreate))) + return RC_FAIL; + + // After the memory is created, it will initialize the index information + if(RC_SUCC != lInitailTree(pstSavm, (void *)pGetNode(pstRun->m_pvAddr, lGetIdxPos(t)), t)) + return RC_FAIL; + + if(RC_SUCC != lInitailGroup(pstSavm, (void *)pGetNode(pstRun->m_pvAddr, lGetGrpPos(t)), t)) + return RC_FAIL; + + memcpy(pstRun->m_pvAddr, (void *)pGetTblDef(t), sizeof(TblDef)); + prwLock = (RWLock *)pGetRWLock(pstRun->m_pvAddr); + pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); + pthread_rwlock_init(prwLock, &attr); + + memset(pstRun->m_pvAddr + lGetTblData(t), 0, lGetTableSize(t) - lGetTblData(t)); + vTblDisconnect(pstSavm, t); + + if(RC_SUCC != lRegisterTable(pstSavm, pstRun, t, lType)) + { + shmctl(pstRun->m_shmID, IPC_RMID, NULL); + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:create table + parameters: + pstSavm --stvm handle + t --table + lRow --table maxrows + bCreate --create type + lType --table type + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lCreateTable(SATvm *pstSavm, TABLE t, size_t lRow, bool bCreate, long lType, + TCREATE pfCreateFunc) +{ + long lRet; + + if(!pstSavm || lRow <= 0) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + vInitTblDef(t); + pstSavm->tblName = t; + switch(t) + { + case SYS_TVM_INDEX: + lRet = lCreateTvmIndex(); + break; + case SYS_TVM_FIELD: + lRet = lCreateTvmField(); + break; + case SYS_TVM_DOMAIN: + lRet = lCreateTvmDomain(); + break; + case SYS_TVM_SEQUE: + lRet = lCreateTvmSeque(); + break; + default: + if(!pfCreateFunc) + return RC_SUCC; + + lRet = pfCreateFunc(t); + break; + } + if(RC_SUCC != lRet) return lRet; + + return _lCustomTable(pstSavm, t, lRow, bCreate, lType); +} + +/************************************************************************************************* + description:Create a sequence + parameters: + pstSavm --stvm handle + pszSQName --SQL name + uIncre --increment + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lCreateSeque(SATvm *pstSavm, char *pszSQName, uint uIncre) +{ + TSeque stSeque; + + if(RC_SUCC != lInitSATvm(pstSavm, SYS_TVM_SEQUE)) + return RC_FAIL; + + conditinit(pstSavm, stSeque, SYS_TVM_SEQUE); + strncpy(stSeque.m_szSQName, pszSQName, sizeof(stSeque.m_szSQName)); + stSeque.m_uIncrement = uIncre > 0 ? uIncre : 1; + return lInsert(pstSavm); +} + +/************************************************************************************************* + description:Set the starting value of the sequence + parameters: + pstSavm --stvm handle + pszSQName --SQL name + uIncre --increment + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lSetSequence(SATvm *pstSavm, char *pszSQName, ulong uStart) +{ + TSeque stSeque; + SHTree *pstTree = NULL; + RunTime *pstRun = NULL; + RWLock *prwLock = NULL; + SHTruck *pstTruck = NULL; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + memset(&stSeque, 0, sizeof(stSeque)); + strncpy(stSeque.m_szSQName, pszSQName, sizeof(stSeque.m_szSQName)); + if(RC_SUCC != lInitSATvm(pstSavm, SYS_TVM_SEQUE)) + return RC_FAIL; + + pstSavm->lSize = sizeof(TSeque); + if(NULL == (pstRun = (RunTime *)pInitMemTable(pstSavm, SYS_TVM_SEQUE))) + return RC_FAIL; + + prwLock = (RWLock *)pGetRWLock(pstRun->m_pvAddr); + if(RC_SUCC != pthread_rwlock_wrlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DORD_ERR; + vTblDisconnect(pstSavm, SYS_TVM_SEQUE); + return RC_FAIL; + } + + if(NULL == (pstTree = (SHTree *)pGetNode(pstRun->m_pvAddr, + ((TblDef *)pstRun->m_pvAddr)->m_lTreeRoot))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + pthread_rwlock_unlock(prwLock); + vTblDisconnect(pstSavm, SYS_TVM_SEQUE); + return RC_FAIL; + } + + pstTree = (SHTree *)pSearchTree(pstRun->m_pvAddr, pstTree, stSeque.m_szSQName, + lGetIdxLen(SYS_TVM_SEQUE)); + if(!pstTree) + { + pthread_rwlock_unlock(prwLock); + vTblDisconnect(pstSavm, SYS_TVM_SEQUE); + pstSavm->m_lErrno = SEQ_NOT_FOUND; + return RC_FAIL; + } + + pstTruck = (PSHTruck)pGetNode(pstRun->m_pvAddr, pstTree->m_lData); + pstTruck->m_lTimes = uStart; + pthread_rwlock_unlock(prwLock); + vTblDisconnect(pstSavm, SYS_TVM_SEQUE); + + return RC_SUCC; +} + +/************************************************************************************************* + description:select seque + parameters: + pstSavm --stvm handle + pszSQName --SQL name + pulNumber --number + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lSelectSeque(SATvm *pstSavm, char *pszSQName, ulong *pulNumber) +{ + TSeque stSeque; + SHTree *pstTree = NULL; + RunTime *pstRun = NULL; + RWLock *prwLock = NULL; + SHTruck *pstTruck = NULL; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + memset(&stSeque, 0, sizeof(stSeque)); + strncpy(stSeque.m_szSQName, pszSQName, sizeof(stSeque.m_szSQName)); + if(RC_SUCC != lInitSATvm(pstSavm, SYS_TVM_SEQUE)) + return RC_FAIL; + + pstSavm->lSize = sizeof(TSeque); + if(NULL == (pstRun = (RunTime *)pInitMemTable(pstSavm, SYS_TVM_SEQUE))) + return RC_FAIL; + + prwLock = (RWLock *)pGetRWLock(pstRun->m_pvAddr); + if(RC_SUCC != pthread_rwlock_wrlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DORD_ERR; + vTblDisconnect(pstSavm, SYS_TVM_SEQUE); + return RC_FAIL; + } + + if(NULL == (pstTree = (SHTree *)pGetNode(pstRun->m_pvAddr, + ((TblDef *)pstRun->m_pvAddr)->m_lTreeRoot))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + pthread_rwlock_unlock(prwLock); + vTblDisconnect(pstSavm, SYS_TVM_SEQUE); + return RC_FAIL; + } + + pstTree = (SHTree *)pSearchTree(pstRun->m_pvAddr, pstTree, stSeque.m_szSQName, + lGetIdxLen(SYS_TVM_SEQUE)); + if(!pstTree) + { + pthread_rwlock_unlock(prwLock); + vTblDisconnect(pstSavm, SYS_TVM_SEQUE); + pstSavm->m_lErrno = SEQ_NOT_FOUND; + return RC_FAIL; + } + + pstTruck = (PSHTruck)pGetNode(pstRun->m_pvAddr, pstTree->m_lData); + pstTruck->m_lTimes += ((TSeque *)pstTruck->m_pvData)->m_uIncrement; + *pulNumber = pstTruck->m_lTimes; + pthread_rwlock_unlock(prwLock); + vTblDisconnect(pstSavm, SYS_TVM_SEQUE); + pstSavm->m_lEffect = 1; + + return RC_SUCC; +} + +/************************************************************************************************* + description:shut down STVM + parameters: + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lShutdownTvm() +{ + size_t lOut = 0; + TIndex *pstIndex = NULL; + RunTime *pstRun = NULL; + RWLock *prwLock = NULL; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + if(RC_SUCC != lExportTable(SYS_TVM_INDEX, &lOut, (void *)&pstIndex)) + return RC_FAIL; + + if(0 == lOut) return RC_SUCC; + + // Remove from the back forward, root index table last deleted + for(lOut; 0 < lOut; -- lOut) + { + if(RES_REMOT_SID == pstIndex[lOut - 1].m_lLocal) + continue; + + vForceDisconnect(pstSavm, pstIndex[lOut - 1].m_table); + pstRun = (RunTime *)pGetRunTime(pstSavm, pstIndex[lOut - 1].m_table); + pstRun->m_shmID = pstIndex[lOut - 1].m_shmID; + if(NULL == (pstRun = (RunTime *)pInitHitTest(pstSavm, pstIndex[lOut - 1].m_table))) + { + TFree(pstIndex); + return RC_FAIL; + } + + if(RES_REMOT_SID == pstRun->m_lLocal) + continue; + + prwLock = (RWLock *)pGetRWLock(pstRun->m_pvAddr); + pthread_rwlock_destroy(prwLock); + vForceDisconnect(pstSavm, pstIndex[lOut - 1].m_table); + + // The table is deleted, whether successful or not + shmctl(pstIndex[lOut - 1].m_shmID, IPC_RMID, NULL); + } + semctl(pstIndex[0].m_semID, 0, IPC_RMID, NULL); + TFree(pstIndex); + + return RC_SUCC; +} + +/************************************************************************************************* + description:initial domain + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lInitDomain(SATvm *pstSavm) +{ + long i, lCount = 0; + TDomain *pstDomain = NULL; + TIndex stIndex, *pstIndex = NULL; + + if(RC_SUCC != lGetDomainIndex(pstSavm, &lCount, &pstIndex)) + return RC_FAIL; + + insertinit(pstSavm, pstIndex[i], SYS_TVM_INDEX) + for(i = 0; i < lCount; i ++) + { + pstIndex[i].m_lValid = 0; + pstIndex[i].m_lType = TYPE_CLIENT; + pstIndex[i].m_lLocal = RES_REMOT_SID; + pstIndex[i].m_lState = RESOURCE_STOP; + pstIndex[i].m_lPers = OPERATE_NULL; + strncpy(pstIndex[i].m_szTime, sGetUpdTime(), sizeof(pstIndex[i].m_szTime)); + + pstSavm->pstVoid = (void *)&pstIndex[i]; + if(RC_SUCC != lInsert(pstSavm)) + { + TFree(pstIndex); + return RC_FAIL; + } + } + lCount = 0; + TFree(pstIndex); + + if(RC_SUCC != lGetDomainTable(pstSavm, &lCount, &pstDomain)) + return RC_FAIL; + + for(i = 0; i < lCount; i ++) + { + pstDomain[i].m_lStatus = RESOURCE_STOP; + + insertinit(pstSavm, pstDomain[i], SYS_TVM_DOMAIN) + if(RC_SUCC != lInsert(pstSavm)) + { + TFree(pstDomain); + return RC_FAIL; + } + } + + lCount = 0; + TFree(pstDomain); + + return RC_SUCC; +} + +/************************************************************************************************* + description:Get table permissions + parameters: + pstSavm --stvm handle + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lGetPermit(TABLE t) +{ + TIndex *pstIndex = NULL; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + long i, lCount = 0, lPers = OPERATE_DEFAULT; + + if(RC_SUCC != lGetLocalIndex(pstSavm, &lCount, &pstIndex)) + return lPers; + + for(i = 0; i < lCount; i ++) + { + if(t == pstIndex[i].m_table) + { + lPers = pstIndex[i].m_lPers; + break; + } + } + TFree(pstIndex); + + return lPers; +} + +/************************************************************************************************* + description:startup STVM + parameters: + pstBoot --boot paramter + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lStartupTvm(TBoot *pstBoot) +{ + long semID; + TIndex stIndex; + RunTime *pstRun = NULL; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + memset(&stIndex, 0, sizeof(TIndex)); + if(RC_SUCC != _lCreateTable(pstSavm, SYS_TVM_INDEX, pstBoot->m_lMaxTable, TRUE, + TYPE_SYSTEM, NULL)) + return RC_FAIL; + + pstRun = (RunTime *)pGetRunTime(pstSavm, SYS_TVM_INDEX); + if(RC_SUCC != lCreateSems(pstSavm, pstRun, pstBoot->m_lMaxTable, SEM_INIT)) + return RC_FAIL; + + semID = pstRun->m_semID; + stIndex.m_lValid = 0; + stIndex.m_semID = semID; + stIndex.m_lType = TYPE_SYSTEM; + stIndex.m_table = SYS_TVM_INDEX; + stIndex.m_yKey = pstSavm->m_yKey; + stIndex.m_shmID = pstRun->m_shmID; + stIndex.m_lMaxRows = pstBoot->m_lMaxTable; + stIndex.m_lLocal = RES_LOCAL_SID; + stIndex.m_lState = RESOURCE_STOP; + stIndex.m_lPers = OPERATE_NULL; + stIndex.m_lRowSize = lGetRowSize(SYS_TVM_INDEX); + strncpy(stIndex.m_szTime, sGetUpdTime(), sizeof(stIndex.m_szTime)); + strncpy(stIndex.m_szOwner, pstBoot->m_szNode, sizeof(stIndex.m_szOwner)); + strncpy(stIndex.m_szPart, pstBoot->m_szNode, sizeof(stIndex.m_szPart)); + strncpy(stIndex.m_szTable, sGetTableName(SYS_TVM_INDEX), sizeof(stIndex.m_szTable)); + + /* The table was initialized when it was created + if(NULL == (pstSavm = (SATvm *)pInitSATvm(SYS_TVM_INDEX))) + return RC_FAIL; + */ + + insertinit(pstSavm, stIndex, SYS_TVM_INDEX) + if(RC_SUCC != lInsert(pstSavm)) + return RC_FAIL; + + memset(&stIndex, 0, sizeof(TIndex)); + if(RC_SUCC != _lCreateTable(pstSavm, SYS_TVM_FIELD, pstBoot->m_lMaxField, FALSE, + TYPE_INCORE, NULL)) + return RC_FAIL; + + pstRun = (RunTime *)pGetRunTime(pstSavm, SYS_TVM_FIELD); + stIndex.m_lValid = 0; + stIndex.m_semID = semID; + stIndex.m_lType = TYPE_INCORE; + stIndex.m_lLocal = RES_LOCAL_SID; + stIndex.m_table = SYS_TVM_FIELD; + stIndex.m_yKey = pstSavm->m_yKey; + stIndex.m_shmID = pstRun->m_shmID; + stIndex.m_lState = RESOURCE_STOP; + stIndex.m_lPers = OPERATE_NULL; + stIndex.m_lRowSize = lGetRowSize(SYS_TVM_FIELD); + strncpy(stIndex.m_szTime, sGetUpdTime(), sizeof(stIndex.m_szTime)); + strncpy(stIndex.m_szOwner, pstBoot->m_szNode, sizeof(stIndex.m_szOwner)); + strncpy(stIndex.m_szPart, pstBoot->m_szNode, sizeof(stIndex.m_szPart)); + strncpy(stIndex.m_szTable, sGetTableName(SYS_TVM_FIELD), sizeof(stIndex.m_szTable)); + + insertinit(pstSavm, stIndex, SYS_TVM_INDEX) + if(RC_SUCC != lInsert(pstSavm)) + return RC_FAIL; + + if(RC_SUCC != lInsertField(pstSavm, SYS_TVM_FIELD)) + return RC_FAIL; + + memset(&stIndex, 0, sizeof(TIndex)); + if(RC_SUCC != _lCreateTable(pstSavm, SYS_TVM_DOMAIN, pstBoot->m_lMaxDomain, FALSE, + TYPE_INCORE, NULL)) + return RC_FAIL; + + pstRun = (RunTime *)pGetRunTime(pstSavm, SYS_TVM_DOMAIN); + stIndex.m_lValid = 0; + stIndex.m_semID = semID; + stIndex.m_lType = TYPE_INCORE; + stIndex.m_lLocal = RES_LOCAL_SID; + stIndex.m_table = SYS_TVM_DOMAIN; + stIndex.m_yKey = pstSavm->m_yKey; + stIndex.m_shmID = pstRun->m_shmID; + stIndex.m_lState = RESOURCE_STOP; + stIndex.m_lPers = OPERATE_NULL; + stIndex.m_lRowSize = lGetRowSize(SYS_TVM_DOMAIN); + strncpy(stIndex.m_szTime, sGetUpdTime(), sizeof(stIndex.m_szTime)); + strncpy(stIndex.m_szOwner, pstBoot->m_szNode, sizeof(stIndex.m_szOwner)); + strncpy(stIndex.m_szPart, pstBoot->m_szNode, sizeof(stIndex.m_szPart)); + strncpy(stIndex.m_szTable, sGetTableName(SYS_TVM_DOMAIN), sizeof(stIndex.m_szTable)); + + insertinit(pstSavm, stIndex, SYS_TVM_INDEX) + if(RC_SUCC != lInsert(pstSavm)) + return RC_FAIL; + + if(RC_SUCC != lInsertField(pstSavm, SYS_TVM_DOMAIN)) + return RC_FAIL; + + memset(&stIndex, 0, sizeof(TIndex)); + if(RC_SUCC != _lCreateTable(pstSavm, SYS_TVM_SEQUE, pstBoot->m_lMaxSeque, FALSE, + TYPE_INCORE, NULL)) + return RC_FAIL; + + pstRun = (RunTime *)pGetRunTime(pstSavm, SYS_TVM_SEQUE); + stIndex.m_lValid = 0; + stIndex.m_semID = semID; + stIndex.m_lType = TYPE_INCORE; + stIndex.m_lLocal = RES_LOCAL_SID; + stIndex.m_table = SYS_TVM_SEQUE; + stIndex.m_yKey = pstSavm->m_yKey; + stIndex.m_shmID = pstRun->m_shmID; + stIndex.m_lState = RESOURCE_STOP; + stIndex.m_lPers = OPERATE_NULL; + stIndex.m_lRowSize = lGetRowSize(SYS_TVM_SEQUE); + strncpy(stIndex.m_szTime, sGetUpdTime(), sizeof(stIndex.m_szTime)); + strncpy(stIndex.m_szOwner, pstBoot->m_szNode, sizeof(stIndex.m_szOwner)); + strncpy(stIndex.m_szPart, pstBoot->m_szNode, sizeof(stIndex.m_szPart)); + strncpy(stIndex.m_szTable, sGetTableName(SYS_TVM_SEQUE), sizeof(stIndex.m_szTable)); + + insertinit(pstSavm, stIndex, SYS_TVM_INDEX) + if(RC_SUCC != lInsert(pstSavm)) + return RC_FAIL; + + if(RC_SUCC != lInsertField(pstSavm, SYS_TVM_SEQUE)) + return RC_FAIL; + + return lInitDomain(pstSavm); +} + +/************************************************************************************************* + description:API - CreateTable + parameters: + pstSavm --stvm handle + t --table + lRow --table maxrows + pfCreateFunc --table field define + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lCreateTable(SATvm *pstSavm, TABLE t, size_t lRow, TCREATE pfCreateFunc) +{ + return _lCreateTable(pstSavm, t, lRow, FALSE, TYPE_CLIENT, pfCreateFunc); +} + +/************************************************************************************************* + description:Custom template creation + parameters: + pstSavm --stvm handle + t --table + lRow --table maxrows + pstDef --table struck infor + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lCustomTable(SATvm *pstSavm, TABLE t, size_t lRow, TblDef *pstDef) +{ + + memcpy((void *)pGetTblDef(t), (void *)pstDef, sizeof(TblDef)); + + return _lCustomTable(pstSavm, t, lRow, FALSE, TYPE_CLIENT); +} + +/************************************************************************************************* + description:API - lDropTable + parameters: + pstSavm --stvm handle + t --table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lDropTable(SATvm *pstSavm, TABLE t) +{ + TIndex stIndex; + TField stField; + RunTime *pstRun = NULL; + RWLock *prwLock = NULL; + + pstSavm->bSearch = TYPE_SYSTEM; + conditinit(pstSavm, stIndex, SYS_TVM_INDEX) + numberset(pstSavm, stIndex, m_table, t) + numberset(pstSavm, stIndex, m_lType, TYPE_CLIENT) + if(RC_SUCC != lSelect(pstSavm, (void *)&stIndex)) + return RC_FAIL; + + pstRun = (RunTime *)pGetRunTime(pstSavm, t); + if(RES_REMOT_SID == pstRun->m_lLocal) + { + conditinit(pstSavm, stIndex, SYS_TVM_INDEX) + numberset(pstSavm, stIndex, m_table, t) + numberset(pstSavm, stIndex, m_lType, TYPE_CLIENT) + if(RC_SUCC != lDelete(pstSavm)) + return RC_FAIL; + + memset(pstRun, 0, sizeof(RunTime)); + _vDropTableByRt(pstSavm, t); + pstRun->m_lState = RESOURCE_INIT; + return RC_SUCC; + } + + vForceDisconnect(pstSavm, t); + pstRun->m_shmID = stIndex.m_shmID; + if(NULL == (pstRun = (RunTime *)pInitHitTest(pstSavm, t))) + return RC_FAIL; + + prwLock = (RWLock *)pGetRWLock(pstRun->m_pvAddr); + pthread_rwlock_destroy(prwLock); + vForceDisconnect(pstSavm, t); + + // The table is deleted, whether successful or not + shmctl(stIndex.m_shmID, IPC_RMID, NULL); + semctl(stIndex.m_semID, 0, IPC_RMID, 0); + + conditinit(pstSavm, stIndex, SYS_TVM_INDEX) + numberset(pstSavm, stIndex, m_table, t) + numberset(pstSavm, stIndex, m_lType, TYPE_CLIENT) + if(RC_SUCC != lDelete(pstSavm)) return RC_FAIL; + + // Delete the field table + if(RC_SUCC != lInitSATvm(pstSavm, SYS_TVM_FIELD)) + return RC_FAIL; + + conditinit(pstSavm, stField, SYS_TVM_FIELD) + numberset(pstSavm, stField, m_table, t) + if(RC_SUCC != lDelete(pstSavm)) return RC_FAIL; + + memset(pstRun, 0, sizeof(RunTime)); + pstSavm->m_lEffect = 1; + return RC_SUCC; +} + +/************************************************************************************************* + description:Format the data content for export + parameters: + fp --File descriptor + s --data record + lIdx --field number + pstIdx --field key + f --file descriptor + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lExportContext(FILE *fp, char *s, long lIdx, TblKey *pstIdx, char *f) +{ + long i = 0; + + if(!fp || !s || !pstIdx) return RC_FAIL; + + for(i = 0; i < lIdx; i ++) + { + switch(pstIdx[i].m_lAttr) + { + case FIELD_DOUB: + switch(pstIdx[i].m_lLen) + { + case 4: + fprintf(fp, "%.6f", *((float *)(s + pstIdx[i].m_lFrom))); + break; + case 8: + fprintf(fp, "%.6f", *((double *)(s + pstIdx[i].m_lFrom))); + break; + default: + break; + } + break; + case FIELD_LONG: + switch(pstIdx[i].m_lLen) + { + case 2: + fprintf(fp, "%d", *((sint *)(s + pstIdx[i].m_lFrom))); + break; + case 4: + fprintf(fp, "%d", *((int *)(s + pstIdx[i].m_lFrom))); + break; + case 8: + fprintf(fp, "%lld", *((llong *)(s + pstIdx[i].m_lFrom))); + break; + default: + break; + } + break; + case FIELD_CHAR: +// fwrite(s + pstIdx[i].m_lFrom, 1, pstIdx[i].m_lLen, fp); + fprintf(fp, "%s", s + pstIdx[i].m_lFrom); + break; + default: + fprintf(stderr, "Export field attribute exception\n"); + break; + } + fprintf(fp, "%s", f); + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Format the data content into the import + parameters: + s --data line + lIdx --field number + pstIdx --field key + pvOut --format to row record + f --file descriptor + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lImportContext(char *s, long lIdx, TblKey *pstIdx, char *pvOut, char *f) +{ + void *p = NULL; + register long i; + + for(i = 0; i < lIdx; i ++) + { + p = sgetvalue(s, f, i + 1); + + switch(pstIdx[i].m_lAttr) + { + case FIELD_DOUB: + switch(pstIdx[i].m_lLen) + { + case 4: + *((float *)(pvOut + pstIdx[i].m_lFrom)) = atof(p); + break; + case 8: + *((double *)(pvOut + pstIdx[i].m_lFrom)) = atof(p); + break; + default: + break; + } + break; + case FIELD_LONG: + switch(pstIdx[i].m_lLen) + { + case 2: + *((sint *)(pvOut + pstIdx[i].m_lFrom)) = atoi(p); + break; + case 4: + *((int *)(pvOut + pstIdx[i].m_lFrom)) = atoi(p); + break; + case 8: + *((llong *)(pvOut + pstIdx[i].m_lFrom)) = atol(p); + break; + default: + break; + } + break; + case FIELD_CHAR: + memcpy(pvOut + pstIdx[i].m_lFrom, p, pstIdx[i].m_lLen); + break; + default: + break; + } + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:API - CreateTable + parameters: + pstSavm --stvm handle + pszFile --file name + pszFlag --separator + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lImportFile(TABLE t, char *pszFile, char *pszFlag) +{ + FILE *fp = NULL; + char szLine[1024]; + RunTime *pstRun = NULL; + void *pvData = NULL; + RWLock *prwLock = NULL; + long lEffect = 0, lRet = RC_SUCC; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + if(!pszFile || !pszFlag || !strlen(pszFlag)) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + memset(szLine, 0, sizeof(szLine)); + if(NULL == (pstSavm = (SATvm *)pInitSATvm(t))) + return RC_FAIL; + + if(NULL == (pstRun = (RunTime *)pInitHitTest(pstSavm, pstSavm->tblName))) + return RC_FAIL; + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + pstSavm->m_lErrno = RMT_NOT_SUPPT; + return RC_FAIL; + } + + if(NULL == (fp = fopen(pszFile, "rb"))) + { + pstSavm->m_lErrno = FIL_NOT_EXIST; + return RC_FAIL; + } + + if(NULL == (pvData = (void *)malloc(lGetRowSize(t)))) + { + fclose(fp); + pstSavm->m_lErrno = MALLC_MEM_ERR; + return RC_FAIL; + } + + pstSavm->pstVoid = pvData; + pstSavm->lSize = lGetRowSize(t); + prwLock = (RWLock *)pGetRWLock(pstRun->m_pvAddr); + if(RC_SUCC != pthread_rwlock_wrlock(prwLock)) + { + fclose(fp); + TFree(pvData); + pstSavm->m_lErrno = LOCK_DOWR_ERR; + return RC_FAIL; + } + + while(fgets(szLine, sizeof(szLine), fp)) + { + strimcrlf(szLine); + if(!strlen(szLine)) + continue; + + if(lGetTblRow(t) <= ((TblDef *)pstRun->m_pvAddr)->m_lValid) + { + lRet = RC_FAIL; + pstSavm->m_lErrno = DATA_SPC_FULL; + break; + } + + memset(pvData, 0, lGetRowSize(t)); + _lImportContext(szLine, lGetFldNum(t), pGetTblKey(t), pvData, pszFlag); + if(RC_SUCC != (lRet = __lInsert(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, 0))) + break; + + lEffect ++; + memset(szLine, 0, sizeof(szLine)); + if(RC_SUCC != lRecordWork(pstSavm, pstSavm->pstVoid, OPERATE_INSERT)) + break; + } + fclose(fp); + pthread_rwlock_unlock(prwLock); + pstSavm->m_lEffect = lEffect; + vTblDisconnect(pstSavm, pstSavm->tblName); + + TFree(pvData); + return lRet; +} + +/************************************************************************************************* + description:Export the data from the memory table + parameters: + t --table + plOut --plOut + ppsvOut --result data list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lExportTable(TABLE t, size_t *plOut, void **ppsvOut) +{ + long lRet; + RunTime *pstRun = NULL; + SATvm *pstSavm = NULL; + + if(NULL == (pstSavm = (SATvm *)pInitSATvm(t))) + return RC_FAIL; + + if(NULL == (pstRun = (RunTime *)pInitHitTest(pstSavm, t))) + return RC_FAIL; + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + pstSavm->m_lErrno = RMT_NOT_SUPPT; + return RC_FAIL; + } + + pstSavm->pstVoid = NULL; + lRet = _lQueryTruck(pstSavm, pstRun->m_pvAddr, t, plOut, ppsvOut); + vTblDisconnect(pstSavm, pstSavm->tblName); + if(NO_DATA_FOUND == pstSavm->m_lErrno) + return RC_SUCC; + + return lRet; +} + +/************************************************************************************************* + description:Import the data into the memory table + parameters: + t --table + lCount --count + psvData --record list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lImportTable(TABLE t, size_t lCount, void *psvData) +{ + RunTime *pstRun = NULL; + SATvm *pstSavm = NULL; + RWLock *prwLock = NULL; + long i, lRet = RC_SUCC; + + if(!psvData || lCount < 0) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + if(NULL == (pstSavm = (SATvm *)pInitSATvm(t))) + return RC_FAIL; + + if(NULL == (pstRun = (RunTime *)pInitHitTest(pstSavm, t))) + return RC_FAIL; + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + pstSavm->m_lErrno = RMT_NOT_SUPPT; + return RC_FAIL; + } + + prwLock = (RWLock *)pGetRWLock(pstRun->m_pvAddr); + if(RC_SUCC != pthread_rwlock_wrlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DOWR_ERR; + return RC_FAIL; + } + + for(i = 0; i < lCount; i ++) + { + pstSavm->pstVoid = psvData + lGetRowSize(t) * i; + if(RC_SUCC != (lRet = __lInsert(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, 0))) + break; + } + + pthread_rwlock_unlock(prwLock); + vTblDisconnect(pstSavm, pstSavm->tblName); + + return lRet; +} + +/************************************************************************************************* + description:Export the memory table to a file + parameters: + t --table + pszFile --file name + pszFlag --separator + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lExportFile(TABLE t, char *pszFile, char *pszFlag) +{ + FILE *fp = NULL; + char szLine[1024]; + void *psvOut = NULL; + RunTime *pstRun = NULL; + SATvm *pstSavm = NULL; + + if(!pszFile || !pszFlag || !strlen(pszFlag)) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + memset(szLine, 0, sizeof(szLine)); + if(NULL == (pstSavm = (SATvm *)pInitSATvm(t))) + return RC_FAIL; + + if(NULL == (fp = fopen(pszFile, "wb"))) + { + pstSavm->m_lErrno = FIL_NOT_EXIST; + return RC_FAIL; + } + + pstSavm->pstVoid = NULL; + if(NULL == (pstRun = (RunTime *)pInitHitTest(pstSavm, t))) + { + fclose(fp); + return RC_FAIL; + } + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + pstSavm->m_lErrno = RMT_NOT_SUPPT; + return RC_FAIL; + } + + if(NULL == (psvOut = (char *)malloc(lGetRowSize(t)))) + { + fclose(fp); + vTblDisconnect(pstSavm, pstSavm->tblName); + return RC_FAIL; + } + + pstRun->m_lCurLine = 1; + pstRun->m_lCurType = EXE_PLAN_ALL; + pstRun->m_pvCurAddr = pstRun->m_pvAddr; + while(RC_NOTFOUND != _llFetchTruck(pstSavm, pstRun, t, psvOut)) + { + _lExportContext(fp, psvOut, lGetFldNum(t), pGetTblKey(t), pszFlag); + fprintf(fp, "\n"); + } + + fclose(fp); + TFree(psvOut); + vTblDisconnect(pstSavm, pstSavm->tblName); + return RC_SUCC; +} + +/************************************************************************************************* + description:Get the table field + parameters: + t --table + plOut --number + ppstField --out field list + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lGetTblField(TABLE t, size_t *plOut, TField **ppstField) +{ + TField stField; + SATvm *pstSavm = NULL; + + if(NULL == (pstSavm = (SATvm *)pInitSATvm(SYS_TVM_FIELD))) + return RC_FAIL; + + conditinit(pstSavm, stField, SYS_TVM_FIELD) + numberset(pstSavm, stField, m_table, t) + return lQuery(pstSavm, plOut, (void **)ppstField); +} + +/************************************************************************************************* + description:Get the table properties + parameters: + pstSavm --table + pstTable --table name + pszPart --table part + pszIndex --result index + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lGetTblIndex(SATvm *pstSavm, char *pszTable, char *pszPart, TIndex *pstIndex) +{ + TIndex stIndex; + + if(!pszTable || !pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstSavm->bSearch = TYPE_SYSTEM; + conditinit(pstSavm, stIndex, SYS_TVM_INDEX); + stringset(pstSavm, stIndex, m_szPart, pszPart); + stringset(pstSavm, stIndex, m_szTable, pszTable); + numberset(pstSavm, stIndex, m_lLocal, RES_LOCAL_SID); + if(RC_SUCC != lSelect(pstSavm, (void *)pstIndex)) + { + if(NO_DATA_FOUND == pstSavm->m_lErrno) + pstSavm->m_lErrno = TBL_NOT_FOUND; + return RC_FAIL; + } + + return RC_SUCC; +} + +/************************************************************************************************* + description:Update the table partition + parameters: + pstSavm --stvm handle + t --table + pszPart --table part + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lUpdIndexPart(SATvm *pstSavm, TABLE t, char *pszPart) +{ + TIndex stIndex, stUpdate; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstSavm->bSearch = TYPE_SYSTEM; + updateinit(stUpdate); + conditinit(pstSavm, stIndex, SYS_TVM_INDEX); + numberset(pstSavm, stIndex, m_table, t) + numberset(pstSavm, stIndex, m_lLocal, RES_LOCAL_SID); + + stringupd(pstSavm, stUpdate, m_szPart, pszPart); + return lUpdate(pstSavm, &stUpdate); +} + +/************************************************************************************************* + description:Does the table exist + parameters: + t --table + return: + true --success + false --failure + *************************************************************************************************/ +bool bTableIsExist(TABLE t) +{ + TIndex stIndex; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + pstSavm->bSearch = TYPE_SYSTEM; + conditinit(pstSavm, stIndex, SYS_TVM_INDEX) + numberset(pstSavm, stIndex, m_table, t) + if(RC_SUCC != lSelect(pstSavm, (void *)&stIndex)) + return false; + + return true; +} + +/************************************************************************************************* + description:API - renametable + parameters: + pstSavm --stvm handle + to --old table + tn --new table + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lRenameTable(SATvm *pstSavm, TABLE to, TABLE tn) +{ + RunTime *pstRun = NULL; + TIndex stIndex, stNIdx; + TField stField, stNFld; + + pstSavm->bSearch = TYPE_SYSTEM; + updateinit(stNIdx); + conditinit(pstSavm, stIndex, SYS_TVM_INDEX); + numberset(pstSavm, stIndex, m_table, to); + numberupd(pstSavm, stNIdx, m_table, tn); + + if(RC_SUCC != lUpdate(pstSavm, &stNIdx)) + return RC_FAIL; + + _lRenameTableByRt(pstSavm, to, tn); + + memcpy((void *)pGetRunTime(pstSavm, tn), (void *)pGetRunTime(pstSavm, to), sizeof(RunTime)); + if(RC_SUCC != lInitSATvm(pstSavm, tn)) + return RC_FAIL; + + if(NULL == (pstRun = (RunTime *)pInitHitTest(pstSavm, pstSavm->tblName))) + return RC_FAIL; + + if(RES_REMOT_SID == pstRun->m_lLocal) + return RC_SUCC; + + ((TblDef *)pstRun->m_pvAddr)->m_table = tn; + vTblDisconnect(pstSavm, pstSavm->tblName); + memset((void *)pGetRunTime(pstSavm, to), 0, sizeof(RunTime)); + if(RC_SUCC != lInitSATvm(pstSavm, SYS_TVM_FIELD)) + return RC_FAIL; + + updateinit(stNFld); + conditinit(pstSavm, stField, SYS_TVM_FIELD); + numberset(pstSavm, stField, m_table, to); + numberupd(pstSavm, stNFld, m_table, tn); + return lUpdate(pstSavm, &stNFld); +} + +/************************************************************************************************* + description:Does the table part exist + parameters: + t --table + return: + true --success + false --failure + *************************************************************************************************/ +bool bPartIsExist(char *pszTable, char *pszPart) +{ + TIndex stIndex; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + pstSavm->bSearch = TYPE_SYSTEM; + conditinit(pstSavm, stIndex, SYS_TVM_INDEX) + stringset(pstSavm, stIndex, m_szPart, pszPart) + stringset(pstSavm, stIndex, m_szTable, pszTable) + numberset(pstSavm, stIndex, m_lLocal, RES_LOCAL_SID) + if(RC_SUCC != lSelect(pstSavm, (void *)&stIndex)) + { + if(MORE_ROWS_SEL == pstSavm->m_lErrno) + return true; + + return false; + } + + return true; +} + +/************************************************************************************************* + description:Gets the table maxrows + parameters: + pstSavm --stvm handle + t --table + return: + true --success + false --failure + *************************************************************************************************/ +long lTableMaxRow(SATvm *pstSavm, TABLE t) +{ + TIndex stIndex; + + if(!pstSavm) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + pstSavm->bSearch = TYPE_SYSTEM; + conditinit(pstSavm, stIndex, SYS_TVM_INDEX) + numberset(pstSavm, stIndex, m_table, t) + if(RC_SUCC != lSelect(pstSavm, (void *)&stIndex)) + return RC_FAIL; + + return stIndex.m_lMaxRows; +} + +/************************************************************************************************* + description:Whether or not the STVM is started + parameters: + t --table + return: + true --yes + false --failed + *************************************************************************************************/ +bool bIsTvmBoot() +{ + RunTime *pstRun = NULL; + SATvm *pstSavm = (SATvm *)pGetSATvm(); + + pstSavm->bSearch = TYPE_SYSTEM; + pstSavm->tblName = SYS_TVM_INDEX; + pstSavm->lSize = sizeof(TIndex); + + pstRun = (RunTime *)pGetRunTime(pstSavm, SYS_TVM_INDEX); + pstRun->m_lLocal = RES_LOCAL_SID; + + if(NULL == (pstRun = (RunTime *)pInitMemTable(pstSavm, pstSavm->tblName))) + return FALSE; + + vTblDisconnect(pstSavm, pstSavm->tblName); + return TRUE; +} + +/************************************************************************************************* + description:Returns the row record of the field's extreme value by index + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + pFdKey --field key + psvOut --result data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lExtremGroup(SATvm *pstSavm, void *pvAddr, TABLE t, FdKey *pFdKey, void *psvOut) +{ + TblKey *pstIdx; + void *pvData = NULL; + SHList *pstList = NULL; + SHTree *pstTree = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + TblKey *pstKey = pGetTblGrp(t); + + if(NULL == (pstIdx = pGetFldKey(t, pFdKey->uFldpos, pFdKey->uFldlen))) + { + pstSavm->m_lErrno = FLD_NOT_EXIST; + return RC_FAIL; + } + + if(NULL == (pstTree = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lGroupRoot))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == pstSavm->pstVoid && 1 == lGetGrpNum(t) && pstKey[0].m_lFrom == pFdKey->uFldpos + && pstKey[0].m_lAttr == FIELD_CHAR) + { + pstSavm->m_lEType = EXE_PLAN_GRP; + if(NULL == (pstTree = (SHTree *)pExtremeTree(pFdKey->uDecorate, pvAddr, pstTree))) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + if(NULL == (pstList = (SHList *)pGetNode(pvData, pstTree->m_lData))) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + memcpy(psvOut + pFdKey->uFldpos, pstTree->m_szIdx, pFdKey->uFldlen); + return RC_SUCC; + } + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetGrpNum(t), pGetTblGrp(t), + pstSavm->pstVoid, szIdx)) + return RC_CONTU; + + if(NULL == (pstList = pSearchGroup(pvAddr, pstTree, szIdx, lGetGrpLen(t)))) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_CONTU; + } + + for(pstSavm->m_lEType = EXE_PLAN_GRP; SELF_POS_UNUSE != pstList->m_lPos; + pstList = (SHList *)pGetNode(pvAddr, pstList->m_lNext)) + { + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + if(RC_MATCH == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + pvData = pvCompExtrem(pstTruck->m_pvData, pvData, pstIdx, pFdKey->uDecorate); + + if(SELF_POS_UNUSE == pstList->m_lNext) break; + } + + if(!pvData) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + memcpy(psvOut + pFdKey->uFldpos, pvData + pFdKey->uFldpos, pFdKey->uFldlen); + return RC_SUCC; +} + +/************************************************************************************************* + description:Returns the row record of the field's extreme value by hash + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + pFdKey --field key + psvOut --result data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lExtremeHash(SATvm *pstSavm, void *pvAddr, TABLE t, FdKey *pFdKey, void *psvOut) +{ + TblKey *pstIdx; + size_t lData, lIdx; + SHTree *pstTree = NULL; + SHList *pstList = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN], *pvData = NULL; + + if(NULL == (pstIdx = pGetFldKey(t, pFdKey->uFldpos, pFdKey->uFldlen))) + { + pstSavm->m_lErrno = FLD_NOT_EXIST; + return RC_FAIL; + } + + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetGrpNum(t), pGetTblGrp(t), + pstSavm->pstVoid, szIdx)) + return RC_CONTU; + + lIdx = uGetHash(szIdx, lGetGrpLen(t)) % ((TblDef *)pvAddr)->m_lMaxRow; + pstTree = pvAddr + ((TblDef *)pvAddr)->m_lGroupRoot + lIdx * sizeof(SHTree); + if(NULL == pstTree || SELF_POS_UNUSE == pstTree->m_lData) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + pstList = (SHList *)pGetNode(pvAddr, pstTree->m_lData); + for(pstSavm->m_lEType = EXE_PLAN_GRP; SELF_POS_UNUSE != pstList->m_lPos; + pstList = (SHList *)pGetNode(pvAddr, pstList->m_lNext)) + { + pstTruck = (PSHTruck)pGetNode(pvAddr, pstList->m_lData); + if(RC_MATCH == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + pvData = pvCompExtrem(pstTruck->m_pvData, pvData, pstIdx, pFdKey->uDecorate); + + if(SELF_POS_UNUSE == pstList->m_lNext) break; + } + + if(!pvData) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + memcpy(psvOut + pFdKey->uFldpos, pvData + pFdKey->uFldpos, pFdKey->uFldlen); + return RC_SUCC; +} + +/************************************************************************************************* + description:Returns the row record of the field's extreme value by truck + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + pFdKey --field key + psvOut --result data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lExtremeTruck(SATvm *pstSavm, void *pvAddr, TABLE t, FdKey *pFdKey, void *psvOut) +{ + TblKey *pstIdx; + void *pvData = NULL; + SHTruck *pstTruck = NULL; + size_t lRow = 0, lOffset = lGetTblData(t); + + if(NULL == (pstIdx = pGetFldKey(t, pFdKey->uFldpos, pFdKey->uFldlen))) + { + pstSavm->m_lErrno = FLD_NOT_EXIST; + return RC_FAIL; + } + + pstSavm->m_lEffect = 0; + pstSavm->m_lEType = EXE_PLAN_ALL; + pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset); + for(lRow = 0; (lRow < ((TblDef *)pvAddr)->m_lValid) && (lOffset < lGetTableSize(t)); + pstTruck = (PSHTruck)pGetNode(pvAddr, lOffset)) + { + if(IS_TRUCK_NULL(pstTruck)) + { + lOffset += lGetRowTruck(t); + continue; + } + + lRow ++; + if(RC_MISMA == lFeildMatch(&pstSavm->stCond, pstTruck->m_pvData, pstSavm->pstVoid)) + { + lOffset += lGetRowTruck(t); + continue; + } + + lOffset += lGetRowTruck(t); + pvData = pvCompExtrem(pstTruck->m_pvData, pvData, pstIdx, pFdKey->uDecorate); + } + + if(!pvData) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + memcpy(psvOut + pFdKey->uFldpos, pvData + pFdKey->uFldpos, pFdKey->uFldlen); + return RC_SUCC; +} + +/************************************************************************************************* + description:Returns the row record of the field's extreme value + parameters: + pstSavm --stvm handle + pvAddr --memory address + t --table + pFdKey --field key + psvOut --result data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lExtremIndex(SATvm *pstSavm, void *pvAddr, TABLE t, FdKey *pFdKey, void *psvOut) +{ + SHTree *pstTree = NULL; + SHTruck *pstTruck = NULL; + char szIdx[MAX_INDEX_LEN]; + TblKey *pstKey = pGetTblIdx(t); + + if(NULL == (pstTree = (SHTree *)pGetNode(pvAddr, ((TblDef *)pvAddr)->m_lTreeRoot))) + { + pstSavm->m_lErrno = SVR_EXCEPTION; + return RC_FAIL; + } + + if(NULL == pstSavm->pstVoid && 1 == lGetIdxNum(t) && pstKey[0].m_lFrom == pFdKey->uFldpos + && pstKey[0].m_lAttr == FIELD_CHAR) + { + pstSavm->m_lEType = EXE_PLAN_IDX; + pstTree = (SHTree *)pExtremeTree(pFdKey->uDecorate, pvAddr, pstTree); + } + else + { + memset(szIdx, 0, sizeof(szIdx)); + if(NULL == pGetIndex(&pstSavm->stCond, lGetIdxNum(t), pGetTblIdx(t), + pstSavm->pstVoid, szIdx)) + return RC_CONTU; + + pstSavm->m_lEType = EXE_PLAN_IDX; + pstTree = (SHTree *)pSearchTree(pvAddr, pstTree, szIdx, lGetIdxLen(t)); + } + if(!pstTree) + { + pstSavm->m_lErrno = NO_DATA_FOUND; + return RC_FAIL; + } + + pstTruck = (PSHTruck)pGetNode(pvAddr, pstTree->m_lData); + memcpy(psvOut + pFdKey->uFldpos, pstTruck->m_pvData + pFdKey->uFldpos, pFdKey->uFldlen); + return RC_SUCC; +} + +/************************************************************************************************* + description:Returns extreme value + parameters: + pstSavm --stvm handle + pstRun --table handle + pFdKey --field key + psvOut --result data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long _lExtreme(SATvm *pstSavm, RunTime *pstRun, FdKey *pFdKey, void *psvOut) +{ + long lRet; + RWLock *prwLock = (RWLock *)pGetRWLock(pstRun->m_pvAddr); + + if(MATCH_MAX != pFdKey->uDecorate && MATCH_MIN != pFdKey->uDecorate) + { + pstSavm->m_lErrno = EXTRE_SET_ERR; + return RC_FAIL; + } + + if(RC_SUCC != pthread_rwlock_rdlock(prwLock)) + { + pstSavm->m_lErrno = LOCK_DORD_ERR; + return RC_FAIL; + } + + if(HAVE_UNIQ_IDX(pstSavm->tblName)) + { + lRet = _lExtremIndex(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, pFdKey, psvOut); + if(RC_CONTU != lRet) + { + pthread_rwlock_unlock(prwLock); + return lRet; + } + } + + if(HAVE_NORL_IDX(pstSavm->tblName)) + { + lRet = _lExtremGroup(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, pFdKey, psvOut); + if(RC_CONTU != lRet) + { + pthread_rwlock_unlock(prwLock); + return lRet; + } + } + else if(HAVE_HASH_IDX(pstSavm->tblName)) + { + lRet = _lExtremeHash(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, pFdKey, psvOut); + if(RC_CONTU != lRet) + { + pthread_rwlock_unlock(prwLock); + return lRet; + } + } + + lRet = _lExtremeTruck(pstSavm, pstRun->m_pvAddr, pstSavm->tblName, pFdKey, psvOut); + pthread_rwlock_unlock(prwLock); + return lRet; +} + +/************************************************************************************************* + description:API - extreme + parameters: + pstSavm --stvm handle + psvOut --result data + return: + RC_SUCC --success + RC_FAIL --failure + *************************************************************************************************/ +long lExtreme(SATvm *pstSavm, void *psvOut) +{ + uint i; + FdCond *pstExm; + RunTime *pstRun = NULL; + + if(!pstSavm || NULL == (pstExm = &pstSavm->stUpdt)) + { + pstSavm->m_lErrno = CONDIT_IS_NIL; + return RC_FAIL; + } + + if(0 == pstExm->uFldcmp) + { + pstSavm->m_lErrno = FIELD_NOT_SET; + return RC_FAIL; + } + + if(NULL == (pstRun = (RunTime *)pInitMemTable(pstSavm, pstSavm->tblName))) + return RC_FAIL; + + if(RES_REMOT_SID == pstRun->m_lLocal) + { + Tremohold(pstSavm, pstRun); + return _lExtremeByRt(pstSavm, psvOut); + } + + for(i = 0; i < pstExm->uFldcmp; i ++) + { + if(RC_FAIL == _lExtreme(pstSavm, pstRun, &pstExm->stFdKey[i], psvOut)) + { + vTblDisconnect(pstSavm, pstSavm->tblName); + return RC_FAIL; + } + } + + vTblDisconnect(pstSavm, pstSavm->tblName); + return RC_SUCC; +} + +/************************************************************************************************* + * debug + *************************************************************************************************/ diff --git a/stvm.conf b/stvm.conf new file mode 100644 index 0000000..c080ef8 --- /dev/null +++ b/stvm.conf @@ -0,0 +1,27 @@ +*GLOBLE +MACHINE="TVM" +MAXTABLE=255 +MAXFILED=3000 +MAXDOMAIN=1024 +MAXSEQUE=1024 +#SERVER_EXEC=4 +SERVER_EXEC=1 +DEPLOY=cluster +#DEPLOY=local +SERVER_PORT=5050 +LOGNAME="/home/stvm/log/stvm.log" + +*LOCAL_RESOURCE +TABLE=15 PERMIT=15 + +*REMOTE_DOMAIN +GROUP=1 DOMAINID="DBS" WSADDR="192.168.5.20:5010" TIMETOUT=2 MAXTRY=3 KEEPALIVE=30 +GROUP=2 DOMAINID="CTS" WSADDR="192.168.5.20:5011" TIMETOUT=2 MAXTRY=3 KEEPALIVE=30 + +*REMOTE_TABLE +TABLE=8 TABLENAME="TBL_BRH_INFO" + MTABLE=17 DOMAINID="DBS" + MTABLE=17 DOMAINID="CTS" +TABLE=9 TABLENAME="TBL_ACCT_INFO" + MTABLE=16 DOMAINID="DBS" + MTABLE=16 DOMAINID="CTS" diff --git a/tbl_user_info.def b/tbl_user_info.def new file mode 100644 index 0000000..ebf7908 --- /dev/null +++ b/tbl_user_info.def @@ -0,0 +1,16 @@ +set TABLE=20 +set TABLESPACE=10000 + +create table TBL_USER_INFO +( + acct_id long, + user_no char(21), + user_type char[2], + user_nm char[81], + user_addr char[161], + user_phone char[31] +); + +-- Create indexes +create unique index (user_no, user_type); +create index (acct_id);