因为缓存数据的buffer总是不够大(会引起段错误)索性从堆上拿了两块大内存

/*
功能说明:逐日存储来访用户(使用伯克利DB)
根据存储的用户信息确定某用户是否是首次来访用户(未被存储的伯克利DB) 调用方式1: 查询游客在2013年8月8日是否访问了指定渠道
./channeldb -s "bch2000 guest:123456789" 20130808
调用方式2:将指定文件里的用户信息写入DB,同时将该文件里的首次访问用户写入日志
./channeldb -f 20130809 ./clog/20130809.log 20130809
*/ #include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <db.h>
#include <sys/types.h>
#include <getopt.h> #define DATABASE "/mnt/disk1/ucshuqi/touch/userlist/historydb/channel.db"
#define YES 1
#define NO 0
#define BUFFER_SIZE 1024 * 8 char *readBuffer = NULL;
char *writeBuffer = NULL; /* ViewData 组件:记录
用户第一次来访时需要记录的数据,例如日期
*/ struct ViewData {
int date;
}; void setDate(struct ViewData *data,char *s)
{
assert(data!=NULL && s!= NULL && strlen(s) == );
data->date = atoi(s);
} /*当 query.date >= stored.date 返回YES,即包含此附属数据的用户信息是历史来访用户*/
int isHistoryViewInfo(struct ViewData *query , struct ViewData *stored)
{
assert(query != NULL && stored != NULL);
printf("query date is %d , stored date is %d \n",query->date, stored->date); if(query->date >= stored->date)
{
return YES;
}
else
{
return NO;
}
} void printViewData(struct ViewData *data)
{
assert(data != NULL);
printf("print view date : %d\n",data->date);
} /* string helper module */ char *trim(char *s)
{
int i; assert(s!=NULL);
i = strlen(s);
for(;i>;i--)
{
if(s[i]==' ' || s[i]=='\n' || s[i]=='\0' || s[i]=='\t')
{
s[i] = '\0';
}
else
{
break;
}
}
return s;
} /* 数据库访问 组件*/ DB *openDb()
{
int ret;
DB *dbp = NULL; ret = db_create(&dbp, NULL, );
if(ret != )
{
fprintf(stderr,"create Db error!\n");
exit();
} ret = dbp->open(dbp, NULL, DATABASE, NULL, DB_BTREE, DB_CREATE,); if(ret != )
{
fprintf(stderr,"open Db error!\n");
exit();
} return dbp;
} /* 业务逻辑 */ /* 存储用户访问信息和附属信息viewdata */
int saveViewInfo(DB *dbp, char *user, struct ViewData *data)
{
DBT key,value; assert(dbp != NULL && user != NULL && data != NULL); memset(&key, , sizeof(key));
key.data = user;
key.size = strlen(user) + ; memset(&value, , sizeof(value));
value.data = data;
value.size = sizeof(*data);
if(dbp->put(dbp, NULL, &key, &value, ) == )
{
//printf("save ---> %s, %d\n", key.data, key.size);
printViewData(value.data);
return YES;
}
else
{
return NO;
}
} /*查找用户访问信息,并将附属信息写入data*/
int findViewInfo(DB *dbp, char *user, struct ViewData *data)
{
DBT key,value; assert(dbp != NULL && user != NULL && data != NULL); memset(&key, , sizeof(key));
key.data = user;
key.size = strlen(user) + ; memset(&value,,sizeof(value)); // must !!! if(dbp->get(dbp, NULL, &key, &value, ) == )
{
memcpy((char*)data,(char*)value.data,value.size);
//printViewData(data);
return YES; //view in database
}
else
{
return NO; //view not in database
}
} /*记录用户信息,如果用户是首次来访*/
void recordNewView(FILE *fp, char *user, char *buffer)
{
//char buffer[BUFFER_SIZE] = {0};
assert(fp != NULL && user != NULL && buffer != NULL);
printf("%s is new view\n", user);
sprintf(buffer, "%s found\n", user);
fwrite(buffer, sizeof(char), strlen(buffer), fp);
} /*存储访问信息到数据库,同时写入附属信息*/
void saveViewFile(char *from, char *to, struct ViewData *writeData)
{
DB *dbp = openDb();
struct ViewData stored;
FILE *fp = fopen(from,"r");
FILE *fpResult = fopen(to,"w"); assert(fp != NULL && fpResult != NULL && writeData != NULL);
assert(readBuffer != NULL && writeBuffer != NULL); /* clear global buffer content */
memset(readBuffer, , BUFFER_SIZE);
memset(writeBuffer, , BUFFER_SIZE); while(fgets((char*)readBuffer, BUFFER_SIZE, fp)!=NULL)
{
char *user = trim((char*)readBuffer);
memset(&stored, , sizeof(stored)); if(findViewInfo(dbp, user, &stored) == YES)
{
if(isHistoryViewInfo(writeData,&stored) == NO)
{
recordNewView(fpResult, user, writeBuffer);
}
continue;
} recordNewView(fpResult, user, writeBuffer);
if(saveViewInfo(dbp, user, writeData) == NO)
{
printf("save %s faild\n", user);
} /* clear global buffer content */
memset(readBuffer, , BUFFER_SIZE);
memset(writeBuffer, , BUFFER_SIZE);
} free(readBuffer);
free(writeBuffer);
dbp->close(dbp, );
fclose(fp);
fclose(fpResult);
} /*给命令行调用的接口,找茬指定的用户是否是历史用户*/
void hasViewInfo(char *user, struct ViewData *query)
{
DB *dbp = NULL;
struct ViewData stored; dbp = openDb();
assert(user != NULL && query != NULL);
memset(&stored, ,sizeof(stored));
user = trim(user); if(findViewInfo(dbp, user, &stored) == YES)
{
if(isHistoryViewInfo(query, &stored) == YES)
{
printf("found %s\n",user);
}
else
{
//printf("%s in db\n",user);
printf("not found %s\n",user);
}
}
else
{
printf("%s not in db\n",user);
printf("not found %s\n",user);
} dbp->close(dbp, );
} int main (int argc, char *argv[])
{
int oc;
extern char *optarg;
extern int optind, opterr, optopt; char *from = NULL;
char *to = NULL; struct ViewData viewData;
memset(&viewData, , sizeof(viewData)); readBuffer = malloc(BUFFER_SIZE);
writeBuffer = malloc(BUFFER_SIZE); while((oc=getopt(argc,argv,"f:s:t:")) != -)
{
switch(oc)
{
case 's':
setDate(&viewData,argv[optind]);
hasViewInfo(optarg, &viewData);
break; case 'f':
from = optarg;
to = argv[optind++];
setDate(&viewData,argv[optind]);
saveViewFile(from, to, &viewData);
break;
}
} return ;
}

