2019-07-28 10:31:56 +08:00
|
|
|
#include "stdafx.h"
|
2018-12-12 11:16:12 +08:00
|
|
|
#include <getopt.h>
|
|
|
|
#include "mail_object.h"
|
|
|
|
|
|
|
|
struct DIFF_RES
|
|
|
|
{
|
|
|
|
int equal;
|
|
|
|
int added;
|
|
|
|
int deleted;
|
|
|
|
int updated;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void print_objs(const std::vector<acl::diff_object*>& objs,
|
|
|
|
const char* prompt, int max)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
for (std::vector<acl::diff_object*>::const_iterator cit = objs.begin();
|
|
|
|
cit != objs.end() && i++ < max; ++cit)
|
|
|
|
{
|
|
|
|
printf(">>%s->%d: key: %s, val: %s\r\n",
|
|
|
|
prompt, i, (*cit)->get_key(), (*cit)->get_val());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void print_objs(
|
|
|
|
const std::vector<std::pair<acl::diff_object*, acl::diff_object*> >& objs,
|
|
|
|
const char* prompt, int max)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
for (std::vector<std::pair<acl::diff_object*, acl::diff_object*> >
|
|
|
|
::const_iterator cit = objs.begin();
|
|
|
|
cit != objs.end() && i++ < max; ++cit)
|
|
|
|
{
|
|
|
|
printf(">>%s->%d: key: %s, new val: %s, old val: %s\r\n",
|
|
|
|
prompt, i, (*cit).first->get_key(),
|
|
|
|
(*cit).first->get_val(),
|
|
|
|
(*cit).second->get_val());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int load_objs(acl::diff_manager& manager, const char* filepath,
|
|
|
|
std::vector<acl::diff_object*>& new_objs)
|
|
|
|
{
|
|
|
|
acl::ifstream in;
|
|
|
|
|
2019-07-28 10:31:56 +08:00
|
|
|
// 以只读方式打开数据文件
|
2018-12-12 11:16:12 +08:00
|
|
|
if (in.open_read(filepath) == false)
|
|
|
|
{
|
|
|
|
printf("open %s error %s\r\n", filepath, acl::last_serror());
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2019-07-28 10:31:56 +08:00
|
|
|
// 从比较器中获得内存池对象,以便于下面分配内存
|
2018-12-12 11:16:12 +08:00
|
|
|
acl::dbuf_guard& dbuf = manager.get_dbuf();
|
|
|
|
int linenum = 0;
|
|
|
|
acl::string line;
|
|
|
|
|
|
|
|
int nobjs = 0;
|
|
|
|
|
|
|
|
while (!in.eof())
|
|
|
|
{
|
|
|
|
line.clear();
|
|
|
|
|
2019-07-28 10:31:56 +08:00
|
|
|
// 从文件中读取一行数据
|
2018-12-12 11:16:12 +08:00
|
|
|
if (in.gets(line) == false)
|
|
|
|
break;
|
|
|
|
|
|
|
|
linenum++;
|
|
|
|
|
2019-07-28 10:31:56 +08:00
|
|
|
// 分析该行数据,提取 key 和 value 值
|
2018-12-12 11:16:12 +08:00
|
|
|
char* key = line.c_str();
|
|
|
|
char* val = strrchr(key, '|');
|
|
|
|
|
2019-07-28 10:31:56 +08:00
|
|
|
// 检查数据的有效性
|
2018-12-12 11:16:12 +08:00
|
|
|
if (val == NULL || val == key || *(val + 1) == 0)
|
|
|
|
{
|
|
|
|
printf("invalid line: %s in %s, linenum: %d\r\n",
|
|
|
|
key, filepath, linenum);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
*val++ = 0;
|
|
|
|
|
2019-07-28 10:31:56 +08:00
|
|
|
// 创建 diff 对象,并置入对象集合中
|
2018-12-12 11:16:12 +08:00
|
|
|
mail_object* obj = new (dbuf.dbuf_alloc(sizeof(mail_object)))
|
|
|
|
mail_object(manager, key, val);
|
|
|
|
new_objs.push_back(obj);
|
|
|
|
nobjs++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nobjs;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool check_diff(const char* new_file, const char* old_file,
|
|
|
|
const DIFF_RES* res = NULL)
|
|
|
|
{
|
2019-07-28 10:31:56 +08:00
|
|
|
// 首先定义差集比较器
|
2018-12-12 11:16:12 +08:00
|
|
|
acl::diff_manager manager;
|
2019-07-28 10:31:56 +08:00
|
|
|
// 存放当前对象
|
2018-12-12 11:16:12 +08:00
|
|
|
std::vector<acl::diff_object*> cur_objs;
|
2019-07-28 10:31:56 +08:00
|
|
|
// 存放旧的对象
|
2018-12-12 11:16:12 +08:00
|
|
|
std::vector<acl::diff_object*> old_objs;
|
|
|
|
|
2019-07-28 10:31:56 +08:00
|
|
|
// 先从文件中读取当前的对象至新对象集合中
|
2018-12-12 11:16:12 +08:00
|
|
|
int n = load_objs(manager, new_file, cur_objs);
|
|
|
|
if (n < 0)
|
|
|
|
{
|
|
|
|
printf("load curr objs error from %s\r\n", new_file);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
printf("cur objs: %d\r\n", n);
|
|
|
|
|
2019-07-28 10:31:56 +08:00
|
|
|
// 再从文件中读取旧的对象至旧对象集合中
|
2018-12-12 11:16:12 +08:00
|
|
|
n = load_objs(manager, old_file, old_objs);
|
|
|
|
if (n < 0)
|
|
|
|
{
|
|
|
|
printf("load old objs error from %s\r\n", old_file);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct timeval begin;
|
|
|
|
gettimeofday(&begin, NULL);
|
|
|
|
|
2019-07-28 10:31:56 +08:00
|
|
|
// 开始进行差集比较,并获得最终新增对象人个数
|
2018-12-12 11:16:12 +08:00
|
|
|
manager.diff_changes(cur_objs, old_objs);
|
|
|
|
|
|
|
|
struct timeval end;
|
|
|
|
gettimeofday(&end, NULL);
|
|
|
|
|
|
|
|
double spent = acl::stamp_sub(end, begin);
|
|
|
|
printf("spent: %.4f ms\r\n", spent);
|
|
|
|
|
|
|
|
printf("-------------------------------------------------------\r\n");
|
|
|
|
|
2019-07-28 10:31:56 +08:00
|
|
|
// 获得新增对象集合
|
2018-12-12 11:16:12 +08:00
|
|
|
const std::vector<acl::diff_object*>& new_objs = manager.get_new();
|
|
|
|
|
2019-07-28 10:31:56 +08:00
|
|
|
// 打印新增对象至屏幕,限定最大输出 10 个
|
2018-12-12 11:16:12 +08:00
|
|
|
print_objs(new_objs, "new objs", 10);
|
|
|
|
printf("new nobjs: %d\r\n", (int) new_objs.size());
|
|
|
|
|
|
|
|
printf("-------------------------------------------------------\r\n");
|
|
|
|
|
2019-07-28 10:31:56 +08:00
|
|
|
// 获得被删除的对象集合
|
2018-12-12 11:16:12 +08:00
|
|
|
const std::vector<acl::diff_object*>& del_objs = manager.get_deleted();
|
|
|
|
|
2019-07-28 10:31:56 +08:00
|
|
|
// 打印删除的对象至屏幕,限定最大输出 10 个
|
2018-12-12 11:16:12 +08:00
|
|
|
print_objs(del_objs, "deleted objs", 10);
|
|
|
|
printf("deleted objs: %d\r\n", (int) del_objs.size());
|
|
|
|
|
|
|
|
printf("-------------------------------------------------------\r\n");
|
|
|
|
|
2019-07-28 10:31:56 +08:00
|
|
|
// 获得变化的对象集合
|
2018-12-12 11:16:12 +08:00
|
|
|
const std::vector<std::pair<acl::diff_object*, acl::diff_object*> >&
|
|
|
|
upd_objs = manager.get_updated();
|
|
|
|
|
2019-07-28 10:31:56 +08:00
|
|
|
// 打印变化的对象至屏幕,限定最大输出 10 个
|
2018-12-12 11:16:12 +08:00
|
|
|
print_objs(upd_objs, "updated objs", 10);
|
|
|
|
printf("updated objs: %d\r\n", (int) upd_objs.size());
|
|
|
|
|
|
|
|
printf("-------------------------------------------------------\r\n");
|
|
|
|
|
2019-07-28 10:31:56 +08:00
|
|
|
// 获得相同的对象集合
|
2018-12-12 11:16:12 +08:00
|
|
|
const std::vector<acl::diff_object*>& equ_objs = manager.get_same();
|
|
|
|
print_objs(equ_objs, "equal objs", 10);
|
|
|
|
printf("equal objs: %d\r\n", (int) equ_objs.size());
|
|
|
|
|
|
|
|
printf("-------------------------------------------------------\r\n");
|
|
|
|
|
2019-07-28 10:31:56 +08:00
|
|
|
// 本函数返回则 manager 对象及内部自建内存池自动销毁
|
2018-12-12 11:16:12 +08:00
|
|
|
|
|
|
|
if (res == NULL)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (res->equal != (int) equ_objs.size())
|
|
|
|
{
|
|
|
|
printf("invalid equal: %d, %lu\r\n", res->equal, equ_objs.size());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (res->updated != (int) upd_objs.size())
|
|
|
|
{
|
|
|
|
printf("invalid updated: %d, %lu\r\n",
|
|
|
|
res->updated, equ_objs.size());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (res->deleted != (int) del_objs.size())
|
|
|
|
{
|
|
|
|
printf("invalid deleted: %d, %lu\r\n",
|
|
|
|
res->deleted, del_objs.size());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (res->added != (int) new_objs.size())
|
|
|
|
{
|
|
|
|
printf("invalid added: %d, %lu\r\n",
|
|
|
|
res->added, new_objs.size());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void usage(const char* procname)
|
|
|
|
{
|
|
|
|
printf("usage: %s -h [help] -n new_file -o old_file\r\n"
|
|
|
|
" -N new_objs_count\r\n"
|
|
|
|
" -U update_objs_count\r\n"
|
|
|
|
" -D delete_objs_count\r\n"
|
|
|
|
" -E equal_objs_count\r\n",
|
|
|
|
procname);
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char* argv[])
|
|
|
|
{
|
|
|
|
int ch;
|
|
|
|
acl::string new_file, old_file;
|
|
|
|
DIFF_RES res;
|
|
|
|
|
|
|
|
res.deleted = -1;
|
|
|
|
res.updated = -1;
|
|
|
|
res.added = -1;
|
|
|
|
res.equal = -1;
|
|
|
|
|
|
|
|
while ((ch = getopt(argc, argv, "hn:o:N:U:D:E:")) > 0)
|
|
|
|
{
|
|
|
|
switch (ch)
|
|
|
|
{
|
|
|
|
case 'h':
|
|
|
|
usage(argv[0]);
|
|
|
|
return 0;
|
|
|
|
case 'n':
|
|
|
|
new_file = optarg;
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
old_file = optarg;
|
|
|
|
break;
|
|
|
|
case 'N':
|
|
|
|
res.added = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'U':
|
|
|
|
res.updated = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'D':
|
|
|
|
res.deleted = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'E':
|
|
|
|
res.equal = atoi(optarg);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (new_file.empty() || old_file.empty())
|
|
|
|
{
|
|
|
|
usage(argv[0]);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2019-07-28 10:31:56 +08:00
|
|
|
// 如果设置了完整的期望结果集数值,则传入校验差集结果
|
2018-12-12 11:16:12 +08:00
|
|
|
|
|
|
|
if (check_diff(new_file, old_file,
|
|
|
|
res.updated >= 0 && res.deleted >= 0
|
|
|
|
&& res.added >= 0 && res.equal >= 0 ? &res : NULL) == true)
|
|
|
|
{
|
|
|
|
printf("check diff ok, new_file: %s, old_file: %s\r\n",
|
|
|
|
new_file.c_str(), old_file.c_str());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printf("check error, new_file: %s, old_file: %s\r\n",
|
|
|
|
new_file.c_str(), old_file.c_str());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|