#include "stdafx.h" #include #include "mail_object.h" struct DIFF_RES { int equal; int added; int deleted; int updated; }; static void print_objs(const std::vector& objs, const char* prompt, int max) { int i = 0; for (std::vector::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 >& objs, const char* prompt, int max) { int i = 0; for (std::vector > ::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& new_objs) { acl::ifstream in; // 以只读方式打开数据文件 if (in.open_read(filepath) == false) { printf("open %s error %s\r\n", filepath, acl::last_serror()); return -1; } // 从比较器中获得内存池对象,以便于下面分配内存 acl::dbuf_guard& dbuf = manager.get_dbuf(); int linenum = 0; acl::string line; int nobjs = 0; while (!in.eof()) { line.clear(); // 从文件中读取一行数据 if (in.gets(line) == false) break; linenum++; // 分析该行数据,提取 key 和 value 值 char* key = line.c_str(); char* val = strrchr(key, '|'); // 检查数据的有效性 if (val == NULL || val == key || *(val + 1) == 0) { printf("invalid line: %s in %s, linenum: %d\r\n", key, filepath, linenum); continue; } *val++ = 0; // 创建 diff 对象,并置入对象集合中 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) { // 首先定义差集比较器 acl::diff_manager manager; // 存放当前对象 std::vector cur_objs; // 存放旧的对象 std::vector old_objs; // 先从文件中读取当前的对象至新对象集合中 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); // 再从文件中读取旧的对象至旧对象集合中 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); // 开始进行差集比较,并获得最终新增对象人个数 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"); // 获得新增对象集合 const std::vector& new_objs = manager.get_new(); // 打印新增对象至屏幕,限定最大输出 10 个 print_objs(new_objs, "new objs", 10); printf("new nobjs: %d\r\n", (int) new_objs.size()); printf("-------------------------------------------------------\r\n"); // 获得被删除的对象集合 const std::vector& del_objs = manager.get_deleted(); // 打印删除的对象至屏幕,限定最大输出 10 个 print_objs(del_objs, "deleted objs", 10); printf("deleted objs: %d\r\n", (int) del_objs.size()); printf("-------------------------------------------------------\r\n"); // 获得变化的对象集合 const std::vector >& upd_objs = manager.get_updated(); // 打印变化的对象至屏幕,限定最大输出 10 个 print_objs(upd_objs, "updated objs", 10); printf("updated objs: %d\r\n", (int) upd_objs.size()); printf("-------------------------------------------------------\r\n"); // 获得相同的对象集合 const std::vector& 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"); // 本函数返回则 manager 对象及内部自建内存池自动销毁 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; } // 如果设置了完整的期望结果集数值,则传入校验差集结果 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; }