C语言读写伯克利DB 4的更多相关文章

  1. C语言读写伯克利DB 3

    gcc -o channeldb channel.c -db -Wall # -Wall参数等价于执行lint,即:进行代码的静态分析,它可以指出未初始化的变量,未使用的变量 #include < ...

  2. C语言解析日志,存储数据到伯克利DB

    编译命令 gcc -o dbwriter dbwriter.c -ldb dbwriter.c #include <assert.h> #include <stdlib.h> ...

  3. R语言读写中文编码方式

    最近遇到一个很头疼的事,就是 R语言读写中文编码方式.在网上找到了一篇博文,谢谢博主的精彩分享,让我很快解决了问题,在此也分享一下 R语言读写数据的方法很多,这里主要是我在使用read.csv/rea ...

  4. 伯克利DB的一个BUG

    一旦没有手工close掉伯克利DB,则缓存里的数据不会主动写入到文件中,因此非常难于排查这个BUG,记录在这里提醒自己

  5. R语言读写数据

    R语言读写数据 一般做模型的时候,从外部的excel中读入数据,我现在常用的比较多的是read_csv(file) 读入之前先把excel数据转化成.csv格式 同样的把结果输出来的时候用的是writ ...

  6. C++封装C语言读写文件

    自己项目需要,封装C语言读写文件. 为了兼容低版本的编译器,因为低版本的编译器(比如,Vs2010,Vs2008)他们可能不支持 modern c++. 项目 使用 cmake管理的项目. 可以在 g ...

  7. C语言解析日志,存储数据到伯克利DB 2

    #编译程序 gcc -o historydb historydb.c -ldb #将2013年8月9日的用户记录写入数据库 (程序自动识别新用户入库,跳过老用户) ./historydb -f .us ...

  8. C语言读写文件

    对文件的读和写是最常用的文件操作.在C语言中提供了多种文件读写的函数: 字符读写函数  :fgetc和fputc 字符串读写函数:fgets和fputs 数据块读写函数:freed和fwrite 格式 ...

  9. Go 语言读写 Excel

    Excelize 是 Golang 编写的一个用来操作 Office Excel 文档类库,基于微软的 Office OpenXML 标准.可以使用它来读取.写入 XLSX 文件.相比较其他的开源类库 ...

随机推荐

  1. 不知道算不算另类的ASP.NET MVC4 Ajax分页

    以往用Ajax来实现无刷新分页,用户一按F5,页数就记不住了,点了一个链接也是同一个问题,再想回退回来,就回到第一页了.上次看到一篇文章,说到window.location.hash的用途,于是萌生了 ...

  2. 动态Linq(结合反射)

    这篇文章决定对最近一个单机版Web程序用到的东西总结一下. 一.反射Linq之OrderBy 动态Linq结合反射对某字段排序: namespace 动态Linq { class Program { ...

  3. mysql创建utf-8字符集数据库

    CREATE DATABASE db_name DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; CREATE DATABASE 的语法:CREA ...

  4. PowerShell文件系统(一)前言

    PowerShell文件系统(一)前言 3 12 2月, 2014  在 Powershell tagged Powershell教程 / 别名 / 文件系统 by Mooser Lee PowerS ...

  5. NOI2015 小园丁与老司机

    http://uoj.ac/problem/132 这道题前2行的输出比较容易,就是简单的动态规划,然后第3行就是比较少见的有上下界的最小流. 前2行比较容易,我们讨论一下第3行的解法吧. 比如第1个 ...

  6. UVA514 Rails

     铁轨 PopPush城市有一座著名的火车站.这个国家到处都是丘陵.而这个火车站是建于上一个世纪.不幸的是,那时的资金有限.所以只能建立起一条路面铁轨.而且,这导致这个火车站在同一个时刻只能一个轨道投 ...

  7. Java集合的实现细节—Set集合和Map集合

    Set:代表无序.不可重复的集合 Map:代表key-value对集合,也称为关联数组 从表面上看,Set和Map相似性很少,但实际上可以说Map集合时Set集合的扩展. 1.Set集合和Map集合的 ...

  8. javascript笔记4之运算符

    /* var box = 100; --box; //前置递增,box = box +1 alert(box);//99 var box = 100; var age = ++box; //先box累 ...

  9. c语言指向结构体数组的指针

    #include <stdio.h> #include <stdlib.h> struct dangdang { ]; ]; ]; int num; int bugnum; ] ...

  10. Js获取元素样式值(getComputedStyle&currentStyle)兼容性解决方案

    因为:style(document.getElementById(id).style.XXX)只能获取元素的内联样式,内部样式和外部样式使用style是获取不到的. 一般js获取内部样式和外部样式使用 ...