第一个C语言的小项目
这里先写下主要的业务代码,一些库代码稍后补充上
/**
* Feed新闻个性化推送
*/ #include "push_service_news.h" /**
* 保证单进程运行
*/
void single_process() {
lock_fd = open("logs/lock", O_CREAT | O_RDWR | O_TRUNC, );
if (push_trylock_fd(lock_fd) == FAILURE) {
push_sys_notice("push_service_news already exists\n");
close(lock_fd);
exit();
} else {
push_sys_notice("push_service_news lock success");
}
} /**
* 线程数据回收函数,单线程结束的时候,系统自动调用
*/
void *push_thread_data_del(void *data) {
if (data) {
free(data);
push_sys_notice("thread data free success");
} else {
push_sys_notice("thread data free fail");
}
} /**
* 初始化
* 连接mysql、线程池、日志打印目录
*/
void init_main(int argc, char **argv) {
a_tpool = push_init_tpool(PUSH_TPOOL_THREAD_COUNT, PUSH_TPOOL_MAX_TASK);
if (!a_tpool) {
push_sys_error("push_init_tpool error");
exit();
}
ThreadData_create(push_thread_data, push_thread_data_del);
} /**
* 获取待执行的任务
*/
void get_task() {
int ret = push_mysql_connect(PUSH_DB_HOST, PUSH_DB_USER, PUSH_DB_PASSWD,
PUSH_DB_PORT, PUSH_DB_DBNAME);
if (ret) {
push_sys_error("mysql_connect error");
exit();
}
ret = push_dao_newstask_getone(&a_newstask);
if (ret == FAILURE) {
push_sys_error("push_dao_newstask_getone error");
exit();
}
if (ret == ) {
push_sys_notice("have no task");
exit();
}
task_id = atol(a_newstask.info[][F_news_task_id]);
if (!task_id) {
push_sys_error("task_id error,:%d", task_id);
exit();
}
ret = push_dao_newstask_update_status(task_id, STATUS_DOING);
if (!ret) {
push_sys_error("update status doing error:%d", task_id);
exit();
}
push_mysql_close();
} /**
* 初始化一些基础路径
*/
void init_path(int platform) {
//重新初始化日志打印目录
char log_path[PUSH_MAXLEN_PATH] = {};
snprintf(log_path, sizeof (log_path), "logs/%u", task_id);
push_init_logger(log_path);
//base_path
snprintf(base_path, sizeof (base_path), "logs/%u/", task_id);
//data_path
snprintf(data_path, sizeof (data_path), "%s%s", base_path, "data/");
char *ptr = platform == PUSH_PLATFORM_ANDROID ? "android" : "iphone";
//cuids_path
snprintf(cuids_path, sizeof (cuids_path), "%s%s_cuids", data_path, ptr);
//bigdata_path
snprintf(bigdata_path, sizeof (bigdata_path), "%s%s_bigdata", data_path, ptr);
//mkdir
push_mkdir(data_path);
push_sys_notice("cuids_path[%s] bigdata_path[%s]", cuids_path, bigdata_path);
/**
* 记录一下task的详细信息
*/
push_sys_notice("task_name[%s]", a_newstask.info[][F_news_task_task_name]);
push_sys_notice("android_cuid_files[%s]", a_newstask.info[][F_news_task_android_cuid_files]);
push_sys_notice("iphone_cuid_files[%s]", a_newstask.info[][F_news_task_iphone_cuid_files]);
push_sys_notice("platform[%s]", a_newstask.info[][F_news_task_platform]); } /**
* 下载Ftp文件
* @notice 此函数中不能使用strtok会造成iPhone只解析一个
* @todo 一篇文章重复推送
* @param src_file
* @param platform
*/
void download_files(char *src_file) {
char *ptr = NULL, *save_ptr = NULL;
char wget_cmd[PUSH_LEN_256] = {};
char uniq_cmd[PUSH_LEN_256] = {};
ptr = strtok_r(src_file, ",", &save_ptr);
int num = , ret = ;
//下载所有cuid的文件
while (ptr) {
snprintf(wget_cmd, sizeof (wget_cmd), "wget -c -O %s_%d %s >> %swget.log 2>&1", cuids_path, num, ptr, base_path);
push_sys_notice("wget_cmd start");
ret = system(wget_cmd);
push_sys_notice("wget_cmd end:[%s]", wget_cmd);
if (ret) {
push_sys_error("wget file error:[%s] [%s]", strerror(errno), wget_cmd);
}
ptr = strtok_r(NULL, ",", &save_ptr);
num++;
}
/**
* 对文件进行去重
* ① 如果选择的是一个tag则不需要处理了,针对全量用户效果是显著的
*/
if (num <= ) {
snprintf(uniq_cmd, sizeof (uniq_cmd), "cat %s_* > %s", cuids_path, bigdata_path);
} else {
snprintf(uniq_cmd, sizeof (uniq_cmd), "sort %s_* -u -T /home/work/tmp/sort_tmp > %s", cuids_path, bigdata_path);
}
push_sys_notice("uniq_cmd start");
system(uniq_cmd);
push_sys_notice("uniq_cmd end:[%s]", uniq_cmd);
} /**
* 工作线程函数
* @param arg
*/
void worker(void *arg) {
/*-------------------------------qps控制ST---------------------------------*/
push_thread_data_t *thread_data = (push_thread_data_t *) ThreadData_get(push_thread_data);
//第一次初始化
if (!thread_data) {
thread_data = (push_thread_data_t *) calloc(, sizeof (push_thread_data_t));
if (!thread_data) {
push_sys_error("push_thread_data calloc error:%s", strerror(errno));
pthread_exit(NULL);
}
thread_data->count = ;
thread_data->timestamp = push_timestamp();
ThreadData_set(push_thread_data, thread_data);
}
while () {
int now_timestamp = push_timestamp();
if (now_timestamp == thread_data->timestamp) {
//触发了qps限制
if (thread_data->count >= PUSH_EVERY_THREAD_QPS) {
push_sys_notice("qps limit: %d >= %d", thread_data->count, PUSH_EVERY_THREAD_QPS);
usleep();
continue;
} else { //没有触发qps限制
thread_data->count++;
push_sys_notice("qps:%d", thread_data->count);
break;
}
} else { //时间不相等,说明肯定没有触发qps限制
thread_data->count = ;
thread_data->timestamp = now_timestamp;
break;
}
}
/*-------------------------------qps控制SE----------------------------------*/
//工作流程
push_news_worker_param_t *param = (push_news_worker_param_t *) arg;
char *response = push_mapi_news_batch(param->platform, task_id, param->cuids, &a_newstask);
if (!response) {
push_error("response error cuids[%s]", param->cuids);
} else if (strstr(response, "{\"errno\":0")) {
push_notice("send success:response[%s]", response);
} else {
push_error("send fail:response[%s] cuids[%s]", response, param->cuids);
}
free(param);
} /**
* 读取文件,向线程池添加任务
*/
int read_file(int platform) {
FILE *fp = fopen(bigdata_path, "r");
if (!fp) {
push_sys_error("open %s error:%s", bigdata_path, strerror(errno));
return FAILURE;
}
char line_data[PUSH_LEN_256] = {};
char cuid_data[PUSH_LEN_256] = {};
int count;
push_news_worker_param_t *worker_param;
for (count = ; !feof(fp) && fgets(line_data, sizeof (line_data), fp) != NULL; count++) {
if (count % PUSH_ONCE_CUID_COUNT == ) {
worker_param = calloc(, sizeof (push_news_worker_param_t));
if (!worker_param) {
push_sys_error("calloc worker_param error:%s", strerror(errno));
continue;
}
worker_param->platform = platform;
}
sscanf(line_data, "%[^\n]", cuid_data);
strncat(worker_param->cuids, cuid_data, PUSH_MAX_CUID_LEN);
strncat(worker_param->cuids, ",", ); if (count % PUSH_ONCE_CUID_COUNT == (PUSH_ONCE_CUID_COUNT - )) {
if (push_tpool_add_task(a_tpool, worker, worker_param)) {
push_sys_error("bigdata_path[%s] tpool add task error", bigdata_path);
} else {
push_sys_notice("bigdata_path[%s] tpool add task success", bigdata_path);
}
}
}
//不是整数的需要特殊处理的
if ((count % PUSH_ONCE_CUID_COUNT != (PUSH_ONCE_CUID_COUNT - )) && (count % PUSH_ONCE_CUID_COUNT != )) {
if (push_tpool_add_task(a_tpool, worker, worker_param)) {
push_sys_error("bigdata_path[%s] tpool add task error", bigdata_path);
} else {
push_sys_notice("bigdata_path[%s] tpool add task success", bigdata_path);
}
}
fclose(fp);
return count;
} /**
* 更新数据库数据
*/
void update_mysql() {
if (task_id == ) {
return;
}
push_sys_notice("---android_send_count[%d]---", android_send_count);
push_sys_notice("---iphone_send_count[%d]---", iphone_send_count);
int ret = push_mysql_connect(PUSH_DB_HOST, PUSH_DB_USER, PUSH_DB_PASSWD,
PUSH_DB_PORT, PUSH_DB_DBNAME);
if (ret) {
push_sys_error("mysql_connect error");
return;
}
int affect;
affect = push_dao_newstask_update_send_count(task_id, android_send_count, iphone_send_count);
if (!affect) {
push_sys_error("update send_count error");
}
affect = push_dao_newstask_update_status(task_id, STATUS_SUSS);
if (affect > ) {
push_sys_error("update status success, status[%d]", STATUS_SUSS);
}
push_mysql_close();
} /**
* 收尾工作
* 关闭mysql连接、销毁线程池、释放查询结果集
*/
void end_main(void) {
push_tpool_destroy(a_tpool);
push_dao_newstask_free_result(&a_newstask);
update_mysql();
push_unlock_fd(lock_fd);
close(lock_fd);
ThreadData_delete(push_thread_data);
push_sys_notice("--------------------task:%d end----------------\n", task_id);
} /**
* 主函数
*/
int main(int argc, char **argv) {
push_init_logger("logs");
single_process();
atexit(end_main);
/**
*@todo应该先获取任务在实例化线程池
*/
init_main(argc, argv);
get_task(); /**
* 分平台去处理各自的逻辑
*/
platform = atoi(a_newstask.info[][F_news_task_platform]);
//Android平台
if (platform == PUSH_PLATFORM_ANDROID || platform == PUSH_PLATFORM_ALL) {
init_path(PUSH_PLATFORM_ANDROID);
download_files(a_newstask.info[][F_news_task_android_cuid_files]);
android_send_count = read_file(PUSH_PLATFORM_ANDROID);
}
//iphone平台
if (platform == PUSH_PLATFORM_IPHONE || platform == PUSH_PLATFORM_ALL) {
init_path(PUSH_PLATFORM_IPHONE);
download_files(a_newstask.info[][F_news_task_iphone_cuid_files]);
iphone_send_count = read_file(PUSH_PLATFORM_IPHONE);
}
//错误的平台设置
if (platform != PUSH_PLATFORM_ANDROID && platform != PUSH_PLATFORM_ALL &&
platform != PUSH_PLATFORM_IPHONE) {
push_sys_error("platform error:%d", platform);
exit();
}
}
第一个C语言的小项目的更多相关文章
- 一个简陋的个人小项目,也是个人第一个真正意义上的独立项目——Graph
由来 我最早接触到图这个概念是在大二的离散数学当中图论相关的内容,当时是以著名的哥尼斯堡七桥问题引出图论的概念,现在依然记忆犹新(不过只是记得这个名字,具体的解题思路我重新温习了一下才想起来),当时也 ...
- 使用OC和Swift两种语言写一个发射烟花的小项目
OC与Swift两种实现方式基本上区别不大,主要是在一些对象或方法的调用方式不同,附带源码. OC代码样式: self.view.backgroundColor = [UIColor blackCol ...
- 我发起并创立了一个 C 语言编译器 开源项目 InnerC
本文是 VMBC / D# 项目 的 系列文章, 有关 VMBC / D# , 见 <我发起并创立了一个 VMBC 的 子项目 D#>(以下简称 <D#>) https: ...
- 10分钟掌握Python-机器学习小项目
学习机器学习相关技术的最好方式就是先自己设计和完成一些小项目. Python 是一种非常流行和强大的解释性编程语言.不像 R 语言,Python 是个很完整的语言和平台,你既可以用来做研发,也可以用来 ...
- Vue小项目二手书商城:(一)准备工作、组件和路由
本项目基于vue2.5.2,与低版本部分不同之处会在(五)参考资料中提出 完整程序:https://github.com/M-M-Monica/bukesi 实现内容: 资源准备(mock数据) 组件 ...
- 【源码项目+解析】C语言/C++开发,打造一个小项目扫雷小游戏!
一直说写个几百行的小项目,于是我写了一个控制台的扫雷,没有想到精简完了代码才200行左右,不过考虑到这是我精简过后的,浓缩才是精华嘛,我就发出来大家一起学习啦,看到程序跑起来能玩,感觉还是蛮有成就感的 ...
- 小项目特供 贪吃蛇游戏(基于C语言)
C语言写贪吃蛇本来是打算去年暑假写的,结果因为ACM集训给耽搁了,因此借寒假的两天功夫写了这个贪吃蛇小项目,顺带把C语言重温了一次. 是发表博客的前一天开始写的,一共写了三个版本,第一天写了第一版,第 ...
- python3开发进阶-Django框架学习前的小项目(一个简单的学员管理系统)
''' 自己独立写一个学员管理系统 表结构: 班级表: -id -grade_name 学生表: -id -student_name -grade 关联外键班级表 老师表: -id -teacher_ ...
- C语言实现简单计算器小项目
昨天刚安装上devc++,半夜想着练练C语言吧 于是就看到实验楼有一个计算器的项目 之前做过一次,这次写的主要是思路 首先我们先从原理思考jia,实现简单的计算器就要具备加减乘除这些,看普通的计算器也 ...
随机推荐
- vscode常用设置
1.代码提示快捷键设置:(keybindings.json) { "key": "ctrl+j","command": "edit ...
- RAC 主库配置单实例ADG
1.主库准备工作 2.物理备库准备工作 3.创建物理备库 写在前面: 最终实现环境:11.2.0.4版本 2节点RAC + 1节点DG 本文旨在弄清楚整个搭建过程中涉及到的基础概念: 本文安装maxi ...
- C# VLCPlayer视频播放器(附源码)
VLCPlayer视频播放器. 支持本地播放,支持网络URL.支持全屏,截图. 基于VLCPlayer. 附带基本代码. 下载地址:http://pan.baidu.com/s/1nvjNvID
- 在WPF按钮删除默认的鼠标悬停效果
如果你想在应用程序的所有按钮将此风格,那么这种风格可以插入Application.Resources部分的App.xaml页面. <Window.Resources> <Style ...
- Be a new gentlemen
学好技术的同时,更要注重自身素养的提升! 一 .有则改之,无责加冕 1.女士优先 2. 不随地吐痰, 不乱扔垃圾, 不在人群中抽烟 3. 不大声喧哗 4. 不插队,碰到别人要说抱歉 5. 不在公共交 ...
- iPhone开发学习
Xcode6中怎么添加空工程模板 NSBundle 使用(程序的资源) 本地存储数据的简单方式:NSUserDefaults UIApplication隐藏statusBarStyle ...
- Android Studio的SVN Performing VCS Refresh/Commit 长时间不结束
给Android Studio项目里面的一个文件改名以后,再提交SVN时总是提示冲突,没办法解决.再后来不知道怎么弄的,每次提交时停留在SVN Performing VCS Refresh始终都不会完 ...
- call_user_func()的参数不能为引用传递 自定义替代方法
php手册 中关于 请注意,传入call_user_func()的参数不能为引用传递. 关于这个情况的解释,可自己搜索.我们可以自己定义一个函数解决这样的问题,实例如下: <?php ini_s ...
- canvas学习之API整理笔记(二)
前面我整理过一篇文章canvas学习之API整理笔记(一),从这篇文章我们已经可以基本了解到常用绘图的API.简单的变换和动画.而本篇文章的主要内容包括高级动画.像素操作.性能优化等知识点,讲解每个知 ...
- DS 工作室
如果你想租用我,QQ:26959368 价格可以详细谈哦, 1. 企业信息化过程中问题的免费咨询: 2. Office 365.Sharepoint Online .Azure 云的咨询服务. 3. ...