就个人理解而言,fastdb client-server模式,只是在client和server之间添加了一个socket通信,其实操作都是在server端完成的。
但是client-server也有很多好处,其中一个就是可以同一个进程可以同时运用fastdb的无盘模式,和磁盘模式。
当然其中一个模式只是client(比如这个进程开启时需要用无盘模式,将数据全部存入内存,以方便读取,但是记录日志时希望用fastdb记录到库中,这时候就可以另外开始一个server进程,用磁盘模式打开数据库,client连接到server进行insert操作。)
server端代码:
// Sev_log.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "fastdb.h"
class CLog
{
public:
char const* sdatetime;
int4 ProcessNo;
int4 level;
char const* logtext;
char const* ifwrited;
TYPE_DESCRIPTOR((FIELD(sdatetime),
FIELD(logtext),
FIELD(ProcessNo),
FIELD(level),
FIELD(ifwrited)
));
};
#pragma comment(lib, "fastdb.lib")
#pragma comment(lib, "wsock32.lib")
#if THREADS_SUPPORTED && !defined(NO_SOCKETS)
#define SERVER_SUPPORTED 1
#include "server.h"
#else
#define SERVER_SUPPORTED 0
#endif
USE_FASTDB_NAMESPACE
REGISTER(CLog);
int _tmain(int argc, _TCHAR* argv[])
{
//由于不关闭数据库的话,内存占用会越来越大,所以定时重启数据库
while(1)
{
dbDatabase* m_pdb;
m_pdb = NULL;
size_t dbInitSize = 16 * 1024 * 1024; // 16M 指定了数据库文件的初始大小 缺省值为4MB
size_t dbExtensionQuantum = 1 * 1024 * 1024; // 1M 内存分配位图的扩展量子 缺省值为4MB
size_t dbInitIndexSize = 2 * 1024 * 1024; // 2M 指定了初始的索引大小 64K个对象标识符
m_pdb = new dbDatabase(dbDatabase::dbAllAccess, dbExtensionQuantum, dbInitIndexSize);
if(m_pdb->open("test"))
{
m_pdb->scheduleBackup("backup.fdb",2); //定时备份 2s备份一次
char serverURL[64];
strcpy(serverURL, "localhost:2100");
dbServer* server = dbServer::find(serverURL);
if (server == NULL){
/*
dbServer::dbServer(dbDatabase* db,
char const* serverURL,
int optimalNumberOfThreads,
int connectionQueueLen)
*/
server = new dbServer(m_pdb, serverURL, 8);
if (server != NULL){
server->start();
printf("Server started for URL %s\n", serverURL);
}
}
Sleep(60000);
if (server != NULL) {
server->stop();
delete server;
server = NULL;
printf("Server stopped for URL %s\n", serverURL);
}
m_pdb->close();
printf("fastdb close!\n");
}
delete m_pdb;
m_pdb=NULL;
}
return 0;
}
client端代码:
// cli_writelog.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "cli.h"
#include <string.h>
#include <process.h> //windows
//#include "unistd.h" //linux
#include "fastdb.h"
class CLog
{
public:
char const* sdatetime;
int4 ProcessNo;
int4 level;
char const* logtext;
char const* ifwrited;
TYPE_DESCRIPTOR((FIELD(sdatetime),
FIELD(logtext),
FIELD(ProcessNo),
FIELD(level),
FIELD(ifwrited)
));
};
#pragma comment(lib, "cli.lib")
#pragma comment(lib, "wsock32.lib")
USE_FASTDB_NAMESPACE;
#define SUCCESS 1
#define CREATE_STATEMENT_ERROR -1
#define BIND_COLUMN_ERROR -2
#define INSERT_ERROR -3
#define PRECOMMIT_ERROR -4
#define FREE_STATEMENT_ERROR -5
int WriteLog(char *format,...)
{
FILE * fp;
va_list args;
char sLogFile[100];
memset(sLogFile,0,sizeof(sLogFile));
strcpy(sLogFile,"log.txt");
if((fp=fopen(sLogFile,"a+"))==NULL)
{
//printf("open file happened errors!\n");
return -1;
}
va_start(args,format);
vfprintf(fp,format,args);
va_end(args);
fclose(fp);
return 0;
}
int WriteLog(const char* log , const int level , const int session)
{
const int MAXSTRLEN = 256;
int inst_level,inst_processno;
char inst_sdatetime[MAXSTRLEN];
char inst_logs[MAXSTRLEN];
int StatementToInst = cli_statement(session, "insert into CLog");
if (StatementToInst < 0) {
WriteLog("cli_statement failed with code %d\n", StatementToInst);
return CREATE_STATEMENT_ERROR;
}
int rc;//用于返回错误代码
if ((rc = cli_column(StatementToInst, "sdatetime",cli_asciiz, NULL, &inst_sdatetime)) != cli_ok ||
(rc = cli_column(StatementToInst, "logtext", cli_asciiz, NULL, &inst_logs)) != cli_ok ||
(rc = cli_column(StatementToInst, "ProcessNo", cli_int4, NULL, &inst_processno)) != cli_ok ||
(rc = cli_column(StatementToInst, "level", cli_int4, NULL, &inst_level)) != cli_ok )
{
WriteLog("cli_column failed with code %d\n", rc);
return BIND_COLUMN_ERROR;
}
char buf[MAXSTRLEN];//用于临时存储时间
strcpy(inst_sdatetime,dbDateTime::current().asString(buf,sizeof buf,"%Y-%m-%d %H:%M:%S"));
strcpy(inst_logs,log);
inst_processno = (int)getpid();
inst_level = level;
if((rc = cli_insert(StatementToInst,NULL))!= cli_ok)
{
WriteLog("cli_insert failed with code %d\n", rc);
return INSERT_ERROR;
}
/*
if((rc = cli_commit(session)) != cli_ok) //直接commit非常慢!
{
printf("cli_commit failed with code %d\n", rc);
return PRECOMMIT_ERROR;
}
*/
if((rc = cli_precommit(session)) != cli_ok)
{
WriteLog("cli_precommit failed with code %d\n", rc);
return PRECOMMIT_ERROR;
}
if((rc = cli_free(StatementToInst)) != cli_ok){
WriteLog("cli_free failed with code %d\n", rc);
return FREE_STATEMENT_ERROR;
}
return SUCCESS;
}
int _tmain(int argc, _TCHAR* argv[])
{
char* const serverURL = "127.0.0.1:2100";
int session = cli_open(serverURL,10,1);//重连次数10,重连间隔1s
if (session < 0) {
printf("cli_open failed with code %d\n", session);
return -1;
}
DWORD dstart = GetTickCount();
for(int i=0;i < 10;i++)
WriteLog("this is a log test",i%10,session);
printf("time is %d\n",GetTickCount()-dstart);
int rc;
/*
if((rc = cli_commit(session)) != cli_ok) //批量提交速度最快 但是在提交之前,这部分日志无法取出
{
printf("cli_commit failed with code %d\n", rc);
return PRECOMMIT_ERROR;
}
*/
//precommit最好加上定时备份日志
/*FastDB为数据库提供了precommit的接口,用于完成除sync到磁盘文件外的所有事物操作
,如释放mutex资源等。同时提供了backup接口,用来完成内存数据到磁盘文件的备份,
甚至支持打开数据库时同时指定定时备份到磁盘文件的间隔,但是cli这个功能还没完善*/
if ((rc = cli_close(session)) != 0) {
printf("cli_close failed with code %d\n", rc);
return -1;
}
printf("fastdb insert successfully!\n");
dstart = GetTickCount();
for(int i=0;i < 100;i++)
WriteLog("this is a log test\n",i%10);
printf("time is %d\n",GetTickCount()-dstart);
printf("file insert successfully!\n");
getchar();
return 0;
}
原文:https://blog.csdn.net/fuyun10036/article/details/8620816