diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..57b95fd --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.out +.vscode +.DS_Store \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 7a73a41..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} \ No newline at end of file diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 6baf1d0..732e706 --- a/README.md +++ b/README.md @@ -2,174 +2,100 @@ 这个repo的大致的想法是,把自己看到的,学到的东西 或者时觉得不错的一些零散碎片的东西,整理上来。 - ----- ## 目录 * [C/C++](#C/C++) -* [操作系统](#操作系统) -* [计算机网络](#计算机网络) +* [Linux](#Linux和系统编程) * [数据库](#数据库) -* [HTTP](#HTTP) -* [Linux](#Linux) -* [编码实践 / 设计模式](#编码实践/设计模式) -* [数据结构 / 算法](#数据结构/算法) -* [机器 / 深度学习](#机器学习/深度学习) -* [书单 / 读书](#书单) -* [工具](#工具) -* [关注的人 / Blog](#关注的人/Blog) -* [源码 / 开源项目](#源码/开源项目) -* [后记 / 参考文献](#后记) +* [编码实践和设计模式](#编码实践和设计模式) +* [数据结构和算法](#数据结构和算法) +* [工具和锤子](#工具和锤子) --- ## C/C++ -> [c++ 语法](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/c%2B%2B%E5%AD%A6%E4%B9%A0.md) - -> [编译,链接,装载](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/%E7%BC%96%E8%AF%91%2C%E9%93%BE%E6%8E%A5%E4%B8%8E%E8%A3%85%E8%BD%BD.md) - -> [c++的new和delete](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/c%2B%2B%E7%9A%84new%E5%92%8Cdelete.md) - -> [c++的多态和虚函数](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/c%2B%2B%E7%9A%84%E5%A4%9A%E6%80%81%E5%92%8C%E8%99%9A%E5%87%BD%E6%95%B0.md) - -> [c++的前置声明](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/c%2B%2B%E7%9A%84%E5%89%8D%E7%BD%AE%E5%A3%B0%E6%98%8E.md) +> [c++基础](./note/c++学习.md) -> [c++面向对象](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/c%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1.md) +> [STL容器](./note/c++STL.md) -> [c++类型转换cast](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/c%2B%2B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1.md) +> [编译,链接,装载](./note/编译,链接与装载.md) -## 操作系统 +> [函数调用过程](./note/函数调用过程.md) -> [unix环境高级编程](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/unix%E7%8E%AF%E5%A2%83%E9%AB%98%E7%BA%A7%E7%BC%96%E7%A8%8B.md) +> [内存管理](./note/c++内存管理.md) -> [文件系统-todo] +> [其他](./note/c++.md) -> [线程同步](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/%E7%BA%BF%E7%A8%8B%E5%90%8C%E6%AD%A5.md) +> [C++踩坑指南](https://www.jianshu.com/p/b67222570785) -## 计算机网络 +## Linux和系统编程 -> [网络编程](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/TCP%E5%92%8C%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B.md) +> [Linux 基本命令](./note/linux命令.md) -## 数据库 - ->[数据库](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/%E6%95%B0%E6%8D%AE%E5%BA%93.md) - ->[数据库索引](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/%E6%95%B0%E6%8D%AE%E5%BA%93-%E7%B4%A2%E5%BC%95.md) +> [linux 关于性能分析的命令](./note/linux命令_linux性能分析和优化.md) -## HTTP +> [linux 其他](./note/linux命令整理.md) -## Linux +### 乱七八糟的东西 -> [Linux 基本命令](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/linux%E5%91%BD%E4%BB%A4.md) +> [协程](https://www.jianshu.com/p/c4de909fee75) -> [linux gcc命令](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/linux%E5%91%BD%E4%BB%A4_gcc.md) +> [protobuff](https://www.jianshu.com/p/131f0bf218ef) ->[linux tcpdump命令](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/linux%E5%91%BD%E4%BB%A4_tcpdump.md) +> [分布式id生成](./note/分布式id生成.md) ->[linux 关于性能分析的命令](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/linux%E5%91%BD%E4%BB%A4_linux%E6%80%A7%E8%83%BD%E5%88%86%E6%9E%90%E5%92%8C%E4%BC%98%E5%8C%96.md) +> [分布式锁](./note/分布式锁.md) ->[bash&shell 编程](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/bash%26shell%E7%BC%96%E7%A8%8B.md) +> [消息队列](./note/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97.md) ->[linux 关于配置的命令](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/linux%E9%85%8D%E7%BD%AE.md) +> [缓存系统](https://www.jianshu.com/p/057da7850c93) +> [限流器实现](./note/limiter.md) -## 工具 +> [一致性哈希](./note/%E4%B8%80%E8%87%B4%E6%80%A7%E5%93%88%E5%B8%8C.md) ->[git教程](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/git%E6%95%99%E7%A8%8B.md) +> [大型C++工程编译时间优化](./note/C++编译耗时优化.md) ->[make构建教程](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/linux%E5%91%BD%E4%BB%A4_make%E6%95%99%E7%A8%8B.md) +## 工具和锤子 ->[svn教程](https://www.jianshu.com/p/d6abd4a986a6) +> [jemalloc](./note/jemalloc.md) ->[docker-todo] +> [Address Sanitizer](./note/asan.md) -## 编码实践/设计模式 +> [PhysX基本概念](./note/PhysX.md) ->[《重构》的笔记](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/%E3%80%8A%E9%87%8D%E6%9E%84%E3%80%8B%E7%9A%84%E7%AC%94%E8%AE%B0.md) +> [收集些小工具,代码片段或轮子](./note/%E6%94%B6%E9%9B%86%E8%A7%81%E5%88%B0%E8%BF%87%E7%9A%84%E4%B8%80%E4%BA%9B%E5%B7%A5%E5%85%B7%E5%92%8C%E8%BD%AE%E5%AD%90.md) ->[设计模型的几个原则](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%9A%84%E5%9F%BA%E6%9C%AC%E5%8E%9F%E5%88%99.md) +> [git教程](./note/git教程.md) ->[具体的设计模式](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.md) +> [make构建教程](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/linux%E5%91%BD%E4%BB%A4_make%E6%95%99%E7%A8%8B.md) -> [Google-style](https://zh-google-styleguide.readthedocs.io/en/latest/contents/) +> [vscode插件](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/vscode%E5%86%99c%2B%2B%E6%8F%92%E4%BB%B6%E4%BB%A5%E5%8F%8A%E9%85%8D%E7%BD%AE.md) -## 数据结构/算法 +## 数据结构和算法 >[常见的算法题](https://github.com/zhaozhengcoder/Algorithm) ->[关于系统设计类的问题](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A1%E7%B1%BB%E7%9A%84%E9%97%AE%E9%A2%98.md) - -## 机器学习/深度学习 - -## 书单 - -> [我整理的技术类的书单](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/%E4%B9%A6%E5%8D%95_%E6%8A%80%E6%9C%AF%E7%B1%BB_%E8%87%AA%E5%B7%B1%E6%95%B4%E7%90%86%E7%9A%84.md) - -> [我整理的技术类的书单](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/%E4%B9%A6%E5%8D%95_%E9%9D%9E%E6%8A%80%E6%9C%AF%E7%B1%BB_%E8%87%AA%E5%B7%B1%E6%95%B4%E7%90%86%E7%9A%84.md) - -> [江湖上面有人整理出来的技术类书单](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/%E4%B9%A6%E5%8D%95_%E6%8A%80%E6%9C%AF%E7%B1%BB_%E5%88%AB%E4%BA%BA%E6%95%B4%E7%90%86%E7%9A%84%E4%B9%A6%E5%8D%95.md) - - -## 开发工具 - -> [window下的ubuntu子系统](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/%E5%B7%A5%E5%85%B7%E6%A0%88.md) - ->[vscode插件](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/vscode%E5%86%99c%2B%2B%E6%8F%92%E4%BB%B6%E4%BB%A5%E5%8F%8A%E9%85%8D%E7%BD%AE.md) - ->[vim插件](https://www.jianshu.com/p/c527d9c2717a) - -## 关注的人 / 大牛 - -> [C++大牛的博客](https://gist.github.com/wen-long/d4d2eb183f1a3d6834c3) - -### 博客BLOG - -这些是我整理的一些,感觉是一些有意思的人。 - -* [张洋的blog](http://blog.codinglabs.org/pages/about-me.html) - -* [果冻想](https://www.jellythink.com/) - -* [lifeofzjs](http://lifeofzjs.com/) - -* [tiankonguse](http://github.tiankonguse.com/) - -* [关于机器学习的算法的blog](liuyaolei.com/archives/) - -* [阮一峰](http://www.ruanyifeng.com/blog/archives.html) - -* [selfboot](https://selfboot.cn/) - -* [cizixs](https://cizixs.com/) - -* [c++的一个blog — watson2016](https://blog.csdn.net/watson2016/article/list/6) - -* [c++的一个blog — senlinzhan](http://senlinzhan.github.io/) - -* [c++做游戏开发的一个人](https://me.csdn.net/wallwind) - -**中文世界里面的大牛们** - -* 陈硕 : https://blog.csdn.net/Solstice - -* 云风 :https://blog.codingnow.com/ - -* milo : https://www.cnblogs.com/miloyip/ +>[关于系统设计类的问题](https://github.com/donnemartin/system-design-primer/blob/master/README-zh-Hans.md) +## 数据库 -## 源码/开源项目 +>[数据库系统基本概念](./note/数据库.md) -> [练手的小的组件和小轮子](https://github.com/zhaozhengcoder/rebuild-the-wheel) +>[数据库索引](./note/数据库-索引.md) -> [muduo](https://github.com/zhaozhengcoder/muduo) +## 编码实践和设计模式 +> [设计模式](./note/设计模式.md) -## 程序员身体保养 +> [Google-style 编码规范](https://zh-google-styleguide.readthedocs.io/en/latest/contents/) ->[颈椎保护指南]() +## 书单和博客 +* [书单和博客](./note/书单和博客.md) ## 后记 @@ -178,3 +104,6 @@ - 内容按照 [中文文案排版指北](https://mazhuang.org/wiki/chinese-copywriting-guidelines/) 进行排版。 - markdown [教程](http://xianbai.me/learn-md/index.html) + +- branch test test + diff --git a/example_code/apue/file_lock.c b/example_code/apue/file_lock.c old mode 100644 new mode 100755 diff --git a/example_code/cas/lockfree_ringbuff/ringbuff.h b/example_code/cas/lockfree_ringbuff/ringbuff.h new file mode 100755 index 0000000..e7bf3d1 --- /dev/null +++ b/example_code/cas/lockfree_ringbuff/ringbuff.h @@ -0,0 +1,137 @@ +#ifndef __RINGBUFF_H__ +#define __RINGBUFF_H__ + +#include +#include + +const unsigned int MAX_BUFF_SIZE = 1024 * 1000; + +template +class RingBuff +{ + public: + RingBuff() + { + memset(&ring_buff[0], 0, sizeof(ring_buff[0]) * MAX_BUFF_SIZE); + this->head_idx = 0; + this->tail_idx = 0; + // printf("ringbuff init, size %d, use lock %d \n" + // , MAX_BUFF_SIZE, use_lock()); + } + + int enqueue_unlock(const T &ele) + { + if (is_full()) {return -1;} + + head_idx = (head_idx+1)%MAX_BUFF_SIZE; + ring_buff[head_idx] = ele; + return 0; + } + + int enqueue_lock(const T &ele) + { + while (true) + { + if (is_full()) {return -1;} + + unsigned int cur_head = this->head_idx; + unsigned int next_head = (head_idx+1)%MAX_BUFF_SIZE; + ring_buff[next_head] = ele; + if (this->head_idx.compare_exchange_weak(cur_head, next_head)) + { + return 0; + } + } + return 0; + } + + int enqueue(const T &ele) + { + if (use_lock()) + { + return enqueue_lock(ele); + } + else + { + return enqueue_unlock(ele); + } + } + + int dequeue_unlock(T &ele) + { + if (is_empty()) {return -1;} + tail_idx = (tail_idx + 1) % MAX_BUFF_SIZE; + ele = ring_buff[tail_idx]; + return 0; + } + + int dequeue_lock(T &ele) + { + while (true) + { + unsigned int cur_tail = this->tail_idx; + unsigned int next_tail = (this->tail_idx + 1) % MAX_BUFF_SIZE; + if (this->tail_idx.compare_exchange_weak(cur_tail, next_tail)) + { + return 0; + } + } + return 0; + } + + int dequeue(T &ele) + { + if (use_lock()) + { + return dequeue_lock(ele); + } + else + { + return dequeue_unlock(ele); + } + } + + bool is_empty() + { + if (head_idx == tail_idx) {return true;} + return false; + } + + bool is_full() + { + if ((head_idx + 1) % MAX_BUFF_SIZE == tail_idx) {return true;} + return false; + } + + int get_size() + { + if (is_empty()) {return 0;} + + if (is_full()) {return MAX_BUFF_SIZE-1;} + + if (head_idx - tail_idx > 0) + { + return head_idx - tail_idx; + } + else + { + return head_idx + (MAX_BUFF_SIZE - tail_idx); + } + } + + bool use_lock() + { + #ifdef USE_LOCK + return true; + #else + return false; + #endif + } + + private: + T ring_buff[MAX_BUFF_SIZE]; + std::atomic head_idx; + std::atomic tail_idx; +}; + +#endif \ No newline at end of file diff --git a/example_code/cas/lockfree_ringbuff/unittest/Makefile b/example_code/cas/lockfree_ringbuff/unittest/Makefile new file mode 100755 index 0000000..1a2e384 --- /dev/null +++ b/example_code/cas/lockfree_ringbuff/unittest/Makefile @@ -0,0 +1,21 @@ +APP_EXE=unittest + +all: $(APP_EXE) + +CFLAGS += -Wsign-conversion -Wpedantic -Wall -DNDEBUG -O3 +CFLAGS += -g + +ifeq ($(_LOCK), 1) +CFLAGS += -D USE_LOCK +endif + +#默认无锁版本 +$(APP_EXE):unittest.cpp ../ringbuff.h Makefile + g++ -std=c++11 $(CFLAGS) unittest.cpp ../ringbuff.h -o $(APP_EXE) -lpthread + +#构建有锁版本 +lock_version: + make $(APP_EXE) _LOCK=1 + +clean: + rm $(APP_EXE) \ No newline at end of file diff --git a/example_code/cas/lockfree_ringbuff/unittest/unittest b/example_code/cas/lockfree_ringbuff/unittest/unittest new file mode 100755 index 0000000..c862f6a Binary files /dev/null and b/example_code/cas/lockfree_ringbuff/unittest/unittest differ diff --git a/example_code/cas/lockfree_ringbuff/unittest/unittest.cpp b/example_code/cas/lockfree_ringbuff/unittest/unittest.cpp new file mode 100755 index 0000000..d0837ef --- /dev/null +++ b/example_code/cas/lockfree_ringbuff/unittest/unittest.cpp @@ -0,0 +1,168 @@ +#include +#include +#include +#include +#include "../ringbuff.h" + +using namespace std; +const int THREAD_NUM = 4; +const int TASK_REPEATED_TIMES = 10; + +RingBuff thread_ring_buff; + +void single_test() +{ + int enqueue = 10; + RingBuff ring_buff; + ring_buff.enqueue(enqueue); + + int dequeue = 0; + ring_buff.dequeue(dequeue); + assert(enqueue == dequeue); + return; +} + +void size_test() +{ + int push_num = 100; + RingBuff ring_buff; + for (int i = 0; i < push_num; i++) + { + ring_buff.enqueue(i); + } + assert(ring_buff.get_size() == push_num); + return; +} + +void empty_test() +{ + RingBuff ring_buff; + assert(ring_buff.is_empty()); + return; +} + +void full_test() +{ + RingBuff ring_buff; + for (unsigned int i = 0; i < MAX_BUFF_SIZE - 1; i++) + { + ring_buff.enqueue((int)i); + } + assert(ring_buff.is_full()); + return; +} + +void push_test() +{ + RingBuff ring_buff; + unsigned int half = MAX_BUFF_SIZE / 2; + for (unsigned int i = 0; i < half; i++) + { + ring_buff.enqueue((int)i); + } + + for (unsigned int i = 0; i < half; i++) + { + int dequeue = 0; + ring_buff.dequeue(dequeue); + assert(dequeue == i); + } + + for (unsigned int i = 0; i < MAX_BUFF_SIZE - 1; i++) + { + ring_buff.enqueue((int)i); + } + + for (unsigned int i = 0; i < MAX_BUFF_SIZE - 1; i++) + { + int dequeue = 0; + ring_buff.dequeue(dequeue); + assert(dequeue == i); + } + assert(ring_buff.is_empty()); + return; +} + +int multi_datatype_test() +{ + { + char enqueue = 'a'; + RingBuff ring_buff; + ring_buff.enqueue(enqueue); + + char dequeue = '0'; + ring_buff.dequeue(dequeue); + assert(enqueue == dequeue); + } + + { + unsigned long long enqueue = 100; + RingBuff ring_buff; + ring_buff.enqueue(enqueue); + + unsigned long long dequeue = 0; + ring_buff.dequeue(dequeue); + assert(enqueue == dequeue); + } + return 0; +} + +void thread_enqueue(int thread_info) +{ + for (int i = 0; i < TASK_REPEATED_TIMES; i++) + { + thread_ring_buff.enqueue(thread_info * 10000 + i); + } + return; +} + +void thread_dequeue() +{ + for (int i = 0; i < TASK_REPEATED_TIMES; i++) + { + int value = 0; + thread_ring_buff.dequeue(value); + } + return; +} + +int multi_thread_test() +{ + // enqueue + thread thead_arr[THREAD_NUM]; + for (int i = 0; i < THREAD_NUM; i++) + { + thead_arr[i] = thread(thread_enqueue, i); + } + + for (int i = 0; i < THREAD_NUM; i++) + { + thead_arr[i].join(); + } + assert(thread_ring_buff.get_size() == THREAD_NUM * TASK_REPEATED_TIMES); + + // dequeue + thread thead_arr_deque[THREAD_NUM]; + for (int i = 0; i < THREAD_NUM; i++) + { + thead_arr_deque[i] = thread(thread_dequeue); + } + for (int i = 0; i < THREAD_NUM; i++) + { + thead_arr_deque[i].join(); + } + assert(thread_ring_buff.get_size() == 0); + return 0; +} + +int main() +{ + single_test(); + size_test(); + empty_test(); + full_test(); + push_test(); + multi_datatype_test(); + multi_thread_test(); + return 0; +} \ No newline at end of file diff --git a/example_code/cas/lockfree_stack/lockfree_stack.cpp b/example_code/cas/lockfree_stack/lockfree_stack.cpp new file mode 100755 index 0000000..15c4e37 --- /dev/null +++ b/example_code/cas/lockfree_stack/lockfree_stack.cpp @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include "lockfree_stack.h" + +void Stack::push(int val, int debug_thread_info) +{ + while (true) { + Node * new_obj = new Node(val); + if (new_obj == NULL) {return;} + new_obj->extra_info = debug_thread_info; + + Node *next_ptr = this->_top; + new_obj->next = next_ptr; + + // ��ջ��ָ��ָ���½ڵ㣬CAS ֱ���ɹ� + if (this->_top.compare_exchange_weak(next_ptr, new_obj)) { + return; + } + } +} + +Node* Stack::pop() +{ + while (true) { + Node *cur_ptr = this->_top; + if (!cur_ptr) { + return NULL; + } + Node *next_ptr = cur_ptr->next; + // ��ջ��ָ��ָ����һ�ڵ㣬CAS ֱ���ɹ� + if (this->_top.compare_exchange_weak(cur_ptr, next_ptr)) { + return cur_ptr; + } + } +} + +void Stack::print() +{ + int count = 0; + Node * p = this->_top; + while (p != NULL) + { + printf("[%d, %d] -> ", p->val, p->extra_info); + p = p->next; + count++; + } + printf("\nstack count : %d\n", count); +} + +int Stack::get_size() +{ + int size = 0; + Node * p = this->_top; + while (p != NULL) + { + p = p->next; + size++; + } + return size; +} \ No newline at end of file diff --git a/example_code/cas/lockfree_stack/lockfree_stack.h b/example_code/cas/lockfree_stack/lockfree_stack.h new file mode 100755 index 0000000..51d371b --- /dev/null +++ b/example_code/cas/lockfree_stack/lockfree_stack.h @@ -0,0 +1,26 @@ +#ifndef __LOCKFREE_STACK_H__ +#define __LOCKFREE_STACK_H__ + +class Node +{ + public: + int val; + int extra_info; + + Node *next; + Node(int val): val(val), next(NULL) {} +}; + +class Stack +{ + public: + void push(int val, int debug_thread_info); + Node* pop(); + void print(); + int get_size(); + +private: + std::atomic _top; +}; + +#endif diff --git a/example_code/cas/lockfree_stack/test/unittest/Makefile b/example_code/cas/lockfree_stack/test/unittest/Makefile new file mode 100755 index 0000000..365e9f2 --- /dev/null +++ b/example_code/cas/lockfree_stack/test/unittest/Makefile @@ -0,0 +1,12 @@ +APP_EXE=unittest + +all: $(APP_EXE) + +CFLAGS += -Wsign-conversion -Wpedantic -Wall -DNDEBUG -O3 +CFLAGS += -g + +$(APP_EXE):unittest.cpp ../../lockfree_stack.h ../../lockfree_stack.cpp Makefile + g++ -std=c++11 $(CFLAGS) unittest.cpp ../../lockfree_stack.cpp -o $(APP_EXE) -lpthread + +clean: + rm $(APP_EXE) \ No newline at end of file diff --git a/example_code/cas/lockfree_stack/test/unittest/unittest b/example_code/cas/lockfree_stack/test/unittest/unittest new file mode 100755 index 0000000..0bf2610 Binary files /dev/null and b/example_code/cas/lockfree_stack/test/unittest/unittest differ diff --git a/example_code/cas/lockfree_stack/test/unittest/unittest.cpp b/example_code/cas/lockfree_stack/test/unittest/unittest.cpp new file mode 100755 index 0000000..868b5ec --- /dev/null +++ b/example_code/cas/lockfree_stack/test/unittest/unittest.cpp @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include +#include +#include +#include "../../lockfree_stack.h" + +using namespace std; +const int TASK_REPEATED_TIMES = 10; +const int THREAD_NUM = 4; + +Stack stack; + +int stack_push(int val,int thread_info) +{ + stack.push(val, thread_info); + // printf("thread id : %lu, push_val %d , info %d\n" + // , std::this_thread::get_id(), val, thread_info); + return 0; +} + +int stack_pop() +{ + Node * node = stack.pop(); + if (node == NULL) + { + printf("thread id : %lu, empty \n", std::this_thread::get_id()); + return 0; + } + // printf("thread id : %d, pop %d \n" + // , std::this_thread::get_id(), node->val); + // stack.print(); + return 0; +} + +void task_push(int thread_id) +{ + for (int i = 0; i < TASK_REPEATED_TIMES; i++) + { + stack_push(i, thread_id); + } +} + +void task_pop() +{ + for (int i = 0; i < TASK_REPEATED_TIMES; i++) + { + stack_pop(); + } +} + +void unit_test_push() +{ + thread thead_arr[THREAD_NUM]; + for (int i = 0; i < THREAD_NUM; i++) + { + int thread_info = i * 1000; + thead_arr[i] = thread(task_push, thread_info); + } + + for (int i = 0; i < THREAD_NUM; i++) + { + thead_arr[i].join(); + } + + assert(stack.get_size() == THREAD_NUM * TASK_REPEATED_TIMES); + return; +} + +void unit_test_pop() +{ + assert(stack.get_size() == THREAD_NUM * TASK_REPEATED_TIMES); + + thread thead_arr[THREAD_NUM]; + for (int i = 0; i < THREAD_NUM; i++) + { + thead_arr[i] = thread(task_pop); + } + + for (int i = 0; i < THREAD_NUM; i++) + { + thead_arr[i].join(); + } + assert(stack.get_size() == 0); + return; +} + +void unit_test_mix() +{ + printf("stack size %d", stack.get_size()); + const int push_thread_num = 20; + const int pop_thread_num = 10; + + thread thead_push[push_thread_num]; + for (int i = 0; i < push_thread_num; i++) + { + int thread_info = i * 1000; + thead_push[i] = thread(task_push, thread_info); + } + + thread thead_pop[pop_thread_num]; + for (int i = 0; i < pop_thread_num; i++) + { + thead_pop[i] = thread(task_pop); + } + + // join + for (int i = 0; i < push_thread_num; i++) + { + thead_push[i].join(); + } + for (int i = 0; i < pop_thread_num; i++) + { + thead_pop[i].join(); + } + + printf("stack size %d", stack.get_size()); + return; +} + +int main() +{ + unit_test_push(); + stack.print(); + + unit_test_pop(); + stack.print(); + + unit_test_mix(); + return 0; +} \ No newline at end of file diff --git a/example_code/condition.cc b/example_code/condition.cc old mode 100644 new mode 100755 diff --git a/example_code/coroutine_demo/coroutine/Makefile b/example_code/coroutine_demo/coroutine/Makefile new file mode 100755 index 0000000..802e25d --- /dev/null +++ b/example_code/coroutine_demo/coroutine/Makefile @@ -0,0 +1,8 @@ +all: + g++ main.cpp coroutine.cpp -g -o main + g++ unit_test.cpp coroutine.cpp -g -o unittest + +clean: + rm -f main + rm -f unit_test + rm *.o \ No newline at end of file diff --git a/example_code/coroutine_demo/coroutine/coroutine.cpp b/example_code/coroutine_demo/coroutine/coroutine.cpp new file mode 100755 index 0000000..64a8570 --- /dev/null +++ b/example_code/coroutine_demo/coroutine/coroutine.cpp @@ -0,0 +1,148 @@ +#include +#include +#include +#include "coroutine.h" + +CO_MGR* CO_MGR::instance = NULL; +void co_swap_func(CO_MGR *mgr); + +CO_MGR::CO_MGR():running_co(INVALID_IDX),cur_max_num(0) +{ + for (int i = 0; i < CO_ROUTINE_MAX; i++) + { + co_ctxs[i].state = FREE; + } +} + +CO_MGR * CO_MGR::get_instance() +{ + if (instance == NULL) + { + instance = new CO_MGR(); + return instance; + } + return instance; +} + +int co_create(CO_MGR * mgr, TaskFunc func, void *arg) +{ + int co_idx = INVALID_IDX; + for (int i = 0; i < mgr->cur_max_num; i++) + { + if (mgr->co_ctxs[i].state == FREE) + { + co_idx = i; + } + } + + if (co_idx == INVALID_IDX) + { + if (mgr->cur_max_num == CO_ROUTINE_MAX) + { + printf("coroutine num excced max, max is %d", CO_ROUTINE_MAX); + return -1; + } + + co_idx = mgr->cur_max_num; + mgr->cur_max_num++; + } + + CO_ROUTINE_CTX* co = &mgr->co_ctxs[co_idx]; + co->state = RUNNABLE; + co->func = func; + co->arg = arg; + getcontext(&(co->ctx)); + co->ctx.uc_stack.ss_sp = co->stack; + co->ctx.uc_stack.ss_size = CO_STACK_SIZE; + co->ctx.uc_stack.ss_flags = 0; + co->ctx.uc_link = &(mgr->main); + + mgr->running_co = co_idx; + + makecontext(&(co->ctx),(void (*)(void))(co_swap_func), 1, mgr); + swapcontext(&(mgr->main), &(co->ctx)); + return co_idx; +} + +int co_resume(int co_id) +{ + CO_MGR * mgr = co_mgr_get(); + CO_ROUTINE_CTX* co = &mgr->co_ctxs[co_id]; + if (co->state == SUSPEND) + { + int bak_id = mgr->running_co; + mgr->running_co = co_id; + co->state = RUNNING; + printf("resume switch co %d to %d \n", bak_id, co_id); + swapcontext(&(mgr->main), &(co->ctx)); + } + return 0; +} + +int co_yield() +{ + CO_MGR * mgr = co_mgr_get(); + + int bak = mgr->running_co; + CO_ROUTINE_CTX* co = &mgr->co_ctxs[mgr->running_co]; + co->state = SUSPEND; + mgr->running_co = -1; + printf("yield switch co %d to %d \n", bak, mgr->running_co); + + swapcontext(&(co->ctx), &(mgr->main)); + return 0; +} + +void co_swap_func(CO_MGR *mgr) +{ + if (mgr == NULL) {return;} + + if (mgr->running_co != -1) + { + CO_ROUTINE_CTX* co = &mgr->co_ctxs[mgr->running_co]; + co->func(co->arg); + + co->state = FREE; + + // uclink 指定切换到main,所以当此函数执行完毕就会切换到main + mgr->running_co = -1; + } + return; +} + +bool co_is_all_finished(CO_MGR * mgr) +{ + if (mgr == NULL) {return false;} + + for (int i = 0; i < mgr->cur_max_num; i++) + { + if (mgr->co_ctxs[i].state != FREE) + { + return false; + } + } + return true; +} + +bool co_is_dead(CO_MGR * mgr, int co_id) +{ + if (mgr == NULL) {return true;} + + if (mgr->co_ctxs[co_id].state == FREE) + { + return true; + } + return false; +} + +int get_running_co_id(CO_MGR * mgr) +{ + if (mgr == NULL) {return -1;} + return mgr->running_co; +} + +CO_MGR * co_mgr_get() +{ + CO_MGR * mgr = CO_MGR::get_instance(); + return mgr; +} \ No newline at end of file diff --git a/example_code/coroutine_demo/coroutine/coroutine.h b/example_code/coroutine_demo/coroutine/coroutine.h new file mode 100755 index 0000000..cc5a402 --- /dev/null +++ b/example_code/coroutine_demo/coroutine/coroutine.h @@ -0,0 +1,46 @@ +#ifndef __COROUTINE_H__ +#define __COROUTINE_H__ + +#include +#include + +enum ROUNTINE_STATE {FREE,RUNNABLE,RUNNING,SUSPEND}; + +typedef void (*TaskFunc)(void *arg); +const int CO_ROUTINE_MAX = 1024 * 100; // 最多可以运行10w个协程 +const int CO_STACK_SIZE = 1024 * 128; // 每个协程的大小是128k + +const int INVALID_IDX = -1; + +class CO_ROUTINE_CTX +{ +public: + ucontext_t ctx; // 协程的上下文 (协程被切出的时候,上下文保存在这里) + TaskFunc func; // 协程的任务函数 + void *arg; // 协程任务函数的函数 + enum ROUNTINE_STATE state; // 协程的状态 + char stack[CO_STACK_SIZE]; // 协程的栈空间 +}; + +class CO_MGR +{ + private: + CO_MGR(); + static CO_MGR * instance; + + public: + static CO_MGR * get_instance(); + ucontext_t main; + int cur_max_num; + int running_co; + CO_ROUTINE_CTX co_ctxs[CO_ROUTINE_MAX]; +}; + +int co_create(CO_MGR * mgr, TaskFunc func, void *arg); +int co_yield(); +int co_resume(int co_id); +bool co_is_all_finished(CO_MGR * mgr); +bool co_is_dead(CO_MGR * mgr, int co_id); +int get_running_co_id(CO_MGR * mgr); +CO_MGR * co_mgr_get(); +#endif \ No newline at end of file diff --git a/example_code/coroutine_demo/coroutine/main.cpp b/example_code/coroutine_demo/coroutine/main.cpp new file mode 100755 index 0000000..4b7819a --- /dev/null +++ b/example_code/coroutine_demo/coroutine/main.cpp @@ -0,0 +1,65 @@ +#include +#include "coroutine.h" + +struct DB_REQ_ARG +{ + int req; + int result; +}; + +int send_query_db_req(void * req) +{ + printf("do %s \n", __FUNCTION__); + return 0; +} + +void foo1(void *arg) +{ + DB_REQ_ARG * req = (DB_REQ_ARG *)arg; + send_query_db_req(req); + + CO_MGR * mgr = co_mgr_get(); + co_yield(); + printf("func resume, co id %d\n", mgr->running_co); +} + +void foo2(void *arg) +{ + DB_REQ_ARG * req = (DB_REQ_ARG *)arg; + send_query_db_req(req); + + CO_MGR * mgr = co_mgr_get(); + co_yield(); + printf("func resume once, co id %d\n", mgr->running_co); + + co_yield(); + printf("func resume twice, co id %d\n", mgr->running_co); +} + +void schedule_test() +{ + DB_REQ_ARG arg; + CO_MGR * mgr = co_mgr_get(); + + int id1 = co_create(mgr, foo1, &arg); + if (id1 < 0) {return;} + + int id2 = co_create(mgr, foo2, &arg); + if (id2 < 0) {return;} + + arg.result = 100; + while(!co_is_dead(mgr, id1) || !co_is_dead(mgr, id2)) + { + co_resume(id1); + co_resume(id2); + } + printf("===== %s end ====\n", __FUNCTION__); +} + + +int main() +{ + schedule_test(); + + return 0; +} diff --git a/example_code/coroutine_demo/demo0.cpp b/example_code/coroutine_demo/demo0.cpp new file mode 100755 index 0000000..1fdd3d7 --- /dev/null +++ b/example_code/coroutine_demo/demo0.cpp @@ -0,0 +1,25 @@ +#include + +void ping(); +void pong(); + +void ping() +{ + printf("ping\n"); + pong(); +} + +void pong() +{ + printf("pong\n"); + ping(); +} + +int main(int argc, char *argv[]) +{ + ping(); + return 0; +} + +// 运行结果: +// [1] 431 segmentation fault (core dumped) ./a.out \ No newline at end of file diff --git a/example_code/coroutine_demo/demo1.cpp b/example_code/coroutine_demo/demo1.cpp new file mode 100755 index 0000000..f46a725 --- /dev/null +++ b/example_code/coroutine_demo/demo1.cpp @@ -0,0 +1,70 @@ +#include +#include +#include + +const int MAX_COUNT = 5; + +static ucontext_t uc[3]; +static int count = 0; + +void ping(); +void pong(); + +void ping() +{ + while (count < MAX_COUNT) + { + printf("ping %d\n", ++count); + // yield to pong + sleep(1); + swapcontext(&uc[1], &uc[2]); // 保存当前context于uc[1],切换至uc[2]的context运行 + printf("ping -> end \n"); + } +} + +void pong() +{ + while (count < MAX_COUNT) + { + printf("pong %d\n", ++count); + // yield to ping + sleep(1); + swapcontext(&uc[2], &uc[1]); // 保存当前context于uc[2],切换至uc[1]的context运行 + printf("pong -> end \n"); + } +} + +char st1[8192]; +char st2[8192]; + +int main(int argc, char *argv[]) +{ + + // initialize context + printf("times %d \n", MAX_COUNT); + getcontext(&uc[1]); + getcontext(&uc[2]); + + printf("begin \n"); + + uc[1].uc_link = &uc[0]; // 这个玩意表示uc[1]运行完成后,会跳至uc[0]指向的context继续运行 + uc[1].uc_stack.ss_sp = st1; // 设置新的堆栈 + uc[1].uc_stack.ss_size = sizeof st1; + makecontext(&uc[1], ping, 0); + + uc[2].uc_link = &uc[0]; // 这个玩意表示uc[2]运行完成后,会跳至uc[0]指向的context继续运行 + uc[2].uc_stack.ss_sp = st2; // 设置新的堆栈 + uc[2].uc_stack.ss_size = sizeof st2; + makecontext(&uc[2], pong, 0); + + // start ping-pong + swapcontext(&uc[0], &uc[1]); + + // 将当前context信息保存至uc[0],跳转至uc[1]保存的context去执行 + // 这里我稍微要多说几句,因为我迷惑过,我曾经困惑的一点在于uc[0],为什么uc[0]不需要设置堆栈的信息? + // 因为swapcontext已经帮我们做好了一切,swapcontext函数会将当前点的信息保存在uc[0]中 + // 当然我们没有设置的话,默认的堆栈一定是主堆栈啦 + printf("end \n"); + + return 0; +} \ No newline at end of file diff --git a/example_code/coroutine_demo/demo2.cpp b/example_code/coroutine_demo/demo2.cpp new file mode 100755 index 0000000..a2f0ed9 --- /dev/null +++ b/example_code/coroutine_demo/demo2.cpp @@ -0,0 +1,67 @@ +#include +#include +#include + +const int MAX_COUNT = 5; + +static ucontext_t uc[4]; // 添加一个元素 +static int count = 0; + +void ping(); +void pong(); + +void ping() +{ + while (count < MAX_COUNT) + { + printf("ping %d\n", ++count); + // yield to pong + sleep(1); + swapcontext(&uc[1], &uc[2]); // 保存当前context于uc[1],切换至uc[2]的context运行 + printf("ping -> end \n"); + } +} + +void pong() +{ + while (count < MAX_COUNT) + { + printf("pong %d\n", ++count); + // yield to ping + sleep(1); + swapcontext(&uc[2], &uc[1]); // 保存当前context于uc[2],切换至uc[1]的context运行 + printf("pong -> end \n"); + } +} + +char st1[8192]; +char st2[8192]; + +int main(int argc, char *argv[]) +{ + + // initialize context + printf("times %d \n", MAX_COUNT); + getcontext(&uc[1]); + getcontext(&uc[2]); + getcontext(&uc[3]); + + printf("begin \n"); + + uc[1].uc_link = &uc[3]; // 上下文完毕之后,改成切换到uc[3] + uc[1].uc_stack.ss_sp = st1; // 设置新的堆栈 + uc[1].uc_stack.ss_size = sizeof st1; + makecontext(&uc[1], ping, 0); + + uc[2].uc_link = &uc[3]; // 上下文完毕之后,改成切换到uc[3] + uc[2].uc_stack.ss_sp = st2; // 设置新的堆栈 + uc[2].uc_stack.ss_size = sizeof st2; + makecontext(&uc[2], pong, 0); + + // start ping-pong + swapcontext(&uc[0], &uc[1]); + + printf("end \n"); + + return 0; +} \ No newline at end of file diff --git a/example_code/coroutine_demo/demo3.cpp b/example_code/coroutine_demo/demo3.cpp new file mode 100755 index 0000000..fae3d99 --- /dev/null +++ b/example_code/coroutine_demo/demo3.cpp @@ -0,0 +1,72 @@ +#include +#include +#include + +const int MAX_COUNT = 5; + +static ucontext_t uc[4]; +static int count = 0; +static int first_entry = 0; + +void ping(); +void pong(); + +void ping() +{ + while (count < MAX_COUNT) + { + printf("ping %d\n", ++count); + // yield to pong + sleep(1); + swapcontext(&uc[1], &uc[2]); // 保存当前context于uc[1],切换至uc[2]的context运行 + printf("ping -> end \n"); + } +} + +void pong() +{ + while (count < MAX_COUNT) + { + printf("pong %d\n", ++count); + // yield to ping + sleep(1); + swapcontext(&uc[2], &uc[1]); // 保存当前context于uc[2],切换至uc[1]的context运行 + printf("pong -> end \n"); + } +} + +char st1[8192]; +char st2[8192]; + +int main(int argc, char *argv[]) +{ + + // initialize context + printf("times %d \n", MAX_COUNT); + getcontext(&uc[1]); + getcontext(&uc[2]); + getcontext(&uc[3]); + + printf("begin , is_first_entry %d \n", first_entry); + + if (first_entry == 0) + { + first_entry++; + + uc[1].uc_link = &uc[3]; // + uc[1].uc_stack.ss_sp = st1; // + uc[1].uc_stack.ss_size = sizeof st1; + makecontext(&uc[1], ping, 0); + + uc[2].uc_link = &uc[3]; // + uc[2].uc_stack.ss_sp = st2; // + uc[2].uc_stack.ss_size = sizeof st2; + makecontext(&uc[2], pong, 0); + + // start ping-pong + swapcontext(&uc[0], &uc[1]); + } + printf("end \n"); + + return 0; +} \ No newline at end of file diff --git a/example_code/cpp-concurrency-master/.gitignore b/example_code/cpp-concurrency-master/.gitignore new file mode 100755 index 0000000..0eaa136 --- /dev/null +++ b/example_code/cpp-concurrency-master/.gitignore @@ -0,0 +1,29 @@ +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# bin +bin diff --git a/example_code/cpp-concurrency-master/README.md b/example_code/cpp-concurrency-master/README.md new file mode 100755 index 0000000..d9e5f7d --- /dev/null +++ b/example_code/cpp-concurrency-master/README.md @@ -0,0 +1 @@ +Source code for [C++ 并发编程](https://paul.pub/cpp-concurrency/) \ No newline at end of file diff --git a/example_code/cpp-concurrency-master/make_all.sh b/example_code/cpp-concurrency-master/make_all.sh new file mode 100755 index 0000000..3bb23ef --- /dev/null +++ b/example_code/cpp-concurrency-master/make_all.sh @@ -0,0 +1,11 @@ +rm -rf bin + +mkdir build +cd build + +cmake ../src/ +make + +cd ../ +mv build/bin ./ +rm -rf build/ diff --git a/example_code/cpp-concurrency-master/src/01_hello_thread.cpp b/example_code/cpp-concurrency-master/src/01_hello_thread.cpp new file mode 100755 index 0000000..a83076d --- /dev/null +++ b/example_code/cpp-concurrency-master/src/01_hello_thread.cpp @@ -0,0 +1,15 @@ +#include +#include + +using namespace std; + +void hello() { + cout << "Hello World from new thread." << endl; +} + +int main() { + thread t(hello); + t.join(); + + return 0; +} \ No newline at end of file diff --git a/example_code/cpp-concurrency-master/src/02_lambda_thread.cpp b/example_code/cpp-concurrency-master/src/02_lambda_thread.cpp new file mode 100755 index 0000000..d19565b --- /dev/null +++ b/example_code/cpp-concurrency-master/src/02_lambda_thread.cpp @@ -0,0 +1,14 @@ +#include +#include + +using namespace std; + +int main() { + thread t([] { + cout << "Hello World from lambda thread." << endl; + }); + + t.join(); + + return 0; +} \ No newline at end of file diff --git a/example_code/cpp-concurrency-master/src/02_thread.cpp b/example_code/cpp-concurrency-master/src/02_thread.cpp new file mode 100755 index 0000000..f8648cd --- /dev/null +++ b/example_code/cpp-concurrency-master/src/02_thread.cpp @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include + +using namespace std; + +static const int MAX = 10e8; + +static mutex gMutex; + +static double sum = 0; + +void worker(int min, int max) { + for (int i = min; i <= max; i++) { + sum += sqrt(i); + } +} + +void serial_task(int min, int max) { + auto start_time = chrono::steady_clock::now(); + sum = 0; + worker(0, MAX); + auto end_time = chrono::steady_clock::now(); + auto ms = chrono::duration_cast(end_time - start_time).count(); + cout << "Serail task finish, " << ms << " ms consumed, Result: " << sum << endl; +} + +void concurrent_worker(int min, int max) { + { + lock_guard guard(gMutex); + cout << "Thread " << this_thread::get_id() << " work for [" << min << ", " << max << "]" << endl; + } + double cur_sum = 0; + for (int i = min; i <= max; i++) { + cur_sum += sqrt(i); + } + { + lock_guard guard(gMutex); + sum += cur_sum; + } +} + +void concurrent_task(int min, int max) { + auto start_time = chrono::steady_clock::now(); + + unsigned concurrent_count = thread::hardware_concurrency(); + cout << "hardware_concurrency: " << concurrent_count << endl; + vector threads; + min = 0; + sum = 0; + for (int t = 0; t < concurrent_count; t++) { + int range = max / concurrent_count * (t + 1); + threads.push_back(thread(concurrent_worker, min, range)); + min = range + 1; + } + for (int i = 0; i < threads.size(); i++) { + threads[i].join(); + } + + auto end_time = chrono::steady_clock::now(); + auto ms = chrono::duration_cast(end_time - start_time).count(); + cout << "Concurrent task finish, " << ms << " ms consumed, Result: " << sum << endl; +} + +int main() { + serial_task(0, MAX); + concurrent_task(0, MAX); + return 0; +} \ No newline at end of file diff --git a/example_code/cpp-concurrency-master/src/03_thread_argument.cpp b/example_code/cpp-concurrency-master/src/03_thread_argument.cpp new file mode 100755 index 0000000..2b6418e --- /dev/null +++ b/example_code/cpp-concurrency-master/src/03_thread_argument.cpp @@ -0,0 +1,16 @@ +#include +#include +#include + +using namespace std; + +void hello(string name) { + cout << "Welcome to " << name << endl; +} + +int main() { + thread t(hello, "https://paul.pub/"); + t.join(); + + return 0; +} \ No newline at end of file diff --git a/example_code/cpp-concurrency-master/src/04_thread_self_manage.cpp b/example_code/cpp-concurrency-master/src/04_thread_self_manage.cpp new file mode 100755 index 0000000..40fa2e5 --- /dev/null +++ b/example_code/cpp-concurrency-master/src/04_thread_self_manage.cpp @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include + +using namespace std; + +void print_time() { + auto now = chrono::system_clock::now(); + auto in_time_t = chrono::system_clock::to_time_t(now); + + std::stringstream ss; + ss << put_time(localtime(&in_time_t), "%Y-%m-%d %X"); + cout << "now is: " << ss.str() << endl; +} + +void sleep_thread() { + this_thread::sleep_for(chrono::seconds(3)); + cout << "[thread-" << this_thread::get_id() << "] is waking up" << endl; +} + +void loop_thread() { + for (int i = 0; i < 10; i++) { + cout << "[thread-" << this_thread::get_id() << "] print: " << i << endl; + } +} + +int main() { + print_time(); + + thread t1(sleep_thread); + thread t2(loop_thread); + + t1.join(); + t2.detach(); + + print_time(); + return 0; +} \ No newline at end of file diff --git a/example_code/cpp-concurrency-master/src/05_call_once.cpp b/example_code/cpp-concurrency-master/src/05_call_once.cpp new file mode 100755 index 0000000..54f8b09 --- /dev/null +++ b/example_code/cpp-concurrency-master/src/05_call_once.cpp @@ -0,0 +1,28 @@ +#include +#include +#include + +using namespace std; + +void init() { + cout << "Initialing..." << endl; + // Do something... +} + +void worker(once_flag* flag) { + call_once(*flag, init); +} + +int main() { + once_flag flag; + + thread t1(worker, &flag); + thread t2(worker, &flag); + thread t3(worker, &flag); + + t1.join(); + t2.join(); + t3.join(); + + return 0; +} \ No newline at end of file diff --git a/example_code/cpp-concurrency-master/src/06_naive_multithread.cpp b/example_code/cpp-concurrency-master/src/06_naive_multithread.cpp new file mode 100755 index 0000000..2cd8fea --- /dev/null +++ b/example_code/cpp-concurrency-master/src/06_naive_multithread.cpp @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include + +using namespace std; + +static const int MAX = 10e8; +static double sum = 0; + +void worker(int min, int max) { + for (int i = min; i <= max; i++) { + sum += sqrt(i); + } +} + +void serial_task(int min, int max) { + auto start_time = chrono::steady_clock::now(); + sum = 0; + worker(0, MAX); + auto end_time = chrono::steady_clock::now(); + auto ms = chrono::duration_cast(end_time - start_time).count(); + cout << "Serail task finish, " << ms << " ms consumed, Result: " << sum << endl; +} + +void concurrent_task(int min, int max) { + auto start_time = chrono::steady_clock::now(); + + unsigned concurrent_count = thread::hardware_concurrency(); + cout << "hardware_concurrency: " << concurrent_count << endl; + vector threads; + min = 0; + sum = 0; + for (int t = 0; t < concurrent_count; t++) { + int range = max / concurrent_count * (t + 1); + threads.push_back(thread(worker, min, range)); + min = range + 1; + } + for (int i = 0; i < threads.size(); i++) { + threads[i].join(); + } + + auto end_time = chrono::steady_clock::now(); + auto ms = chrono::duration_cast(end_time - start_time).count(); + cout << "Concurrent task finish, " << ms << " ms consumed, Result: " << sum << endl; +} + +int main() { + serial_task(0, MAX); + concurrent_task(0, MAX); + return 0; +} \ No newline at end of file diff --git a/example_code/cpp-concurrency-master/src/07_mutex_lock.cpp b/example_code/cpp-concurrency-master/src/07_mutex_lock.cpp new file mode 100755 index 0000000..b80198c --- /dev/null +++ b/example_code/cpp-concurrency-master/src/07_mutex_lock.cpp @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include +#include + +using namespace std; + +static const int MAX = 10e8; +static double sum = 0; + +static mutex exclusive; + +void concurrent_worker(int min, int max) { + for (int i = min; i <= max; i++) { + exclusive.lock(); + sum += sqrt(i); + exclusive.unlock(); + } +} + +void concurrent_task(int min, int max) { + auto start_time = chrono::steady_clock::now(); + + unsigned concurrent_count = thread::hardware_concurrency(); + cout << "hardware_concurrency: " << concurrent_count << endl; + vector threads; + min = 0; + sum = 0; + for (int t = 0; t < concurrent_count; t++) { + int range = max / concurrent_count * (t + 1); + threads.push_back(thread(concurrent_worker, min, range)); + min = range + 1; + } + for (int i = 0; i < threads.size(); i++) { + threads[i].join(); + } + + auto end_time = chrono::steady_clock::now(); + auto ms = chrono::duration_cast(end_time - start_time).count(); + cout << "Concurrent task finish, " << ms << " ms consumed, Result: " << sum << endl; +} + +int main() { + concurrent_task(0, MAX); + return 0; +} diff --git a/example_code/cpp-concurrency-master/src/08_improved_mutex_lock.cpp b/example_code/cpp-concurrency-master/src/08_improved_mutex_lock.cpp new file mode 100755 index 0000000..b60aef7 --- /dev/null +++ b/example_code/cpp-concurrency-master/src/08_improved_mutex_lock.cpp @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include +#include + +using namespace std; + +static const int MAX = 10e8; +static double sum = 0; + +static mutex exclusive; + +void concurrent_worker(int min, int max) { + double tmp_sum = 0; + for (int i = min; i <= max; i++) { + tmp_sum += sqrt(i); + } + exclusive.lock(); + sum += tmp_sum; + exclusive.unlock(); +} + +void concurrent_task(int min, int max) { + auto start_time = chrono::steady_clock::now(); + + unsigned concurrent_count = thread::hardware_concurrency(); + cout << "hardware_concurrency: " << concurrent_count << endl; + vector threads; + min = 0; + sum = 0; + for (int t = 0; t < concurrent_count; t++) { + int range = max / concurrent_count * (t + 1); + threads.push_back(thread(concurrent_worker, min, range)); + min = range + 1; + } + for (int i = 0; i < threads.size(); i++) { + threads[i].join(); + } + + auto end_time = chrono::steady_clock::now(); + auto ms = chrono::duration_cast(end_time - start_time).count(); + cout << "Concurrent task finish, " << ms << " ms consumed, Result: " << sum << endl; +} + +int main() { + concurrent_task(0, MAX); + return 0; +} \ No newline at end of file diff --git a/example_code/cpp-concurrency-master/src/09_deadlock_bank_transfer.cpp b/example_code/cpp-concurrency-master/src/09_deadlock_bank_transfer.cpp new file mode 100755 index 0000000..0bfa5f5 --- /dev/null +++ b/example_code/cpp-concurrency-master/src/09_deadlock_bank_transfer.cpp @@ -0,0 +1,93 @@ +#include +#include +#include +#include + +using namespace std; + +class Account { +public: + Account(string name, double money): mName(name), mMoney(money) {}; + +public: + void changeMoney(double amount) { + mMoney += amount; + } + string getName() { + return mName; + } + double getMoney() { + return mMoney; + } + mutex* getLock() { + return &mMoneyLock; + } + +private: + string mName; + double mMoney; + mutex mMoneyLock; +}; + +class Bank { +public: + void addAccount(Account* account) { + mAccounts.insert(account); + } + + bool transferMoney(Account* accountA, Account* accountB, double amount) { + lock_guard guardA(*accountA->getLock()); + lock_guard guardB(*accountB->getLock()); + + if (amount > accountA->getMoney()) { + return false; + } + + accountA->changeMoney(-amount); + accountB->changeMoney(amount); + return true; + } + + double totalMoney() const { + double sum = 0; + for (auto a : mAccounts) { + sum += a->getMoney(); + } + return sum; + } + +private: + set mAccounts; +}; + +void randomTransfer(Bank* bank, Account* accountA, Account* accountB) { + while(true) { + double randomMoney = ((double)rand() / RAND_MAX) * 100; + if (bank->transferMoney(accountA, accountB, randomMoney)) { + cout << "Transfer " << randomMoney << " from " << accountA->getName() + << " to " << accountB->getName() + << ", Bank totalMoney: " << bank->totalMoney() << endl; + } else { + cout << "Transfer failed, " + << accountA->getName() << " has only $" << accountA->getMoney() << ", but " + << randomMoney << " required" << endl; + } + } +} + +int main() { + Account a("Paul", 100); + Account b("Moira", 100); + + Bank aBank; + aBank.addAccount(&a); + aBank.addAccount(&b); + + thread t1(randomTransfer, &aBank, &a, &b); + thread t2(randomTransfer, &aBank, &b, &a); + + t1.join(); + t2.join(); + + return 0; +} \ No newline at end of file diff --git a/example_code/cpp-concurrency-master/src/10_improved_bank_transfer.cpp b/example_code/cpp-concurrency-master/src/10_improved_bank_transfer.cpp new file mode 100755 index 0000000..98e4f4c --- /dev/null +++ b/example_code/cpp-concurrency-master/src/10_improved_bank_transfer.cpp @@ -0,0 +1,101 @@ +#include +#include +#include +#include + +using namespace std; + +class Account { +public: + Account(string name, double money): mName(name), mMoney(money) {}; + +public: + void changeMoney(double amount) { + mMoney += amount; + } + string getName() { + return mName; + } + double getMoney() { + return mMoney; + } + mutex* getLock() { + return &mMoneyLock; + } + +private: + string mName; + double mMoney; + mutex mMoneyLock; +}; + +class Bank { +public: + void addAccount(Account* account) { + mAccounts.insert(account); + } + + bool transferMoney(Account* accountA, Account* accountB, double amount) { + // lock(*accountA->getLock(), *accountB->getLock()); + // lock_guard lockA(*accountA->getLock(), adopt_lock); + // lock_guard lockB(*accountB->getLock(), adopt_lock); + + scoped_lock lockAll(*accountA->getLock(), *accountB->getLock()); + + if (amount > accountA->getMoney()) { + return false; + } + + accountA->changeMoney(-amount); + accountB->changeMoney(amount); + return true; + } + + double totalMoney() const { + double sum = 0; + for (auto a : mAccounts) { + sum += a->getMoney(); + } + return sum; + } + +private: + set mAccounts; +}; + +mutex sCoutLock; +void randomTransfer(Bank* bank, Account* accountA, Account* accountB) { + while(true) { + double randomMoney = ((double)rand() / RAND_MAX) * 100; + if (bank->transferMoney(accountA, accountB, randomMoney)) { + sCoutLock.lock(); + cout << "Transfer " << randomMoney << " from " << accountA->getName() + << " to " << accountB->getName() + << ", Bank totalMoney: " << bank->totalMoney() << endl; + sCoutLock.unlock(); + } else { + sCoutLock.lock(); + cout << "Transfer failed, " + << accountA->getName() << " has only " << accountA->getMoney() << ", but " + << randomMoney << " required" << endl; + sCoutLock.unlock(); + } + } +} + +int main() { + Account a("Paul", 100); + Account b("Moira", 100); + + Bank aBank; + aBank.addAccount(&a); + aBank.addAccount(&b); + + thread t1(randomTransfer, &aBank, &a, &b); + thread t2(randomTransfer, &aBank, &b, &a); + + t1.join(); + t2.join(); + + return 0; +} \ No newline at end of file diff --git a/example_code/cpp-concurrency-master/src/11_bank_transfer_wait_notify.cpp b/example_code/cpp-concurrency-master/src/11_bank_transfer_wait_notify.cpp new file mode 100755 index 0000000..5014010 --- /dev/null +++ b/example_code/cpp-concurrency-master/src/11_bank_transfer_wait_notify.cpp @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include + +using namespace std; + +class Account { +public: + Account(string name, double money): mName(name), mMoney(money) {}; + +public: + void changeMoney(double amount) { + unique_lock lock(mMoneyLock); + mConditionVar.wait(lock, [this, amount] { + return mMoney + amount > 0; + }); + mMoney += amount; + mConditionVar.notify_all(); + } + + string getName() { + return mName; + } + + double getMoney() { + return mMoney; + } + +private: + string mName; + double mMoney; + mutex mMoneyLock; + condition_variable mConditionVar; +}; + +class Bank { +public: + void addAccount(Account* account) { + mAccounts.insert(account); + } + + void transferMoney(Account* accountA, Account* accountB, double amount) { + accountA->changeMoney(-amount); + accountB->changeMoney(amount); + } + + double totalMoney() const { + double sum = 0; + for (auto a : mAccounts) { + sum += a->getMoney(); + } + return sum; + } + +private: + set mAccounts; +}; + +mutex sCoutLock; +void randomTransfer(Bank* bank, Account* accountA, Account* accountB) { + while(true) { + double randomMoney = ((double)rand() / RAND_MAX) * 100; + { + lock_guard guard(sCoutLock); + cout << "Try to Transfer " << randomMoney + << " from " << accountA->getName() << "(" << accountA->getMoney() + << ") to " << accountB->getName() << "(" << accountB->getMoney() + << "), Bank totalMoney: " << bank->totalMoney() << endl; + } + bank->transferMoney(accountA, accountB, randomMoney); + } +} + +int main() { + Account a("Paul", 100); + Account b("Moira", 100); + + Bank aBank; + aBank.addAccount(&a); + aBank.addAccount(&b); + + thread t1(randomTransfer, &aBank, &a, &b); + thread t2(randomTransfer, &aBank, &b, &a); + + t1.join(); + t2.join(); + + return 0; +} \ No newline at end of file diff --git a/example_code/cpp-concurrency-master/src/12_async_task.cpp b/example_code/cpp-concurrency-master/src/12_async_task.cpp new file mode 100755 index 0000000..bc3797a --- /dev/null +++ b/example_code/cpp-concurrency-master/src/12_async_task.cpp @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include + +using namespace std; + +static const int MAX = 10e8; +static double sum = 0; + +void worker(int min, int max) { + for (int i = min; i <= max; i++) { + sum += sqrt(i); + } +} + +class Worker { +public: + Worker(int min, int max): mMin(min), mMax(max) {} + double work() { + mResult = 0; + for (int i = mMin; i <= mMax; i++) { + mResult += sqrt(i); + } + return mResult; + } + double getResult() { + return mResult; + } + +private: + int mMin; + int mMax; + double mResult; +}; + +int main() { + sum = 0; + auto f1 = async(worker, 0, MAX); + cout << "Async task triggered" << endl; + f1.wait(); + cout << "Async task finish, result: " << sum << endl << endl; + + double result = 0; + cout << "Async task with lambda triggered, thread: " << this_thread::get_id() << endl; + auto f2 = async(launch::async, [&result]() { + cout << "Lambda task in thread: " << this_thread::get_id() << endl; + for (int i = 0; i <= MAX; i++) { + result += sqrt(i); + } + }); + f2.wait(); + cout << "Async task with lambda finish, result: " << result << endl << endl; + + Worker w(0, MAX); + cout << "Task in class triggered" << endl; + auto f3 = async(&Worker::work, &w); + f3.wait(); + cout << "Task in class finish, result: " << w.getResult() << endl << endl; + + return 0; +} \ No newline at end of file diff --git a/example_code/cpp-concurrency-master/src/13_packaged_task.cpp b/example_code/cpp-concurrency-master/src/13_packaged_task.cpp new file mode 100755 index 0000000..0ff8643 --- /dev/null +++ b/example_code/cpp-concurrency-master/src/13_packaged_task.cpp @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include + +using namespace std; + +static const int MAX = 10e8; + +double concurrent_worker(int min, int max) { + double sum = 0; + for (int i = min; i <= max; i++) { + sum += sqrt(i); + } + return sum; +} + +double concurrent_task(int min, int max) { + vector> results; + + unsigned concurrent_count = thread::hardware_concurrency(); + min = 0; + for (int i = 0; i < concurrent_count; i++) { + packaged_task task(concurrent_worker); + results.push_back(task.get_future()); + + int range = max / concurrent_count * (i + 1); + thread t(std::move(task), min, range); + t.detach(); + + min = range + 1; + } + + cout << "threads create finish" << endl; + double sum = 0; + for (auto& r : results) { + sum += r.get(); + } + return sum; +} + +int main() { + auto start_time = chrono::steady_clock::now(); + + double r = concurrent_task(0, MAX); + + auto end_time = chrono::steady_clock::now(); + auto ms = chrono::duration_cast(end_time - start_time).count(); + cout << "Concurrent task finish, " << ms << " ms consumed, Result: " << r << endl; + return 0; +} \ No newline at end of file diff --git a/example_code/cpp-concurrency-master/src/14_promise_future.cpp b/example_code/cpp-concurrency-master/src/14_promise_future.cpp new file mode 100755 index 0000000..f61f751 --- /dev/null +++ b/example_code/cpp-concurrency-master/src/14_promise_future.cpp @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include + +using namespace std; + +static const int MAX = 10e8; + +double concurrent_worker(int min, int max) { + double sum = 0; + for (int i = min; i <= max; i++) { + sum += sqrt(i); + } + return sum; +} + +void concurrent_task(int min, int max, promise* result) { + vector> results; + + unsigned concurrent_count = thread::hardware_concurrency(); + min = 0; + for (int i = 0; i < concurrent_count; i++) { + packaged_task task(concurrent_worker); + results.push_back(task.get_future()); + + int range = max / concurrent_count * (i + 1); + thread t(std::move(task), min, range); + t.detach(); + + min = range + 1; + } + + cout << "threads create finish" << endl; + double sum = 0; + for (auto& r : results) { + sum += r.get(); + } + result->set_value(sum); + cout << "concurrent_task finish" << endl; +} + +int main() { + auto start_time = chrono::steady_clock::now(); + + promise sum; + concurrent_task(0, MAX, &sum); + + auto end_time = chrono::steady_clock::now(); + auto ms = chrono::duration_cast(end_time - start_time).count(); + cout << "Concurrent task finish, " << ms << " ms consumed." << endl; + cout << "Result: " << sum.get_future().get() << endl; + return 0; +} \ No newline at end of file diff --git a/example_code/cpp-concurrency-master/src/15_parallel_algorithm.cpp b/example_code/cpp-concurrency-master/src/15_parallel_algorithm.cpp new file mode 100755 index 0000000..3a55de5 --- /dev/null +++ b/example_code/cpp-concurrency-master/src/15_parallel_algorithm.cpp @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include +#include + +using namespace std; + +void generateRandomData(vector& collection, int size) { + random_device rd; + mt19937 mt(rd()); + uniform_real_distribution dist(1.0, 100.0); + for (int i = 0; i < size; i++) { + collection.push_back(dist(mt)); + } +} + +int main() { + vector collection; + generateRandomData(collection, 10e6); + + vector copy1(collection); + vector copy2(collection); + vector copy3(collection); + + auto time1 = chrono::steady_clock::now(); + sort(execution::seq, copy1.begin(), copy1.end()); + auto time2 = chrono::steady_clock::now(); + auto duration = chrono::duration_cast(time2 - time1).count(); + cout << "Sequenced sort consuming " << duration << "ms." << endl; + + auto time3 = chrono::steady_clock::now(); + sort(execution::par, copy2.begin(),copy2.end()); + auto time4 = chrono::steady_clock::now(); + duration = chrono::duration_cast(time4 - time3).count(); + cout << "Parallel sort consuming " << duration << "ms." << endl; + + auto time5 = chrono::steady_clock::now(); + sort(execution::par_unseq, copy2.begin(),copy2.end()); + auto time6 = chrono::steady_clock::now(); + duration = chrono::duration_cast(time6 - time5).count(); + cout << "Parallel unsequenced sort consuming " << duration << "ms." << endl; +} \ No newline at end of file diff --git a/example_code/cpp-concurrency-master/src/CMakeLists.txt b/example_code/cpp-concurrency-master/src/CMakeLists.txt new file mode 100755 index 0000000..d464c51 --- /dev/null +++ b/example_code/cpp-concurrency-master/src/CMakeLists.txt @@ -0,0 +1,57 @@ +cmake_minimum_required(VERSION 3.8) +project(cpp-concurrency) + +set(CMAKE_CXX_COMPILER "g++-9") +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ./bin) + +add_executable(hello_thread 01_hello_thread.cpp) +add_executable(lambda_thread 02_lambda_thread.cpp) +add_executable(thread_argument 03_thread_argument.cpp) +add_executable(thread_self_manage 04_thread_self_manage.cpp) +add_executable(call_once 05_call_once.cpp) +add_executable(naive_multithread 06_naive_multithread.cpp) +add_executable(mutex_lock 07_mutex_lock.cpp) +add_executable(improved_mutex_lock 08_improved_mutex_lock.cpp) +add_executable(deadlock_bank_transfer 09_deadlock_bank_transfer.cpp) +add_executable(improved_bank_transfer 10_improved_bank_transfer.cpp) +add_executable(bank_transfer_wait_notify 11_bank_transfer_wait_notify.cpp) +add_executable(async_task 12_async_task.cpp) +add_executable(packaged_task 13_packaged_task.cpp) +add_executable(promise_future 14_promise_future.cpp) + +# For OS X +if(APPLE) + if (DEFINED ENV{tbb_path}) + message("tbb_path=" $ENV{tbb_path}) + include_directories($ENV{tbb_path}/include/) + link_directories($ENV{tbb_path}/lib/) + add_executable(parallel_algorithm 15_parallel_algorithm.cpp) + target_link_libraries(parallel_algorithm tbb) + else() + message("[Warning] 'tbb_path' not defined, 'export tbb_path=xxx' to build parallel algorithm.") + endif() +endif() + +# For Linux +IF("${CMAKE_SYSTEM}" MATCHES "Linux") + add_executable(parallel_algorithm 15_parallel_algorithm.cpp) + target_link_libraries(parallel_algorithm tbb) + target_link_libraries(hello_thread pthread) + target_link_libraries(lambda_thread pthread) + target_link_libraries(thread_argument pthread) + target_link_libraries(thread_self_manage pthread) + target_link_libraries(call_once pthread) + target_link_libraries(naive_multithread pthread) + target_link_libraries(mutex_lock pthread) + target_link_libraries(improved_mutex_lock pthread) + target_link_libraries(deadlock_bank_transfer pthread) + target_link_libraries(improved_bank_transfer pthread) + target_link_libraries(bank_transfer_wait_notify pthread) + target_link_libraries(async_task pthread) + target_link_libraries(packaged_task pthread) + target_link_libraries(promise_future pthread) +endif() + diff --git a/example_code/cpp/ConsistentHash.cpp b/example_code/cpp/ConsistentHash.cpp new file mode 100755 index 0000000..6adaf41 --- /dev/null +++ b/example_code/cpp/ConsistentHash.cpp @@ -0,0 +1,75 @@ +#include + +using namespace std; + +class ConsistentHash +{ +private: + unordered_set physicalServer; // ��ʵ���������� + map serverNodes; // hash ֵ�ͽڵ�ipӳ�䣨��ʵip�� + int virtualNodeNum; + hash hashStr; // �Դ��� hash ���� ����һ����Χ��size_t�ڵ���ֵ + +public: + ConsistentHash(int vnum) : virtualNodeNum(vnum){}; + void addNode(const string &ip) + { + physicalServer.insert(ip); + // ���������ڵ��ʱ��Ҳ��������ڵ� + for (int i = 0; i < virtualNodeNum; ++i) + { + stringstream key; + key << ip << "#" << i; + serverNodes.insert({hashStr(key.str()), ip}); + } + } + + void delNode(const string &ip) + { + physicalServer.erase(ip); + for (int i = 0; i < virtualNodeNum; ++i) + { + stringstream key; + key << ip << "#" << i; + serverNodes.erase(hashStr(key.str())); + } + } + + // ģ����������� hash string + string virtualInsert(int data) + { + stringstream key; + key << data; + size_t hashKey = hashStr(key.str()); + // map::lower_bound(key) : ����map�е�һ�����ڻ����key�ĵ�����ָ�� + auto iter = serverNodes.lower_bound(hashKey); + if (iter == serverNodes.end()) + { + return serverNodes.begin()->second; + } + return iter->second; + } +}; + +// g++ ConsistentHash.c -std=c++11 +// �����������һ������ +int main() +{ + // ÿ���ڵ�����10������ڵ� + ConsistentHash hash(10); + hash.addNode("127.0.0.1"); + hash.addNode("127.0.0.2"); + hash.addNode("127.0.0.3"); + + map stats; + for (int i = 0; i < 1000; ++i) + { + stats[hash.virtualInsert(i)]++; + } + + for (auto &s : stats) + { + cout << s.first << " " << setprecision(2) << s.second / (1000 * 1.0) << endl; + } + return 0; +} \ No newline at end of file diff --git a/example_code/cpp/macro.cpp b/example_code/cpp/macro.cpp old mode 100644 new mode 100755 diff --git a/example_code/design_parttern/observer.cc b/example_code/design_parttern/observer.cc old mode 100644 new mode 100755 diff --git a/example_code/epoll/client.c b/example_code/epoll/client.c new file mode 100755 index 0000000..b2ce8a2 --- /dev/null +++ b/example_code/epoll/client.c @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// ���÷����� +static void setnonblocking(int sockfd) +{ + int flag = fcntl(sockfd, F_GETFL, 0); + if (flag < 0) + { + perror("fcntl F_GETFL fail"); + return; + } + if (fcntl(sockfd, F_SETFL, flag | O_NONBLOCK) < 0) + { + perror("fcntl F_SETFL fail"); + } +} + +//��,���� +int readn(int fd, void *vptr, size_t n) +{ + /* see man 2 read */ + size_t nleft; + int nread; + char *ptr; + + ptr = (char *)vptr; + nleft = n; + while (nleft > 0) + { + nread = (int)read(fd, ptr, nleft); + if (nread < 0) + { + if (errno == EINTR) + nread = 0; /* call read() again */ + else + return -1; /* maybe errno == EAGAIN */ + } + else if (0 == nread) + { + break; /* EOF */ + } + nleft -= nread; + ptr += nread; + } + return (n - nleft); /* return >= 0 */ +} + +//д,���� +int writen(int fd, const void *vptr, size_t n) +{ + /* see man 2 write */ + size_t nleft; + int nwritten; + const char *ptr; + + ptr = (char *)vptr; + nleft = n; + while (nleft > 0) + { + nwritten = write(fd, ptr, nleft); + if (nwritten <= 0) + { + if (nwritten < 0 && errno == EINTR) + nwritten = 0; /* call write() again */ + else + return (-1); /* error */ + } + nleft -= nwritten; + ptr += nwritten; + } + return (n); +} + +int main() +{ + // socket + struct sockaddr_in servaddr; + short port = 9527; + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); + servaddr.sin_port = htons(port); + setnonblocking(sockfd); + if (connect(sockfd, (sockaddr *)&servaddr, sizeof(sockaddr_in)) < 0) + { + if (errno != EINPROGRESS) + { + perror("connect fail"); + close(sockfd); + exit(EXIT_FAILURE); + } + } + + const char *sendbuf = "hello server!"; + for (;;) + { + + // write + int len = writen(sockfd, sendbuf, strlen(sendbuf)); + if (len < 0 && errno != EAGAIN) + { + break; + } + if (len > 0) + { + printf("fd:%d, write len:%d\n", sockfd, len); + } + + // read + char recvbuf[1024 + 1] = {0}; + int res = readn(sockfd, recvbuf, 1024); + if (res < 0 && errno != EAGAIN) + { + break; + } + else if (0 == res) + { + break; + } + + if (strlen(recvbuf) > 0) + { + printf("fd:%d, read len:%ld\n", sockfd, strlen(recvbuf)); + } + + sleep(1); + } + perror("close by"); + close(sockfd); +} \ No newline at end of file diff --git a/example_code/epoll/readme.md b/example_code/epoll/readme.md new file mode 100755 index 0000000..c4b0b9d --- /dev/null +++ b/example_code/epoll/readme.md @@ -0,0 +1,5 @@ +#### epoll的demo例子 + +--server.cpp 服务器进程 + +--client.cpp 客户端进程 \ No newline at end of file diff --git a/example_code/epoll/server.c b/example_code/epoll/server.c new file mode 100755 index 0000000..bea513c --- /dev/null +++ b/example_code/epoll/server.c @@ -0,0 +1,284 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_EVENTS 1000 +#define MAX_LEN 1024 + +/* +�ο� man epoll_ctl +EPOLLIN �ɶ� +EPOLLOUT ��д +EPOLLPRI �������� +EPOLLRDHUP ���� +EPOLLERR ���� +EPOLLHUP ���� +*/ + +//���÷����� +static void setnonblocking(int sockfd) +{ + int flag = fcntl(sockfd, F_GETFL, 0); + if (flag < 0) + { + perror("fcntl F_GETFL fail"); + return; + } + if (fcntl(sockfd, F_SETFL, flag | O_NONBLOCK) < 0) + { + perror("fcntl F_SETFL fail"); + } +} + +//����epoll�¼� +static int epoll_add(int efd, int sockfd) +{ + struct epoll_event ev; + ev.events = EPOLLIN; + ev.data.fd = sockfd; + if (-1 == epoll_ctl(efd, EPOLL_CTL_ADD, sockfd, &ev)) + { + perror("epoll_ctl EPOLL_CTL_ADD fail"); + return 1; + } + return 0; +} + +//�޸�epoll�¼�,Ĭ��LT +static void epoll_write(int efd, int sockfd, bool enable) +{ + struct epoll_event ev; + ev.events = EPOLLIN | (enable ? EPOLLOUT : 0); + ev.data.fd = sockfd; + epoll_ctl(efd, EPOLL_CTL_MOD, sockfd, &ev); +} + +//ɾ��epoll�¼� +static void epoll_del(int efd, int sockfd) +{ + perror("close by"); + epoll_ctl(efd, EPOLL_CTL_DEL, sockfd, NULL); + close(sockfd); +} + +//��,���� +int readn(int fd, void *vptr, size_t n) +{ + // see man 2 read + size_t nleft; + int nread; + char *ptr; + + ptr = (char *)vptr; + nleft = n; + while (nleft > 0) + { + nread = (int)read(fd, ptr, nleft); + if (nread < 0) + { + if (errno == EINTR) + nread = 0; /* call read() again */ + else + return -1; /* maybe errno == EAGAIN */ + } + else if (0 == nread) + { + break; /* EOF */ + } + nleft -= nread; + ptr += nread; + } + return (n - nleft); /* return >= 0 */ +} + +//д,���� +int writen(int fd, const void *vptr, size_t n) +{ + // see man 2 write + size_t nleft; + int nwritten; + const char *ptr; + + ptr = (char *)vptr; + nleft = n; + while (nleft > 0) + { + nwritten = write(fd, ptr, nleft); + if (nwritten <= 0) + { + if (nwritten < 0 && errno == EINTR) + nwritten = 0; /* call write() again */ + else + return (-1); /* error */ + } + nleft -= nwritten; + ptr += nwritten; + } + return (n); +} + +int main() +{ + // socket + int listenfd; + struct sockaddr_in servaddr; + short port = 9527; + + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + servaddr.sin_port = htons(port); + + listenfd = socket(AF_INET, SOCK_STREAM, 0); + setnonblocking(listenfd); // accept����ʱ������ + int res = bind(listenfd, (sockaddr *)&servaddr, sizeof(servaddr)); + if (0 == res) + printf("server bind success, 0.0.0.0:%d\n", port); + else + { + perror("bind fail"); + exit(EXIT_FAILURE); + } + res = listen(listenfd, 100); + if (0 == res) + printf("server listen success\n"); + else + { + perror("listen fail"); + exit(EXIT_FAILURE); + } + + // epoll create,see man epoll_create + struct epoll_event ev, events[MAX_EVENTS]; + int epollfd = epoll_create(10); + if (-1 == epollfd) + { + perror("epoll_create fail"); + exit(EXIT_FAILURE); + } + + // epoll add + if (epoll_add(epollfd, listenfd)) + { + exit(EXIT_FAILURE); + } + + for (;;) + { + int nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1); + if (-1 == nfds) + { + perror("epoll_wait fail"); + exit(EXIT_FAILURE); + } + for (int n = 0; n < nfds; ++n) + { + if (events[n].data.fd == listenfd) + { + struct sockaddr_in cliaddr; + socklen_t len = sizeof(cliaddr); + int connfd = accept(listenfd, (sockaddr *)&cliaddr, &len); + if (-1 == connfd) + { + perror("accept fail"); + continue; + } + setnonblocking(connfd); + if (epoll_add(epollfd, connfd)) + { + close(connfd); + continue; + } + + // �������һЩ����,�������cliaddr + char buff[INET_ADDRSTRLEN + 1] = {0}; + inet_ntop(AF_INET, &cliaddr.sin_addr, buff, INET_ADDRSTRLEN); + uint16_t port = ntohs(cliaddr.sin_port); + printf("connection from %s, port %d\n", buff, port); + } + else if (events[n].events & EPOLLIN) + { + char buffer[MAX_LEN + 1] = {0}; /* keep the end '\0' */ + size_t count = MAX_LEN; + int connfd = events[n].data.fd; + int res = readn(connfd, buffer, count); + + // ���������쳣��� + if (res < 0 && errno != EAGAIN) + { + epoll_del(epollfd, connfd); + continue; + } + else if (0 == res) + { + epoll_del(epollfd, connfd); + continue; + } + + if (strlen(buffer) != 0) + { + printf("fd:%d, read len:%ld\n", connfd, strlen(buffer)); + } + + // ����Ҫ��������,ע��EPOLLOUT + if (strlen(buffer) != 0) + epoll_write(epollfd, connfd, true); + } + else if (events[n].events & EPOLLOUT) + { + const char *vptr = "hi client!"; /* α��ķ������� */ + int connfd = events[n].data.fd; + size_t count = strlen(vptr); + int len = writen(connfd, vptr, count); + + // ���������쳣��� + if (len < 0 && errno != EAGAIN) + { + epoll_del(epollfd, connfd); + continue; + } + + if (len > 0) + { + printf("fd:%d, write len:%d\n", connfd, len); + } + + if (len < count) + { + epoll_write(epollfd, connfd, true); /* ���п�д����,ע��EPOLLOUT */ + } + else + { + epoll_write(epollfd, connfd, false); /* �Ѿ�û�п�д����,ע��EPOLLIN */ + } + } + else if (events[n].events & EPOLLPRI) + { + // pass + } + else if (events[n].events & EPOLLRDHUP) + { + epoll_del(epollfd, events[n].data.fd); + } + else if (events[n].events & EPOLLERR) + { + epoll_del(epollfd, events[n].data.fd); + } + else if (events[n].events & EPOLLHUP) + { + epoll_del(epollfd, events[n].data.fd); + } + else + { + // pass + } + } + } +} \ No newline at end of file diff --git a/example_code/function/test.c b/example_code/function/test.c new file mode 100755 index 0000000..e5494fb --- /dev/null +++ b/example_code/function/test.c @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +int MyFunction(int x, int y); +int MyFunctionNew(int x, int y); + +char new_func[] = +{ + 0x55, + 0x48, 0x89, 0xe5, + 0x89, 0x7d, 0xec, + 0x89, 0x75, 0xe8, + + 0xc7, 0x45, 0xfc, 0x0a, 0x00, 0x00, 0x00, + + 0xc7, 0x45, 0xf8, 0x01, 0x00, 0x00, 0x00, + + 0x8b, 0x45, 0xfc, + 0x5d, + 0xc3 +}; + +void sig_user1_handler(int sig, siginfo_t *si, void *data) +{ + int pagesize = sysconf(_SC_PAGE_SIZE); + if (pagesize < 0) { + pagesize = 4096; + } + + int len = sizeof(new_func); + + uintptr_t addr = (((uintptr_t)MyFunction) / pagesize) * pagesize; + fprintf(stderr, "%s: iminus: %p, aligned: 0x%lx, sz %d\n", __func__, MyFunction, addr, len); + if (mprotect((void*)addr, (uintptr_t)MyFunction - addr + len, PROT_WRITE|PROT_READ|PROT_EXEC) < 0) { + fprintf(stderr, "%s\n", strerror(errno)); + } + + memcpy((void*)MyFunction, (void*)new_func, len); + + if (mprotect((void*)addr, (uintptr_t)MyFunction - addr + len, PROT_READ|PROT_EXEC) < 0) { + fprintf(stderr, "%s\n", strerror(errno)); + } +} + +int MyFunction(int x, int y) +{ + int a, b; + a = 10; + b = 1; + + int val = a * x + b * y; + return val; +} + +int MyFunctionNew(int x, int y) +{ + int a = 10; + return a; +} + +int main() +{ + struct sigaction newact, oldact; + sigemptyset(&newact.sa_mask); + newact.sa_sigaction = sig_user1_handler; + sigaction(SIGUSR1, &newact, &oldact); + + void * ptr = &MyFunction; + printf("addr %p , sizeof %d\n", ptr, sizeof(new_func)); + + int a = 10; + int b = 10; + + while (1) + { + int val = MyFunction(a, b); + printf("val : %d \n", val); + sleep(3); + } + return 0; +} diff --git a/example_code/function/test_asm.c b/example_code/function/test_asm.c new file mode 100755 index 0000000..d3ab336 --- /dev/null +++ b/example_code/function/test_asm.c @@ -0,0 +1,35 @@ +#include +#include +#include + +void function() +{ + while(1) + { + printf("hello,function!\n"); + sleep(1); + } +} + +void test() +{ + int val = 10; + printf("val %d\n", val); + + // set val = 11 + asm("movl $0xb, -0x4(%rbp)"); + printf("val %d\n", val); + + long addr = function; + asm("movl $0x401156, 0x18(%rbp)"); +} + +int main() +{ + printf("addr %p \n", &function); + test(); + printf("hello,world!\n"); + return 0; +} + +// https://blog.csdn.net/yiftss/article/details/89474622 \ No newline at end of file diff --git a/example_code/function/test_jmp.c b/example_code/function/test_jmp.c new file mode 100755 index 0000000..012fc26 --- /dev/null +++ b/example_code/function/test_jmp.c @@ -0,0 +1,26 @@ +#include +#include +#include + +jmp_buf env; + +int my_func(int a, int b) +{ + if (b == 0) { + printf("do not allow division by 0\n"); + longjmp(env, 1); + } + return a / b; +} + +int main(int argc, char const *argv[]) +{ + int res = setjmp(env); + if (res == 0) { + printf("return from setjmp\n"); + my_func(10, 0); + } else { + printf("return from longjmp: %d\n", res); + } + return 0; +} diff --git a/example_code/grpc_demo/demo/client.go b/example_code/grpc_demo/demo/client.go new file mode 100755 index 0000000..8f11132 --- /dev/null +++ b/example_code/grpc_demo/demo/client.go @@ -0,0 +1,110 @@ +// client/main.go +package main + +import ( + "fmt" + "io" + "log" + + "golang.org/x/net/context" + "google.golang.org/grpc" + + pb "./customer" +) + +const ( + address = "localhost:50051" +) + +// createCustomer calls the RPC method CreateCustomer of CustomerServer +func createCustomer(client pb.CustomerClient, customer *pb.CustomerRequest) { + resp, err := client.CreateCustomer(context.Background(), customer) + if err != nil { + log.Fatalf("Could not create Customer: %v", err) + } + if resp.Success { + log.Printf("A new Customer has been added with id: %d", resp.Id) + } +} + +// GetCustomers calls the RPC method GetCustomers of CustomerServer +func getCustomers(client pb.CustomerClient, filter *pb.CustomerFilter) { + // calling the streaming API + stream, err := client.GetCustomers(context.Background(), filter) + if err != nil { + log.Fatal("Error on get customers: %v", err) + } + for { + customer, err := stream.Recv() + if err == io.EOF { + break + } + + if err != nil { + log.Fatal("%v.GetCustomers(_) = _, %v", client, err) + } + log.Printf("Customer: %v", customer) + } +} + +func main() { + // Set up a connection to the RPC server + conn, err := grpc.Dial(address, grpc.WithInsecure()) + if err != nil { + log.Fatal("did not connect: %v", err) + } + defer conn.Close() + // creates a new CustomerClient + client := pb.NewCustomerClient(conn) + + customer := &pb.CustomerRequest{ + Id: 101, + Name: "Shiju Varghese", + Email: "shiju@xyz.com", + Phone: "732-757-2923", + Addresses: []*pb.CustomerRequest_Address{ + &pb.CustomerRequest_Address{ + Street: "1 Mission Street", + City: "San Francisco", + State: "CA", + Zip: "94105", + IsShippingAddress: false, + }, + &pb.CustomerRequest_Address{ + Street: "Greenfield", + City: "Kochi", + State: "KL", + Zip: "68356", + IsShippingAddress: true, + }, + }, + } + + // Create a new customer + createCustomer(client, customer) + + customer = &pb.CustomerRequest{ + Id: 102, + Name: "Irene Rose", + Email: "irene@xyz.com", + Phone: "732-757-2924", + Addresses: []*pb.CustomerRequest_Address{ + &pb.CustomerRequest_Address{ + Street: "1 Mission Street", + City: "San Francisco", + State: "CA", + Zip: "94105", + IsShippingAddress: true, + }, + }, + } + + // Create a new customer + createCustomer(client, customer) + //Filter with an empty Keyword + filter := &pb.CustomerFilter{Keyword: ""} + + fmt.Println("=====") + getCustomers(client, filter) + +} diff --git a/example_code/grpc_demo/demo/customer/customer.pb.go b/example_code/grpc_demo/demo/customer/customer.pb.go new file mode 100755 index 0000000..fa68d85 --- /dev/null +++ b/example_code/grpc_demo/demo/customer/customer.pb.go @@ -0,0 +1,435 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: customer.proto + +package customer + +import ( + context "context" + fmt "fmt" + proto "github.com/golang/protobuf/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type CustomerRequest struct { + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Email string `protobuf:"bytes,3,opt,name=email,proto3" json:"email,omitempty"` + Phone string `protobuf:"bytes,4,opt,name=phone,proto3" json:"phone,omitempty"` + Addresses []*CustomerRequest_Address `protobuf:"bytes,5,rep,name=addresses,proto3" json:"addresses,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CustomerRequest) Reset() { *m = CustomerRequest{} } +func (m *CustomerRequest) String() string { return proto.CompactTextString(m) } +func (*CustomerRequest) ProtoMessage() {} +func (*CustomerRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_9efa92dae3d6ec46, []int{0} +} + +func (m *CustomerRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CustomerRequest.Unmarshal(m, b) +} +func (m *CustomerRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CustomerRequest.Marshal(b, m, deterministic) +} +func (m *CustomerRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_CustomerRequest.Merge(m, src) +} +func (m *CustomerRequest) XXX_Size() int { + return xxx_messageInfo_CustomerRequest.Size(m) +} +func (m *CustomerRequest) XXX_DiscardUnknown() { + xxx_messageInfo_CustomerRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_CustomerRequest proto.InternalMessageInfo + +func (m *CustomerRequest) GetId() int32 { + if m != nil { + return m.Id + } + return 0 +} + +func (m *CustomerRequest) GetName() string { + if m != nil { + return m.Name + } + return "" +} + +func (m *CustomerRequest) GetEmail() string { + if m != nil { + return m.Email + } + return "" +} + +func (m *CustomerRequest) GetPhone() string { + if m != nil { + return m.Phone + } + return "" +} + +func (m *CustomerRequest) GetAddresses() []*CustomerRequest_Address { + if m != nil { + return m.Addresses + } + return nil +} + +type CustomerRequest_Address struct { + Street string `protobuf:"bytes,1,opt,name=street,proto3" json:"street,omitempty"` + City string `protobuf:"bytes,2,opt,name=city,proto3" json:"city,omitempty"` + State string `protobuf:"bytes,3,opt,name=state,proto3" json:"state,omitempty"` + Zip string `protobuf:"bytes,4,opt,name=zip,proto3" json:"zip,omitempty"` + IsShippingAddress bool `protobuf:"varint,5,opt,name=isShippingAddress,proto3" json:"isShippingAddress,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CustomerRequest_Address) Reset() { *m = CustomerRequest_Address{} } +func (m *CustomerRequest_Address) String() string { return proto.CompactTextString(m) } +func (*CustomerRequest_Address) ProtoMessage() {} +func (*CustomerRequest_Address) Descriptor() ([]byte, []int) { + return fileDescriptor_9efa92dae3d6ec46, []int{0, 0} +} + +func (m *CustomerRequest_Address) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CustomerRequest_Address.Unmarshal(m, b) +} +func (m *CustomerRequest_Address) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CustomerRequest_Address.Marshal(b, m, deterministic) +} +func (m *CustomerRequest_Address) XXX_Merge(src proto.Message) { + xxx_messageInfo_CustomerRequest_Address.Merge(m, src) +} +func (m *CustomerRequest_Address) XXX_Size() int { + return xxx_messageInfo_CustomerRequest_Address.Size(m) +} +func (m *CustomerRequest_Address) XXX_DiscardUnknown() { + xxx_messageInfo_CustomerRequest_Address.DiscardUnknown(m) +} + +var xxx_messageInfo_CustomerRequest_Address proto.InternalMessageInfo + +func (m *CustomerRequest_Address) GetStreet() string { + if m != nil { + return m.Street + } + return "" +} + +func (m *CustomerRequest_Address) GetCity() string { + if m != nil { + return m.City + } + return "" +} + +func (m *CustomerRequest_Address) GetState() string { + if m != nil { + return m.State + } + return "" +} + +func (m *CustomerRequest_Address) GetZip() string { + if m != nil { + return m.Zip + } + return "" +} + +func (m *CustomerRequest_Address) GetIsShippingAddress() bool { + if m != nil { + return m.IsShippingAddress + } + return false +} + +type CustomerResponse struct { + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Success bool `protobuf:"varint,2,opt,name=success,proto3" json:"success,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CustomerResponse) Reset() { *m = CustomerResponse{} } +func (m *CustomerResponse) String() string { return proto.CompactTextString(m) } +func (*CustomerResponse) ProtoMessage() {} +func (*CustomerResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_9efa92dae3d6ec46, []int{1} +} + +func (m *CustomerResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CustomerResponse.Unmarshal(m, b) +} +func (m *CustomerResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CustomerResponse.Marshal(b, m, deterministic) +} +func (m *CustomerResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_CustomerResponse.Merge(m, src) +} +func (m *CustomerResponse) XXX_Size() int { + return xxx_messageInfo_CustomerResponse.Size(m) +} +func (m *CustomerResponse) XXX_DiscardUnknown() { + xxx_messageInfo_CustomerResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_CustomerResponse proto.InternalMessageInfo + +func (m *CustomerResponse) GetId() int32 { + if m != nil { + return m.Id + } + return 0 +} + +func (m *CustomerResponse) GetSuccess() bool { + if m != nil { + return m.Success + } + return false +} + +type CustomerFilter struct { + Keyword string `protobuf:"bytes,1,opt,name=keyword,proto3" json:"keyword,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *CustomerFilter) Reset() { *m = CustomerFilter{} } +func (m *CustomerFilter) String() string { return proto.CompactTextString(m) } +func (*CustomerFilter) ProtoMessage() {} +func (*CustomerFilter) Descriptor() ([]byte, []int) { + return fileDescriptor_9efa92dae3d6ec46, []int{2} +} + +func (m *CustomerFilter) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_CustomerFilter.Unmarshal(m, b) +} +func (m *CustomerFilter) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_CustomerFilter.Marshal(b, m, deterministic) +} +func (m *CustomerFilter) XXX_Merge(src proto.Message) { + xxx_messageInfo_CustomerFilter.Merge(m, src) +} +func (m *CustomerFilter) XXX_Size() int { + return xxx_messageInfo_CustomerFilter.Size(m) +} +func (m *CustomerFilter) XXX_DiscardUnknown() { + xxx_messageInfo_CustomerFilter.DiscardUnknown(m) +} + +var xxx_messageInfo_CustomerFilter proto.InternalMessageInfo + +func (m *CustomerFilter) GetKeyword() string { + if m != nil { + return m.Keyword + } + return "" +} + +func init() { + proto.RegisterType((*CustomerRequest)(nil), "customer.CustomerRequest") + proto.RegisterType((*CustomerRequest_Address)(nil), "customer.CustomerRequest.Address") + proto.RegisterType((*CustomerResponse)(nil), "customer.CustomerResponse") + proto.RegisterType((*CustomerFilter)(nil), "customer.CustomerFilter") +} + +func init() { proto.RegisterFile("customer.proto", fileDescriptor_9efa92dae3d6ec46) } + +var fileDescriptor_9efa92dae3d6ec46 = []byte{ + // 326 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xef, 0x4a, 0xc3, 0x30, + 0x10, 0xc0, 0x97, 0x6e, 0xdd, 0x9f, 0x53, 0xea, 0x0c, 0x22, 0xb1, 0x9f, 0x6a, 0x3f, 0x15, 0x91, + 0x21, 0xf3, 0xab, 0x20, 0x32, 0x70, 0xf8, 0xb5, 0x3e, 0x41, 0x6d, 0x0f, 0x17, 0xdc, 0xda, 0x9a, + 0xcb, 0x90, 0xf9, 0x0a, 0xbe, 0x83, 0xcf, 0xe0, 0x23, 0x4a, 0xd2, 0x66, 0x03, 0xe7, 0xbe, 0xdd, + 0xef, 0x72, 0x77, 0xf9, 0xe5, 0x08, 0x04, 0xf9, 0x9a, 0x74, 0xb5, 0x42, 0x35, 0xa9, 0x55, 0xa5, + 0x2b, 0x3e, 0x74, 0x1c, 0xff, 0x78, 0x70, 0x32, 0x6b, 0x21, 0xc5, 0xf7, 0x35, 0x92, 0xe6, 0x01, + 0x78, 0xb2, 0x10, 0x2c, 0x62, 0x89, 0x9f, 0x7a, 0xb2, 0xe0, 0x1c, 0x7a, 0x65, 0xb6, 0x42, 0xe1, + 0x45, 0x2c, 0x19, 0xa5, 0x36, 0xe6, 0x67, 0xe0, 0xe3, 0x2a, 0x93, 0x4b, 0xd1, 0xb5, 0xc9, 0x06, + 0x4c, 0xb6, 0x5e, 0x54, 0x25, 0x8a, 0x5e, 0x93, 0xb5, 0xc0, 0xef, 0x61, 0x94, 0x15, 0x85, 0x42, + 0x22, 0x24, 0xe1, 0x47, 0xdd, 0xe4, 0x68, 0x7a, 0x39, 0xd9, 0x1a, 0xfd, 0xb9, 0x7d, 0xf2, 0xd0, + 0x94, 0xa6, 0xbb, 0x9e, 0xf0, 0x8b, 0xc1, 0xa0, 0x4d, 0xf3, 0x73, 0xe8, 0x93, 0x56, 0x88, 0xda, + 0x0a, 0x8e, 0xd2, 0x96, 0x8c, 0x64, 0x2e, 0xf5, 0xc6, 0x49, 0x9a, 0xd8, 0xe8, 0x90, 0xce, 0x34, + 0x3a, 0x49, 0x0b, 0x7c, 0x0c, 0xdd, 0x4f, 0x59, 0xb7, 0x8a, 0x26, 0xe4, 0xd7, 0x70, 0x2a, 0xe9, + 0x79, 0x21, 0xeb, 0x5a, 0x96, 0xaf, 0xed, 0x45, 0xc2, 0x8f, 0x58, 0x32, 0x4c, 0xf7, 0x0f, 0xe2, + 0x3b, 0x18, 0xef, 0x9c, 0xa9, 0xae, 0x4a, 0xc2, 0xbd, 0x95, 0x09, 0x18, 0xd0, 0x3a, 0xcf, 0xcd, + 0x1c, 0xcf, 0xce, 0x71, 0x18, 0x5f, 0x41, 0xe0, 0xba, 0x1f, 0xe5, 0x52, 0xa3, 0x32, 0xb5, 0x6f, + 0xb8, 0xf9, 0xa8, 0x54, 0xd1, 0x3e, 0xc9, 0xe1, 0xf4, 0x9b, 0xc1, 0xd0, 0x15, 0xf3, 0x39, 0x1c, + 0xcf, 0x51, 0x3b, 0x24, 0x2e, 0xf6, 0x57, 0xd8, 0x0c, 0x0c, 0x2f, 0x0e, 0x2e, 0x37, 0xee, 0xdc, + 0x30, 0xfe, 0x04, 0xc1, 0x4c, 0x61, 0xa6, 0x71, 0x3b, 0xfa, 0x70, 0x43, 0x18, 0xfe, 0x77, 0xd4, + 0x3c, 0x3a, 0xee, 0xbc, 0xf4, 0xed, 0x77, 0xba, 0xfd, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xde, 0x91, + 0xd3, 0x62, 0x60, 0x02, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// CustomerClient is the client API for Customer service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type CustomerClient interface { + // Get all Customers with filter - A server-to-client streaming RPC. + GetCustomers(ctx context.Context, in *CustomerFilter, opts ...grpc.CallOption) (Customer_GetCustomersClient, error) + // Create a new Customer - A simple RPC + CreateCustomer(ctx context.Context, in *CustomerRequest, opts ...grpc.CallOption) (*CustomerResponse, error) +} + +type customerClient struct { + cc *grpc.ClientConn +} + +func NewCustomerClient(cc *grpc.ClientConn) CustomerClient { + return &customerClient{cc} +} + +func (c *customerClient) GetCustomers(ctx context.Context, in *CustomerFilter, opts ...grpc.CallOption) (Customer_GetCustomersClient, error) { + stream, err := c.cc.NewStream(ctx, &_Customer_serviceDesc.Streams[0], "/customer.Customer/GetCustomers", opts...) + if err != nil { + return nil, err + } + x := &customerGetCustomersClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type Customer_GetCustomersClient interface { + Recv() (*CustomerRequest, error) + grpc.ClientStream +} + +type customerGetCustomersClient struct { + grpc.ClientStream +} + +func (x *customerGetCustomersClient) Recv() (*CustomerRequest, error) { + m := new(CustomerRequest) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +func (c *customerClient) CreateCustomer(ctx context.Context, in *CustomerRequest, opts ...grpc.CallOption) (*CustomerResponse, error) { + out := new(CustomerResponse) + err := c.cc.Invoke(ctx, "/customer.Customer/CreateCustomer", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// CustomerServer is the server API for Customer service. +type CustomerServer interface { + // Get all Customers with filter - A server-to-client streaming RPC. + GetCustomers(*CustomerFilter, Customer_GetCustomersServer) error + // Create a new Customer - A simple RPC + CreateCustomer(context.Context, *CustomerRequest) (*CustomerResponse, error) +} + +// UnimplementedCustomerServer can be embedded to have forward compatible implementations. +type UnimplementedCustomerServer struct { +} + +func (*UnimplementedCustomerServer) GetCustomers(req *CustomerFilter, srv Customer_GetCustomersServer) error { + return status.Errorf(codes.Unimplemented, "method GetCustomers not implemented") +} +func (*UnimplementedCustomerServer) CreateCustomer(ctx context.Context, req *CustomerRequest) (*CustomerResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateCustomer not implemented") +} + +func RegisterCustomerServer(s *grpc.Server, srv CustomerServer) { + s.RegisterService(&_Customer_serviceDesc, srv) +} + +func _Customer_GetCustomers_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(CustomerFilter) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(CustomerServer).GetCustomers(m, &customerGetCustomersServer{stream}) +} + +type Customer_GetCustomersServer interface { + Send(*CustomerRequest) error + grpc.ServerStream +} + +type customerGetCustomersServer struct { + grpc.ServerStream +} + +func (x *customerGetCustomersServer) Send(m *CustomerRequest) error { + return x.ServerStream.SendMsg(m) +} + +func _Customer_CreateCustomer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CustomerRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(CustomerServer).CreateCustomer(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/customer.Customer/CreateCustomer", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(CustomerServer).CreateCustomer(ctx, req.(*CustomerRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Customer_serviceDesc = grpc.ServiceDesc{ + ServiceName: "customer.Customer", + HandlerType: (*CustomerServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "CreateCustomer", + Handler: _Customer_CreateCustomer_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "GetCustomers", + Handler: _Customer_GetCustomers_Handler, + ServerStreams: true, + }, + }, + Metadata: "customer.proto", +} diff --git a/example_code/grpc_demo/demo/customer/customer.proto b/example_code/grpc_demo/demo/customer/customer.proto new file mode 100755 index 0000000..379058b --- /dev/null +++ b/example_code/grpc_demo/demo/customer/customer.proto @@ -0,0 +1,37 @@ +syntax = "proto3"; +package customer; + +// The Customer sercie definition +service Customer { + // Get all Customers with filter - A server-to-client streaming RPC. + rpc GetCustomers(CustomerFilter) returns (stream CustomerRequest) {} + + // Create a new Customer - A simple RPC + rpc CreateCustomer (CustomerRequest) returns (CustomerResponse) {} +} + +message CustomerRequest { + int32 id = 1; // Unique ID number for a Customer. + string name = 2; + string email = 3; + string phone = 4; + + message Address { + string street = 1; + string city = 2; + string state = 3; + string zip = 4; + bool isShippingAddress = 5; + } + + repeated Address addresses = 5; +} + +message CustomerResponse { + int32 id = 1; + bool success = 2; +} + +message CustomerFilter { + string keyword = 1; +} \ No newline at end of file diff --git a/example_code/grpc_demo/demo/main.go b/example_code/grpc_demo/demo/main.go new file mode 100755 index 0000000..1ce2267 --- /dev/null +++ b/example_code/grpc_demo/demo/main.go @@ -0,0 +1,55 @@ +// server/main.go +package main + +import ( + "log" + "net" + "strings" + + "golang.org/x/net/context" + "google.golang.org/grpc" + + pb "./customer" +) + +const ( + port = ":50051" +) + +// server is used to implement customer.CustomerServer. +type server struct { + savedCustomers []*pb.CustomerRequest +} + +// CreateCustomer creates a new Customer +func (s *server) CreateCustomer(ctx context.Context, in *pb.CustomerRequest) (*pb.CustomerResponse, error) { + s.savedCustomers = append(s.savedCustomers, in) + return &pb.CustomerResponse{Id: in.Id, Success: true}, nil +} + +// GetCustomers returns all customers by given filter +func (s *server) GetCustomers(filter *pb.CustomerFilter, stream pb.Customer_GetCustomersServer) error { + for _, customer := range s.savedCustomers { + if filter.Keyword != "" { + if !strings.Contains(customer.Name, filter.Keyword) { + continue + } + } + if err := stream.Send(customer); err != nil { + return err + } + } + return nil +} + +func main() { + lis, err := net.Listen("tcp", port) + if err != nil { + log.Fatal("failed to listen: %v", err) + } + + //Create a new grpc server + s := grpc.NewServer() + pb.RegisterCustomerServer(s, &server{}) + s.Serve(lis) +} diff --git a/example_code/grpc_demo/demo/readme.md b/example_code/grpc_demo/demo/readme.md new file mode 100755 index 0000000..5042fc7 --- /dev/null +++ b/example_code/grpc_demo/demo/readme.md @@ -0,0 +1,6 @@ +## rpc demo + +一个简单的rpc demo +1. proto包含两个服务 +2. proto里面包含了一个数组的定义方式 +3. proto里面的两个rpc,一个是普通的rpc,一个是单边流的rpc \ No newline at end of file diff --git a/example_code/grpc_demo/stream_rpc/client.go b/example_code/grpc_demo/stream_rpc/client.go new file mode 100755 index 0000000..2110729 --- /dev/null +++ b/example_code/grpc_demo/stream_rpc/client.go @@ -0,0 +1,66 @@ +package main + +import ( + "context" + "fmt" + "io" + "strconv" + + "time" + + pb "./hellostream" + "google.golang.org/grpc" +) + +func main() { + conn, e := grpc.Dial("localhost:6001", grpc.WithInsecure()) + if e != nil { + fmt.Println(e.Error()) + return + } + defer conn.Close() + c := pb.NewHelloServiceClient(conn) + + // // say hello + // r, e := c.SayHello(context.Background(), &pb.HelloRequest{Username: "ft"}) + // if e != nil { + // fmt.Println(e.Error()) + // return + // } + // fmt.Println(r.Message) + + // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + // chat + chatClilent, e := c.Chat(context.Background()) + if e != nil { + fmt.Println(e.Error()) + return + } + go func() { + for { + time.Sleep(3 * time.Second) + stream, e := chatClilent.Recv() + if e == io.EOF { + fmt.Println("EOF") + return + } + if e != nil { + fmt.Println("-----err:", e) + return + } + fmt.Println("client recv:", string(stream.Stream)) + } + }() + + go func() { + i := 0 + for { + time.Sleep(3 * time.Second) + chatClilent.Send(&pb.ClientStream{Stream: []byte("client send i:" + strconv.Itoa(i))}) + i++ + } + }() + select { + case <-time.After(20 * time.Second): + } +} diff --git a/example_code/grpc_demo/stream_rpc/hellostream/hellostream.pb.go b/example_code/grpc_demo/stream_rpc/hellostream/hellostream.pb.go new file mode 100755 index 0000000..14cbab9 --- /dev/null +++ b/example_code/grpc_demo/stream_rpc/hellostream/hellostream.pb.go @@ -0,0 +1,357 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// source: hellostream.proto + +package pb + +import ( + context "context" + fmt "fmt" + proto "github.com/golang/protobuf/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + math "math" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package + +type HelloRequest struct { + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *HelloRequest) Reset() { *m = HelloRequest{} } +func (m *HelloRequest) String() string { return proto.CompactTextString(m) } +func (*HelloRequest) ProtoMessage() {} +func (*HelloRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_ba4696d1406ab37a, []int{0} +} + +func (m *HelloRequest) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_HelloRequest.Unmarshal(m, b) +} +func (m *HelloRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_HelloRequest.Marshal(b, m, deterministic) +} +func (m *HelloRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_HelloRequest.Merge(m, src) +} +func (m *HelloRequest) XXX_Size() int { + return xxx_messageInfo_HelloRequest.Size(m) +} +func (m *HelloRequest) XXX_DiscardUnknown() { + xxx_messageInfo_HelloRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_HelloRequest proto.InternalMessageInfo + +func (m *HelloRequest) GetUsername() string { + if m != nil { + return m.Username + } + return "" +} + +type HelloResponse struct { + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *HelloResponse) Reset() { *m = HelloResponse{} } +func (m *HelloResponse) String() string { return proto.CompactTextString(m) } +func (*HelloResponse) ProtoMessage() {} +func (*HelloResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_ba4696d1406ab37a, []int{1} +} + +func (m *HelloResponse) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_HelloResponse.Unmarshal(m, b) +} +func (m *HelloResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_HelloResponse.Marshal(b, m, deterministic) +} +func (m *HelloResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_HelloResponse.Merge(m, src) +} +func (m *HelloResponse) XXX_Size() int { + return xxx_messageInfo_HelloResponse.Size(m) +} +func (m *HelloResponse) XXX_DiscardUnknown() { + xxx_messageInfo_HelloResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_HelloResponse proto.InternalMessageInfo + +func (m *HelloResponse) GetMessage() string { + if m != nil { + return m.Message + } + return "" +} + +// + +type ClientStream struct { + Stream []byte `protobuf:"bytes,1,opt,name=stream,proto3" json:"stream,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ClientStream) Reset() { *m = ClientStream{} } +func (m *ClientStream) String() string { return proto.CompactTextString(m) } +func (*ClientStream) ProtoMessage() {} +func (*ClientStream) Descriptor() ([]byte, []int) { + return fileDescriptor_ba4696d1406ab37a, []int{2} +} + +func (m *ClientStream) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ClientStream.Unmarshal(m, b) +} +func (m *ClientStream) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ClientStream.Marshal(b, m, deterministic) +} +func (m *ClientStream) XXX_Merge(src proto.Message) { + xxx_messageInfo_ClientStream.Merge(m, src) +} +func (m *ClientStream) XXX_Size() int { + return xxx_messageInfo_ClientStream.Size(m) +} +func (m *ClientStream) XXX_DiscardUnknown() { + xxx_messageInfo_ClientStream.DiscardUnknown(m) +} + +var xxx_messageInfo_ClientStream proto.InternalMessageInfo + +func (m *ClientStream) GetStream() []byte { + if m != nil { + return m.Stream + } + return nil +} + +type ServerStream struct { + Stream []byte `protobuf:"bytes,1,opt,name=stream,proto3" json:"stream,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` +} + +func (m *ServerStream) Reset() { *m = ServerStream{} } +func (m *ServerStream) String() string { return proto.CompactTextString(m) } +func (*ServerStream) ProtoMessage() {} +func (*ServerStream) Descriptor() ([]byte, []int) { + return fileDescriptor_ba4696d1406ab37a, []int{3} +} + +func (m *ServerStream) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_ServerStream.Unmarshal(m, b) +} +func (m *ServerStream) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_ServerStream.Marshal(b, m, deterministic) +} +func (m *ServerStream) XXX_Merge(src proto.Message) { + xxx_messageInfo_ServerStream.Merge(m, src) +} +func (m *ServerStream) XXX_Size() int { + return xxx_messageInfo_ServerStream.Size(m) +} +func (m *ServerStream) XXX_DiscardUnknown() { + xxx_messageInfo_ServerStream.DiscardUnknown(m) +} + +var xxx_messageInfo_ServerStream proto.InternalMessageInfo + +func (m *ServerStream) GetStream() []byte { + if m != nil { + return m.Stream + } + return nil +} + +func init() { + proto.RegisterType((*HelloRequest)(nil), "pb.HelloRequest") + proto.RegisterType((*HelloResponse)(nil), "pb.HelloResponse") + proto.RegisterType((*ClientStream)(nil), "pb.ClientStream") + proto.RegisterType((*ServerStream)(nil), "pb.ServerStream") +} + +func init() { proto.RegisterFile("hellostream.proto", fileDescriptor_ba4696d1406ab37a) } + +var fileDescriptor_ba4696d1406ab37a = []byte{ + // 205 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x90, 0xc1, 0x6a, 0x84, 0x30, + 0x14, 0x45, 0x4d, 0x29, 0xd6, 0x3e, 0x2c, 0xd4, 0x2c, 0x8a, 0xb8, 0x2a, 0x59, 0x14, 0xdb, 0x85, + 0xd8, 0xf6, 0x13, 0xdc, 0xcc, 0x5a, 0xbf, 0x20, 0x0e, 0x8f, 0x51, 0x50, 0x93, 0xc9, 0x8b, 0x03, + 0xf3, 0xf7, 0x83, 0x51, 0x87, 0xac, 0x66, 0x79, 0x6f, 0x0e, 0xdc, 0x93, 0x07, 0x49, 0x87, 0xc3, + 0xa0, 0xc8, 0x1a, 0x94, 0x63, 0xa1, 0x8d, 0xb2, 0x8a, 0x3f, 0xe9, 0x56, 0xfc, 0x40, 0x7c, 0x58, + 0x1e, 0x6a, 0x3c, 0xcf, 0x48, 0x96, 0x67, 0x10, 0xcd, 0x84, 0x66, 0x92, 0x23, 0xa6, 0xec, 0x93, + 0xe5, 0xaf, 0xf5, 0x3d, 0x8b, 0x6f, 0x78, 0xdb, 0x58, 0xd2, 0x6a, 0x22, 0xe4, 0x29, 0xbc, 0x8c, + 0x48, 0x24, 0x4f, 0x3b, 0xbb, 0x47, 0xf1, 0x05, 0x71, 0x35, 0xf4, 0x38, 0xd9, 0xc6, 0x0d, 0xf2, + 0x0f, 0x08, 0xd7, 0x69, 0x07, 0xc6, 0xf5, 0x96, 0x16, 0xae, 0x41, 0x73, 0x41, 0xf3, 0x98, 0xfb, + 0xa3, 0x4d, 0x73, 0x81, 0xfb, 0x23, 0xf2, 0x5f, 0x88, 0x1a, 0x79, 0x75, 0x15, 0x7f, 0x2f, 0x74, + 0x5b, 0xf8, 0x9f, 0xc8, 0x12, 0xaf, 0x59, 0x55, 0x45, 0xc0, 0x4b, 0x78, 0xae, 0x3a, 0x69, 0x57, + 0xdc, 0x97, 0xcb, 0x5c, 0xe3, 0x6b, 0x88, 0x20, 0x67, 0x25, 0x6b, 0x43, 0x77, 0xa6, 0xff, 0x5b, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x62, 0x40, 0x6e, 0x59, 0x3b, 0x01, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// HelloServiceClient is the client API for HelloService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type HelloServiceClient interface { + SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloResponse, error) + Chat(ctx context.Context, opts ...grpc.CallOption) (HelloService_ChatClient, error) +} + +type helloServiceClient struct { + cc *grpc.ClientConn +} + +func NewHelloServiceClient(cc *grpc.ClientConn) HelloServiceClient { + return &helloServiceClient{cc} +} + +func (c *helloServiceClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloResponse, error) { + out := new(HelloResponse) + err := c.cc.Invoke(ctx, "/pb.HelloService/SayHello", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *helloServiceClient) Chat(ctx context.Context, opts ...grpc.CallOption) (HelloService_ChatClient, error) { + stream, err := c.cc.NewStream(ctx, &_HelloService_serviceDesc.Streams[0], "/pb.HelloService/Chat", opts...) + if err != nil { + return nil, err + } + x := &helloServiceChatClient{stream} + return x, nil +} + +type HelloService_ChatClient interface { + Send(*ClientStream) error + Recv() (*ServerStream, error) + grpc.ClientStream +} + +type helloServiceChatClient struct { + grpc.ClientStream +} + +func (x *helloServiceChatClient) Send(m *ClientStream) error { + return x.ClientStream.SendMsg(m) +} + +func (x *helloServiceChatClient) Recv() (*ServerStream, error) { + m := new(ServerStream) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +// HelloServiceServer is the server API for HelloService service. +type HelloServiceServer interface { + SayHello(context.Context, *HelloRequest) (*HelloResponse, error) + Chat(HelloService_ChatServer) error +} + +// UnimplementedHelloServiceServer can be embedded to have forward compatible implementations. +type UnimplementedHelloServiceServer struct { +} + +func (*UnimplementedHelloServiceServer) SayHello(ctx context.Context, req *HelloRequest) (*HelloResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented") +} +func (*UnimplementedHelloServiceServer) Chat(srv HelloService_ChatServer) error { + return status.Errorf(codes.Unimplemented, "method Chat not implemented") +} + +func RegisterHelloServiceServer(s *grpc.Server, srv HelloServiceServer) { + s.RegisterService(&_HelloService_serviceDesc, srv) +} + +func _HelloService_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(HelloRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(HelloServiceServer).SayHello(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/pb.HelloService/SayHello", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(HelloServiceServer).SayHello(ctx, req.(*HelloRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _HelloService_Chat_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(HelloServiceServer).Chat(&helloServiceChatServer{stream}) +} + +type HelloService_ChatServer interface { + Send(*ServerStream) error + Recv() (*ClientStream, error) + grpc.ServerStream +} + +type helloServiceChatServer struct { + grpc.ServerStream +} + +func (x *helloServiceChatServer) Send(m *ServerStream) error { + return x.ServerStream.SendMsg(m) +} + +func (x *helloServiceChatServer) Recv() (*ClientStream, error) { + m := new(ClientStream) + if err := x.ServerStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + +var _HelloService_serviceDesc = grpc.ServiceDesc{ + ServiceName: "pb.HelloService", + HandlerType: (*HelloServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SayHello", + Handler: _HelloService_SayHello_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "Chat", + Handler: _HelloService_Chat_Handler, + ServerStreams: true, + ClientStreams: true, + }, + }, + Metadata: "hellostream.proto", +} diff --git a/example_code/grpc_demo/stream_rpc/hellostream/hellostream.proto b/example_code/grpc_demo/stream_rpc/hellostream/hellostream.proto new file mode 100755 index 0000000..5a36146 --- /dev/null +++ b/example_code/grpc_demo/stream_rpc/hellostream/hellostream.proto @@ -0,0 +1,23 @@ +syntax = "proto3"; +package pb; + +message HelloRequest { + string username = 1; +} + +message HelloResponse { + string message = 1; +} + +// + +message ClientStream { + bytes stream = 1; +} +message ServerStream { + bytes stream = 1; +} +service HelloService { + rpc SayHello(HelloRequest) returns (HelloResponse){} + + rpc Chat(stream ClientStream) returns (stream ServerStream){} +} \ No newline at end of file diff --git a/example_code/grpc_demo/stream_rpc/readme.md b/example_code/grpc_demo/stream_rpc/readme.md new file mode 100755 index 0000000..4d716fe --- /dev/null +++ b/example_code/grpc_demo/stream_rpc/readme.md @@ -0,0 +1 @@ +## 双边stream的rpc demo diff --git a/example_code/grpc_demo/stream_rpc/server.go b/example_code/grpc_demo/stream_rpc/server.go new file mode 100755 index 0000000..b0d2d3f --- /dev/null +++ b/example_code/grpc_demo/stream_rpc/server.go @@ -0,0 +1,69 @@ +package main + +import ( + "context" + "fmt" + "io" + "net" + "strconv" + "time" + + pb "./hellostream" + "google.golang.org/grpc" +) + +type HelloService struct { +} + +func (hs *HelloService) SayHello(ctx context.Context, req *pb.HelloRequest) (*pb.HelloResponse, error) { + return &pb.HelloResponse{Message: fmt.Sprintf("hello ,%s", req.Username)}, nil +} + +func (hs *HelloService) Chat(conn pb.HelloService_ChatServer) error { + go func() { + var i int = 100 + for { + time.Sleep(2 * time.Second) + conn.Send(&pb.ServerStream{Stream: []byte("server send i:" + strconv.Itoa(i))}) + i++ + } + }() + + for { + time.Sleep(2 * time.Second) + stream, err := conn.Recv() + if err == io.EOF { + return nil + } + if err != nil { + return err + } + fmt.Println("server recv:", string(stream.Stream)) + // fmt.Println("receive from client:", stream.Stream) + + } + + return nil +} + +// ++++++++++++++++++++ + +func main() { + lis, err := net.Listen("tcp", ":6001") + if err != nil { + fmt.Println(err.Error()) + return + } + s := grpc.NewServer() + pb.RegisterHelloServiceServer(s, &HelloService{}) + go func() { + s.Serve(lis) + }() + + fmt.Println("fmt info : ", s.GetServiceInfo()) + select {} +} + +// func newBytes(a ...byte) []byte { +// return a +// } diff --git a/example_code/linux_perf_example/high_iowait_process/app.c b/example_code/linux_perf_example/high_iowait_process/app.c old mode 100644 new mode 100755 diff --git a/example_code/linux_perf_example/high_iowait_process/readme.md b/example_code/linux_perf_example/high_iowait_process/readme.md old mode 100644 new mode 100755 diff --git a/example_code/linux_perf_example/perf_demo.c b/example_code/linux_perf_example/perf_demo.c new file mode 100755 index 0000000..1537de4 --- /dev/null +++ b/example_code/linux_perf_example/perf_demo.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int func1() +{ + int val = 0; + for(int i=0;i<100000000;i++) + { + val = val * i; + } + return val; +} + +int func2() +{ + int val = 0; + for (int i=0;i<50;i++) + { + val = val * func1(); + usleep(100); + printf("test print %d \n",i); + } + return val; +} + +int main() +{ + func2(); +} \ No newline at end of file diff --git a/example_code/linux_perf_example/readme.md b/example_code/linux_perf_example/readme.md old mode 100644 new mode 100755 diff --git a/example_code/lua/build.sh b/example_code/lua/build.sh new file mode 100755 index 0000000..73bdbad --- /dev/null +++ b/example_code/lua/build.sh @@ -0,0 +1,4 @@ +dependencies_include_path=/data/home/your_path +dependencies_lib_path=/data/home/your_lib + +g++ -g -I${dependencies_include_path}/lua-5.1.4/src -L ${dependencies_lib_path} -llua -Wl,-rpath=${dependencies_lib_path} test.cpp -o test \ No newline at end of file diff --git a/example_code/lua/test.cpp b/example_code/lua/test.cpp new file mode 100755 index 0000000..be643ce --- /dev/null +++ b/example_code/lua/test.cpp @@ -0,0 +1,93 @@ +#include +#include +#include + +extern "C" { +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +} + +// c --> 调用lua --> add_exp --> 调用c +class ACTOR +{ +public: + int id; + int exp; + std::string lua_str; +}; + +struct USE_LUA_ENV +{ + ACTOR * actor_ptr; +}; + +// lua function +USE_LUA_ENV g_use_lua_env; + +int init_lua_env(); +int lua_env_set(ACTOR * actor); +int lua_env_unset(); +int addexp(lua_State* L); + +int exec_buff(ACTOR * actor) +{ + lua_State* L = luaL_newstate(); + luaL_openlibs(L); + + // 将指定的函数注册为Lua的全局函数变量,其中第一个字符串参数为Lua代码 + // 在调用C函数时使用的全局函数名,第二个参数为实际C函数的指针。 + lua_register(L, "addexp", addexp); + + lua_env_set(actor); + + // 在注册完所有的C函数之后,即可在Lua的代码块中使用这些已经注册的C函数了。 + if (luaL_dostring(L, actor->lua_str.c_str())) + { + printf("Failed to invoke.\n"); + } + + lua_env_unset(); + lua_close(L); + printf("actor exec lua buff end \n"); + return 0; +} + +int main() +{ + ACTOR * actor = new ACTOR(); + actor->lua_str = "addexp(100)"; + actor->exp = 5; + actor->id = 10000; + + exec_buff(actor); + return 0; +} + +int init_lua_env() +{ + memset(&g_use_lua_env, 0, sizeof(g_use_lua_env)); + return 0; +} + +int lua_env_set(ACTOR * actor) +{ + g_use_lua_env.actor_ptr = actor; +} + +int lua_env_unset() +{ + g_use_lua_env.actor_ptr = 0; +} + +int addexp(lua_State* L) +{ + int exp = luaL_checknumber(L,1); + + ACTOR * actor = g_use_lua_env.actor_ptr; + if (actor == NULL) {return -1;} + + actor->exp += exp; + printf("id %d, add exp %d, cur exp %d\n", actor->id, exp, actor->exp); + return 0; +} \ No newline at end of file diff --git a/example_code/main.cc b/example_code/main.cc new file mode 100755 index 0000000..0103c78 --- /dev/null +++ b/example_code/main.cc @@ -0,0 +1,7 @@ +#include + +int main() +{ + // modify by github web + return 0; +} diff --git a/example_code/memleak_check/mem_hook/hook_demo/example/checkpasswd b/example_code/memleak_check/mem_hook/hook_demo/example/checkpasswd new file mode 100755 index 0000000..a0d9915 Binary files /dev/null and b/example_code/memleak_check/mem_hook/hook_demo/example/checkpasswd differ diff --git a/example_code/memleak_check/mem_hook/hook_demo/example/checkpasswd.cpp b/example_code/memleak_check/mem_hook/hook_demo/example/checkpasswd.cpp new file mode 100755 index 0000000..909310a --- /dev/null +++ b/example_code/memleak_check/mem_hook/hook_demo/example/checkpasswd.cpp @@ -0,0 +1,26 @@ + +#include +#include + +int main(int argc, char **argv) +{ + char passwd[] = "password"; + if (argc < 2) + { + printf("Usage: %s \n", argv[0]); + return 1; + } + + if (!strcmp(passwd, argv[1])) + { + printf("Correct Password!\n"); + return 0; + } + + printf("Invalid Password!\n"); + return 1; +} + +// g++ -Wall -fPIC -shared -o hack.so hack.cpp -ldl +// g++ checkpasswd.cpp -o checkpasswd +// LD_PRELOAD=./hack.so ./checkpasswd 90 \ No newline at end of file diff --git a/example_code/memleak_check/mem_hook/hook_demo/example/hack.cpp b/example_code/memleak_check/mem_hook/hook_demo/example/hack.cpp new file mode 100755 index 0000000..0fbeeb7 --- /dev/null +++ b/example_code/memleak_check/mem_hook/hook_demo/example/hack.cpp @@ -0,0 +1,10 @@ +#define _GNU_SOURCE + +#include +#include + +extern "C" int strcmp(const char *s1, const char *s2) +{ + printf("hack function invoked. s1=<%s> s2=<%s>\n", s1, s2); + return 0; +} \ No newline at end of file diff --git a/example_code/memleak_check/mem_hook/hook_demo/example/hack.so b/example_code/memleak_check/mem_hook/hook_demo/example/hack.so new file mode 100755 index 0000000..44b27ec Binary files /dev/null and b/example_code/memleak_check/mem_hook/hook_demo/example/hack.so differ diff --git a/example_code/memleak_check/mem_hook/hook_demo/example2/myfopen.c b/example_code/memleak_check/mem_hook/hook_demo/example2/myfopen.c new file mode 100755 index 0000000..6dd08e3 --- /dev/null +++ b/example_code/memleak_check/mem_hook/hook_demo/example2/myfopen.c @@ -0,0 +1,18 @@ +#define _GNU_SOURCE + +#include +#include + +FILE *fopen(const char *path, const char *mode) { + printf("In our own fopen, opening %s\n", path); + + FILE *(*original_fopen)(const char*, const char*); + original_fopen = dlsym(RTLD_NEXT, "fopen"); + return (*original_fopen)(path, mode); +} + +int strcmp(const char *s1, const char *s2) +{ + printf("hack function invoked. s1=<%s> s2=<%s>\n", s1, s2); + return 0; +} \ No newline at end of file diff --git a/example_code/memleak_check/mem_hook/hook_demo/example2/myfopen.so b/example_code/memleak_check/mem_hook/hook_demo/example2/myfopen.so new file mode 100755 index 0000000..d53894e Binary files /dev/null and b/example_code/memleak_check/mem_hook/hook_demo/example2/myfopen.so differ diff --git a/example_code/memleak_check/mem_hook/hook_demo/example2/prog b/example_code/memleak_check/mem_hook/hook_demo/example2/prog new file mode 100755 index 0000000..acb057b Binary files /dev/null and b/example_code/memleak_check/mem_hook/hook_demo/example2/prog differ diff --git a/example_code/memleak_check/mem_hook/hook_demo/example2/prog.c b/example_code/memleak_check/mem_hook/hook_demo/example2/prog.c new file mode 100755 index 0000000..669d632 --- /dev/null +++ b/example_code/memleak_check/mem_hook/hook_demo/example2/prog.c @@ -0,0 +1,28 @@ +#include +#include + +int main(void) { + printf("Calling the fopen() function...\n"); + + FILE *fd = fopen("test.txt", "r"); + if (!fd) { + printf("fopen() returned NULL\n"); + } + + printf("fopen() succeeded\n"); + + char passwd1[] = "password123"; + char passwd2[] = "password3435"; + if (!strcmp(passwd1, passwd2)) + { + printf("Correct Password!\n"); + return 0; + } + printf("unCorrect Password!\n"); + return 0; +} + +// gcc -Wall -fPIC -shared -o myfopen.so myfopen.c -ldl +// gcc prog.c -o prog +// LD_PRELOAD=./myfopen.so ./prog +// unset LD_PRELOAD \ No newline at end of file diff --git a/example_code/memleak_check/mem_hook/macro.h b/example_code/memleak_check/mem_hook/macro.h new file mode 100755 index 0000000..1a3ebb8 --- /dev/null +++ b/example_code/memleak_check/mem_hook/macro.h @@ -0,0 +1,6 @@ +#ifndef __MACRO_H__ +#define __MACRO_H__ + +#define new new(__FILE__, __LINE__) + +#endif \ No newline at end of file diff --git a/example_code/memleak_check/mem_hook/main.cpp b/example_code/memleak_check/mem_hook/main.cpp new file mode 100755 index 0000000..df4684b --- /dev/null +++ b/example_code/memleak_check/mem_hook/main.cpp @@ -0,0 +1,51 @@ +#include +#include +#include "test1.h" +#include "test2.h" + +using namespace std; + +struct A { + int a; +}; + +int main() +{ + test_func1(); + test_func2(); + + cout << "=====" << endl; + { + int * q1 = new int(); + delete q1; + } + { + std::cout <<"\nshared ptr" << std::endl; + shared_ptr a = make_shared(); + } + + // int * p = new(__FILE__, __LINE__) int; + // int * q = new int(); + // int * arr = new int[10]; + + // delete p; + // delete q; + // delete arr; + + // { + // int * q1 = new int(); + // delete q1; + // } + // { + // int * q2 = new int(); + // delete q2; + // } + + // { + // cout << "test shared ptr" < a = make_shared(); + // } + return 0; +} + +// g++ main.cpp test1.cpp test2.cpp memory_op.cpp -Wl,-wrap=malloc -Wl,-wrap=free \ No newline at end of file diff --git a/example_code/memleak_check/mem_hook/memory_op.cpp b/example_code/memleak_check/mem_hook/memory_op.cpp new file mode 100755 index 0000000..5278c31 --- /dev/null +++ b/example_code/memleak_check/mem_hook/memory_op.cpp @@ -0,0 +1,53 @@ +#include +#include +#include +#include + +using namespace std; + +extern "C" void * __real_malloc(size_t size); +extern "C" void __real_free(void *ptr); + +void * operator new (size_t size) +{ + cout << endl << "new size : " << size << endl ; + void *p = malloc(size); + return p; +} + +void * operator new[] (size_t size) +{ + cout << endl << "new size[] : " << size << endl ; + void *p = malloc(size); + return p; +} + +void* operator new (size_t size , const char *file , + unsigned int line ) { + if (void *ptr = malloc (size)) + { + cout << endl << "new size : " << size <<", file : " << file << " "<< line << endl ; + return ptr ; + } + throw std::bad_alloc () ; +} + +void operator delete (void *ptr ) +{ + if (ptr == nullptr) return ; + + cout << ptr << "\tsource has been released !" << endl ; + free (ptr); + ptr = nullptr; +} + + +extern "C" void * __wrap_malloc(size_t size) { + printf("my malloc: %zu\n", size); + return __real_malloc(size); +} + +extern "C" void __wrap_free(void *ptr) { + printf("my free: %p\n", ptr); + __real_free(ptr); +} \ No newline at end of file diff --git a/example_code/memleak_check/mem_hook/memory_op.h b/example_code/memleak_check/mem_hook/memory_op.h new file mode 100755 index 0000000..4af98e4 --- /dev/null +++ b/example_code/memleak_check/mem_hook/memory_op.h @@ -0,0 +1,7 @@ +#ifndef __MEM_H__ +#define __MEM_H__ + +void* operator new (size_t size , const char *file , + unsigned int line ); + +#endif \ No newline at end of file diff --git a/example_code/memleak_check/mem_hook/test1.cpp b/example_code/memleak_check/mem_hook/test1.cpp new file mode 100755 index 0000000..5753019 --- /dev/null +++ b/example_code/memleak_check/mem_hook/test1.cpp @@ -0,0 +1,10 @@ +#include "test1.h" + +int test_func1() +{ + { + int * q1 = new int(); + delete q1; + } + return 0; +} \ No newline at end of file diff --git a/example_code/memleak_check/mem_hook/test1.h b/example_code/memleak_check/mem_hook/test1.h new file mode 100755 index 0000000..b4f5782 --- /dev/null +++ b/example_code/memleak_check/mem_hook/test1.h @@ -0,0 +1,6 @@ +#ifndef __TEST1_H__ +#define __TEST1_H__ + +int test_func1(); + +#endif \ No newline at end of file diff --git a/example_code/memleak_check/mem_hook/test2.cpp b/example_code/memleak_check/mem_hook/test2.cpp new file mode 100755 index 0000000..9ef83a5 --- /dev/null +++ b/example_code/memleak_check/mem_hook/test2.cpp @@ -0,0 +1,12 @@ +#include +#include "memory_op.h" +#include "macro.h" + +int test_func2() +{ + { + int * q1 = new int(); + delete q1; + } + return 0; +} \ No newline at end of file diff --git a/example_code/memleak_check/mem_hook/test2.h b/example_code/memleak_check/mem_hook/test2.h new file mode 100755 index 0000000..dc1136f --- /dev/null +++ b/example_code/memleak_check/mem_hook/test2.h @@ -0,0 +1,6 @@ +#ifndef __TEST2_H__ +#define __TEST2_H__ + +int test_func2(); + +#endif \ No newline at end of file diff --git a/example_code/memleak_check/mem_leak_tool/macro.h b/example_code/memleak_check/mem_leak_tool/macro.h new file mode 100755 index 0000000..1a3ebb8 --- /dev/null +++ b/example_code/memleak_check/mem_leak_tool/macro.h @@ -0,0 +1,6 @@ +#ifndef __MACRO_H__ +#define __MACRO_H__ + +#define new new(__FILE__, __LINE__) + +#endif \ No newline at end of file diff --git a/example_code/memleak_check/mem_leak_tool/memery_op.cpp b/example_code/memleak_check/mem_leak_tool/memery_op.cpp new file mode 100755 index 0000000..7ddbcd9 --- /dev/null +++ b/example_code/memleak_check/mem_leak_tool/memery_op.cpp @@ -0,0 +1,143 @@ +#include +#include +#include +#include +#include +#include +#include +#include "memery_op.h" + +using namespace std; + +int total_mem_alloc = 0; + +new_ptr_list_t ptr_list_head; +std::mutex new_output_lock; +std::mutex new_ptr_lock; + +void print_position(const char * file, unsigned line) +{ + printf("check file %s, line %d", file, line); + return; +} + +void print_position(void * addr, unsigned line) +{ + printf("check file %p, line %d", addr, line); + return; +} + +static void* alloc_mem(std::size_t size, const char* file + , int line, bool is_array) +{ + assert(line >= 0); + + printf("alloc size %d, from file <%s,%d> \n", size, file, line); + std::size_t s = size + ALIGNED_LIST_ITEM_SIZE; + new_ptr_list_t* ptr = (new_ptr_list_t*)malloc(s); + if (ptr == nullptr) + { + std::unique_lock lock(new_output_lock); + printf("Out of memory when allocating %lu bytes\n" + , (unsigned long)size); + abort(); + } + void* usr_ptr = (char*)ptr + ALIGNED_LIST_ITEM_SIZE; + if (line) + { + strncpy(ptr->file, file + , _DEBUG_NEW_FILENAME_LEN - 1)[_DEBUG_NEW_FILENAME_LEN - 1] = '\0'; + } + else + { + ptr->addr = (void*)file; + } + + ptr->line = line; + ptr->is_array = is_array; + ptr->size = size; + ptr->magic = DEBUG_NEW_MAGIC; + { + ptr->next = ptr_list_head.next; + if (ptr_list_head.next != NULL) + { + ptr_list_head.next->prev = ptr; + } + + ptr->prev = &ptr_list_head; + ptr_list_head.next = ptr; + } + total_mem_alloc += size; + return usr_ptr; +} + +static void free_pointer(void* usr_ptr, void* addr, bool is_array) +{ + if (usr_ptr == nullptr) {return;} + + new_ptr_list_t* ptr = (new_ptr_list_t*)((char*)usr_ptr - ALIGNED_LIST_ITEM_SIZE); + { + std::unique_lock lock(new_ptr_lock); + total_mem_alloc -= ptr->size; + ptr->magic = 0; + printf("free pointer, object at %p (size %lu, ", usr_ptr, (unsigned long)ptr->size); + if (ptr->line != 0) + { + print_position(ptr->file, ptr->line); + } else + { + print_position(ptr->addr, ptr->line); + } + printf(")\n"); + + ptr->prev->next = ptr->next; + if (ptr->next != NULL) + { + ptr->next->prev = ptr->prev; + } + } + free(ptr); +} + +void * operator new(size_t size) +{ + return alloc_mem(size, __FILE__, __LINE__, false); +} + +void * operator new(size_t size, const char *file, unsigned int line) +{ + if (void *ptr = alloc_mem(size, file, line, false)) + { + return ptr; + } + throw std::bad_alloc(); +} + +void operator delete(void* ptr) +{ + free_pointer(ptr, nullptr, false); +} + +int checkLeaks() +{ + int leak_cnt = 0; + int whitelisted_leak_cnt = 0; + new_ptr_list_t* ptr = ptr_list_head.next; + + while (ptr != NULL) + { + const char* const usr_ptr = (char*)ptr + ALIGNED_LIST_ITEM_SIZE; + printf("Leaked object at %p (size %lu, ", usr_ptr, (unsigned long)ptr->size); + if (ptr->line != 0) + { + print_position(ptr->file, ptr->line); + } else + { + print_position(ptr->addr, ptr->line); + } + printf(")\n"); + ptr = ptr->next; + ++leak_cnt; + } + return leak_cnt; +} diff --git a/example_code/memleak_check/mem_leak_tool/memery_op.h b/example_code/memleak_check/mem_leak_tool/memery_op.h new file mode 100755 index 0000000..7dd873d --- /dev/null +++ b/example_code/memleak_check/mem_leak_tool/memery_op.h @@ -0,0 +1,34 @@ +#ifndef __MEMERY_OP_H__ +#define __MEMERY_OP_H__ + +#include + +const int _DEBUG_NEW_FILENAME_LEN = 200; +const int DEBUG_NEW_MAGIC = 0xFFFF; +const int ALIGNED_LIST_ITEM_SIZE = 1024; + +struct new_ptr_list_t +{ + new_ptr_list_t* next; + new_ptr_list_t* prev; + std::size_t size; + union + { + char file[_DEBUG_NEW_FILENAME_LEN]; + void* addr; + }; + unsigned line; + bool is_array; + int magic; + + new_ptr_list_t() + { + next = NULL; + prev = NULL; + } +}; + +int checkLeaks(); +void * operator new(size_t size); +void * operator new(size_t size, const char *file, unsigned int line); +#endif \ No newline at end of file diff --git a/example_code/memleak_check/mem_leak_tool/prog.cpp b/example_code/memleak_check/mem_leak_tool/prog.cpp new file mode 100755 index 0000000..4677ce5 --- /dev/null +++ b/example_code/memleak_check/mem_leak_tool/prog.cpp @@ -0,0 +1,30 @@ +#include "memery_op.h" +#include +#include +#include "macro.h" + +using namespace std; + +struct A { + int a; +}; + +int main() +{ + { + int * q1 = new int(); + // delete q1; + + // shared_ptr a = make_shared(); + checkLeaks(); + } + + // { + // int * q1 = new int(); + // delete q1; + // } + // checkLeaks(); + return 0; +} + +// g++ memery_op.cpp prog.cpp \ No newline at end of file diff --git a/example_code/mult_file_no_static_obj_init/Makefile b/example_code/mult_file_no_static_obj_init/Makefile new file mode 100755 index 0000000..a317ba6 --- /dev/null +++ b/example_code/mult_file_no_static_obj_init/Makefile @@ -0,0 +1,5 @@ +plan1: + g++ -o plan1 main.cpp file2.cpp file1.cpp + +plan2: + g++ -o plan2 main.cpp file1.cpp file2.cpp \ No newline at end of file diff --git a/example_code/mult_file_no_static_obj_init/file1.cpp b/example_code/mult_file_no_static_obj_init/file1.cpp new file mode 100755 index 0000000..d1ad4bb --- /dev/null +++ b/example_code/mult_file_no_static_obj_init/file1.cpp @@ -0,0 +1,12 @@ +#include "file1.h" +#include "file2.h" +#include +using namespace std; + +TEST1::TEST1() +{ + val1 = test2.val1 * test2.val2; // 构造test1初始化依赖于test2对象 + cout << "init test1" << endl; +} + +TEST1 test1; \ No newline at end of file diff --git a/example_code/mult_file_no_static_obj_init/file1.h b/example_code/mult_file_no_static_obj_init/file1.h new file mode 100755 index 0000000..4ed72be --- /dev/null +++ b/example_code/mult_file_no_static_obj_init/file1.h @@ -0,0 +1,14 @@ +#ifndef __file_1_h_ +#define __file_1_h_ + +class TEST1 +{ +public: + int val1; + int val2; + TEST1(); +}; + +extern TEST1 test1; + +#endif diff --git a/example_code/mult_file_no_static_obj_init/file2.cpp b/example_code/mult_file_no_static_obj_init/file2.cpp new file mode 100755 index 0000000..e1d326a --- /dev/null +++ b/example_code/mult_file_no_static_obj_init/file2.cpp @@ -0,0 +1,12 @@ +#include "file2.h" +#include +using namespace std; + +TEST2::TEST2() +{ + val1 = 222; + val2 = 222; + cout << "init test2" << endl; +} + +TEST2 test2; \ No newline at end of file diff --git a/example_code/mult_file_no_static_obj_init/file2.h b/example_code/mult_file_no_static_obj_init/file2.h new file mode 100755 index 0000000..70991cf --- /dev/null +++ b/example_code/mult_file_no_static_obj_init/file2.h @@ -0,0 +1,14 @@ +#ifndef __file_2_h_ +#define __file_2_h_ + +class TEST2 +{ +public: + int val1; + int val2; + TEST2(); +}; + +extern TEST2 test2; + +#endif diff --git a/example_code/mult_file_no_static_obj_init/fix_bug_demo/Makefile b/example_code/mult_file_no_static_obj_init/fix_bug_demo/Makefile new file mode 100755 index 0000000..a317ba6 --- /dev/null +++ b/example_code/mult_file_no_static_obj_init/fix_bug_demo/Makefile @@ -0,0 +1,5 @@ +plan1: + g++ -o plan1 main.cpp file2.cpp file1.cpp + +plan2: + g++ -o plan2 main.cpp file1.cpp file2.cpp \ No newline at end of file diff --git a/example_code/mult_file_no_static_obj_init/fix_bug_demo/file1.cpp b/example_code/mult_file_no_static_obj_init/fix_bug_demo/file1.cpp new file mode 100755 index 0000000..cb103ec --- /dev/null +++ b/example_code/mult_file_no_static_obj_init/fix_bug_demo/file1.cpp @@ -0,0 +1,16 @@ +#include "file1.h" +#include "file2.h" +#include +using namespace std; + +TEST1::TEST1() +{ + val1 = get_test2_obj().val1 * get_test2_obj().val2; + cout << "init test1" << endl; +} + +TEST1 &get_test1_obj() +{ + static TEST1 test1; + return test1; +} \ No newline at end of file diff --git a/example_code/mult_file_no_static_obj_init/fix_bug_demo/file1.h b/example_code/mult_file_no_static_obj_init/fix_bug_demo/file1.h new file mode 100755 index 0000000..8877221 --- /dev/null +++ b/example_code/mult_file_no_static_obj_init/fix_bug_demo/file1.h @@ -0,0 +1,14 @@ +#ifndef __file_1_h_ +#define __file_1_h_ + +class TEST1 +{ +public: + int val1; + int val2; + TEST1(); +}; + +TEST1 &get_test1_obj(); + +#endif diff --git a/example_code/mult_file_no_static_obj_init/fix_bug_demo/file2.cpp b/example_code/mult_file_no_static_obj_init/fix_bug_demo/file2.cpp new file mode 100755 index 0000000..d5f76a4 --- /dev/null +++ b/example_code/mult_file_no_static_obj_init/fix_bug_demo/file2.cpp @@ -0,0 +1,16 @@ +#include "file2.h" +#include +using namespace std; + +TEST2::TEST2() +{ + val1 = 222; + val2 = 222; + cout << "init test2" << endl; +} + +TEST2 &get_test2_obj() +{ + static TEST2 test2; + return test2; +} \ No newline at end of file diff --git a/example_code/mult_file_no_static_obj_init/fix_bug_demo/file2.h b/example_code/mult_file_no_static_obj_init/fix_bug_demo/file2.h new file mode 100755 index 0000000..d48e2ee --- /dev/null +++ b/example_code/mult_file_no_static_obj_init/fix_bug_demo/file2.h @@ -0,0 +1,13 @@ +#ifndef __file_2_h_ +#define __file_2_h_ + +class TEST2 +{ +public: + int val1; + int val2; + TEST2(); +}; + +TEST2 &get_test2_obj(); +#endif diff --git a/example_code/mult_file_no_static_obj_init/fix_bug_demo/main.cpp b/example_code/mult_file_no_static_obj_init/fix_bug_demo/main.cpp new file mode 100755 index 0000000..8d19233 --- /dev/null +++ b/example_code/mult_file_no_static_obj_init/fix_bug_demo/main.cpp @@ -0,0 +1,13 @@ +#include +#include "file1.h" +#include "file2.h" + +using namespace std; + +int main() +{ + cout << "enter main" << endl; + cout << "test1 : " << get_test1_obj().val1 << " , " << get_test1_obj().val2 << endl; + cout << "test2 : " << get_test2_obj().val1 << " , " << get_test2_obj().val2 << endl; + return 0; +} \ No newline at end of file diff --git a/example_code/mult_file_no_static_obj_init/main.cpp b/example_code/mult_file_no_static_obj_init/main.cpp new file mode 100755 index 0000000..b131bfe --- /dev/null +++ b/example_code/mult_file_no_static_obj_init/main.cpp @@ -0,0 +1,13 @@ +#include +#include "file1.h" +#include "file2.h" + +using namespace std; + +int main() +{ + cout << "enter main" << endl; + cout << "test1 : " << test1.val1 << " , " << test1.val2 << endl; + cout << "test2 : " << test2.val1 << " , " << test2.val2 << endl; + return 0; +} \ No newline at end of file diff --git a/example_code/mult_file_no_static_obj_init/readme.md b/example_code/mult_file_no_static_obj_init/readme.md new file mode 100755 index 0000000..b43ae19 --- /dev/null +++ b/example_code/mult_file_no_static_obj_init/readme.md @@ -0,0 +1,6 @@ +# 多个文件的全局变量初始化的顺序问题 + +对于同样的代码,执行make plan1,执行make plan2 编译出来的代码,执行的结果会有很大不同。 + +修改之后的代码在: +./fix_bug_demo 目录下面 \ No newline at end of file diff --git a/example_code/network/test_tcp_connect_and_close/client.cc b/example_code/network/test_tcp_connect_and_close/client.cc old mode 100644 new mode 100755 diff --git a/example_code/network/test_tcp_connect_and_close/readme.md b/example_code/network/test_tcp_connect_and_close/readme.md old mode 100644 new mode 100755 index 533f204..6664d1b --- a/example_code/network/test_tcp_connect_and_close/readme.md +++ b/example_code/network/test_tcp_connect_and_close/readme.md @@ -54,7 +54,7 @@ sudo tcpdump -n -i lo port 9999 send 函数,返回-1。 此时tcpdump没有任何输出。 -* 问题4:服务器端close之后,服务器再次尝试发送数据会发生什么? +* 问题4:服务器端close之后,服务器再次尝试接收数据会发生什么? recv 函数,返回-1。此时tcpdump没有任何输出。(recv函数返回0,表示对方关闭,返回-1,表示出错。) @@ -70,7 +70,7 @@ sudo tcpdump -n -i lo port 9999 可以看出,client向服务器发送了数据,但是服务器的读和写都关闭了,于是,服务器回复rst报文。 -* 问题6: 服务器端close之后,client向fd接受数据,会发生什么? +* 问题6: 服务器端close之后,client向fd接收数据,会发生什么? recv 函数,返回0。此时tcpdump没有任何输出。(recv函数返回0,表示对方关闭,返回-1,表示出错。) diff --git a/example_code/network/test_tcp_connect_and_close/server.cc b/example_code/network/test_tcp_connect_and_close/server.cc old mode 100644 new mode 100755 diff --git a/example_code/obj_pool/README.md b/example_code/obj_pool/README.md new file mode 100755 index 0000000..6aa72bf --- /dev/null +++ b/example_code/obj_pool/README.md @@ -0,0 +1,3 @@ +# 对象池 + +https://mp.weixin.qq.com/s/bWe8dLs-sgoCI_5sQbeOaw \ No newline at end of file diff --git a/example_code/obj_pool/pool.c b/example_code/obj_pool/pool.c new file mode 100755 index 0000000..58a5a52 --- /dev/null +++ b/example_code/obj_pool/pool.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +struct A { + A(std::string s) { str_ = std::move(s); } + + void print() { std::cout << str_ << std::endl; } + + std::string str_; +}; + +template > +class ObjectPool { + public: + ObjectPool() = default; + ~ObjectPool() { + assert(freeObjects_.size() == kInitChunkSize * (std::pow(2, pool_.size()) - 1)); + + size_t chunkSize{kInitChunkSize}; + for (auto* chunk : pool_) { + allocator_.deallocate(chunk, chunkSize); + chunkSize *= 2; + } + pool_.clear(); + } + + template + std::shared_ptr acquireObject(Args... args) { + if (freeObjects_.empty()) { + addChunk(); + } + + T* object{freeObjects_.back()}; + + new (object) T{std::forward(args)...}; + + freeObjects_.pop_back(); + + return std::shared_ptr(object, [this](T* object) { + std::_Destroy(object); + freeObjects_.push_back(object); + }); + } + + private: + std::vector pool_; + + std::vector freeObjects_; + + static const size_t kInitChunkSize{5}; + + size_t newChunkSize{kInitChunkSize}; + + void addChunk() { + std::cout << "add Chunk \n"; + + auto* firstNewObject{allocator_.allocate(newChunkSize)}; + pool_.push_back(firstNewObject); + + auto oldFreeObjectSize{freeObjects_.size()}; + freeObjects_.resize(oldFreeObjectSize + newChunkSize); + std::iota(std::begin(freeObjects_) + oldFreeObjectSize, std::end(freeObjects_), firstNewObject); + + newChunkSize *= 2; + } + + Allocator allocator_; +}; + +using APool = ObjectPool; + +int main() { + APool pool; + for (int i = 0; i < 20; i++) { + auto x = pool.acquireObject(std::string("hello")); + x->print(); + } + return 0; +} \ No newline at end of file diff --git a/example_code/pb_demo/heartbeat.db b/example_code/pb_demo/heartbeat.db new file mode 100755 index 0000000..2f20f0f --- /dev/null +++ b/example_code/pb_demo/heartbeat.db @@ -0,0 +1 @@ +�� dataNode-1000 192.168.0.128"!Everything is normal, I'm healthy \ No newline at end of file diff --git a/example_code/pb_demo/heartbeat.pb.cc b/example_code/pb_demo/heartbeat.pb.cc new file mode 100755 index 0000000..d57ab3a --- /dev/null +++ b/example_code/pb_demo/heartbeat.pb.cc @@ -0,0 +1,623 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: heartbeat.proto + +#include "heartbeat.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +// This is a temporary google only hack +#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS +#include "third_party/protobuf/version.h" +#endif +// @@protoc_insertion_point(includes) + +namespace heartbeat { +class HeartBeatMessageDefaultTypeInternal { + public: + ::google::protobuf::internal::ExplicitlyConstructed + _instance; +} _HeartBeatMessage_default_instance_; +} // namespace heartbeat +namespace protobuf_heartbeat_2eproto { +static void InitDefaultsHeartBeatMessage() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::heartbeat::_HeartBeatMessage_default_instance_; + new (ptr) ::heartbeat::HeartBeatMessage(); + ::google::protobuf::internal::OnShutdownDestroyMessage(ptr); + } + ::heartbeat::HeartBeatMessage::InitAsDefaultInstance(); +} + +::google::protobuf::internal::SCCInfo<0> scc_info_HeartBeatMessage = + {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsHeartBeatMessage}, {}}; + +void InitDefaults() { + ::google::protobuf::internal::InitSCC(&scc_info_HeartBeatMessage.base); +} + +::google::protobuf::Metadata file_level_metadata[1]; + +const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::heartbeat::HeartBeatMessage, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::heartbeat::HeartBeatMessage, datetime_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::heartbeat::HeartBeatMessage, hostname_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::heartbeat::HeartBeatMessage, ip_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::heartbeat::HeartBeatMessage, info_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::heartbeat::HeartBeatMessage, info2_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::heartbeat::HeartBeatMessage, info3_), +}; +static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, sizeof(::heartbeat::HeartBeatMessage)}, +}; + +static ::google::protobuf::Message const * const file_default_instances[] = { + reinterpret_cast(&::heartbeat::_HeartBeatMessage_default_instance_), +}; + +void protobuf_AssignDescriptors() { + AddDescriptors(); + AssignDescriptors( + "heartbeat.proto", schemas, file_default_instances, TableStruct::offsets, + file_level_metadata, NULL, NULL); +} + +void protobuf_AssignDescriptorsOnce() { + static ::google::protobuf::internal::once_flag once; + ::google::protobuf::internal::call_once(once, protobuf_AssignDescriptors); +} + +void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD; +void protobuf_RegisterTypes(const ::std::string&) { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1); +} + +void AddDescriptorsImpl() { + InitDefaults(); + static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + "\n\017heartbeat.proto\022\theartbeat\"n\n\020HeartBea" + "tMessage\022\020\n\010dateTime\030\001 \001(\003\022\020\n\010hostName\030\002" + " \001(\t\022\n\n\002ip\030\003 \001(\t\022\014\n\004info\030\004 \001(\t\022\r\n\005info2\030" + "\005 \001(\t\022\r\n\005info3\030\006 \001(\003b\006proto3" + }; + ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( + descriptor, 148); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( + "heartbeat.proto", &protobuf_RegisterTypes); +} + +void AddDescriptors() { + static ::google::protobuf::internal::once_flag once; + ::google::protobuf::internal::call_once(once, AddDescriptorsImpl); +} +// Force AddDescriptors() to be called at dynamic initialization time. +struct StaticDescriptorInitializer { + StaticDescriptorInitializer() { + AddDescriptors(); + } +} static_descriptor_initializer; +} // namespace protobuf_heartbeat_2eproto +namespace heartbeat { + +// =================================================================== + +void HeartBeatMessage::InitAsDefaultInstance() { +} +#if !defined(_MSC_VER) || _MSC_VER >= 1900 +const int HeartBeatMessage::kDateTimeFieldNumber; +const int HeartBeatMessage::kHostNameFieldNumber; +const int HeartBeatMessage::kIpFieldNumber; +const int HeartBeatMessage::kInfoFieldNumber; +const int HeartBeatMessage::kInfo2FieldNumber; +const int HeartBeatMessage::kInfo3FieldNumber; +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 + +HeartBeatMessage::HeartBeatMessage() + : ::google::protobuf::Message(), _internal_metadata_(NULL) { + ::google::protobuf::internal::InitSCC( + &protobuf_heartbeat_2eproto::scc_info_HeartBeatMessage.base); + SharedCtor(); + // @@protoc_insertion_point(constructor:heartbeat.HeartBeatMessage) +} +HeartBeatMessage::HeartBeatMessage(const HeartBeatMessage& from) + : ::google::protobuf::Message(), + _internal_metadata_(NULL) { + _internal_metadata_.MergeFrom(from._internal_metadata_); + hostname_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (from.hostname().size() > 0) { + hostname_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.hostname_); + } + ip_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (from.ip().size() > 0) { + ip_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.ip_); + } + info_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (from.info().size() > 0) { + info_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.info_); + } + info2_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (from.info2().size() > 0) { + info2_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.info2_); + } + ::memcpy(&datetime_, &from.datetime_, + static_cast(reinterpret_cast(&info3_) - + reinterpret_cast(&datetime_)) + sizeof(info3_)); + // @@protoc_insertion_point(copy_constructor:heartbeat.HeartBeatMessage) +} + +void HeartBeatMessage::SharedCtor() { + hostname_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + ip_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + info_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + info2_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + ::memset(&datetime_, 0, static_cast( + reinterpret_cast(&info3_) - + reinterpret_cast(&datetime_)) + sizeof(info3_)); +} + +HeartBeatMessage::~HeartBeatMessage() { + // @@protoc_insertion_point(destructor:heartbeat.HeartBeatMessage) + SharedDtor(); +} + +void HeartBeatMessage::SharedDtor() { + hostname_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + ip_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + info_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + info2_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + +void HeartBeatMessage::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const ::google::protobuf::Descriptor* HeartBeatMessage::descriptor() { + ::protobuf_heartbeat_2eproto::protobuf_AssignDescriptorsOnce(); + return ::protobuf_heartbeat_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +} + +const HeartBeatMessage& HeartBeatMessage::default_instance() { + ::google::protobuf::internal::InitSCC(&protobuf_heartbeat_2eproto::scc_info_HeartBeatMessage.base); + return *internal_default_instance(); +} + + +void HeartBeatMessage::Clear() { +// @@protoc_insertion_point(message_clear_start:heartbeat.HeartBeatMessage) + ::google::protobuf::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + hostname_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + ip_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + info_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + info2_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + ::memset(&datetime_, 0, static_cast( + reinterpret_cast(&info3_) - + reinterpret_cast(&datetime_)) + sizeof(info3_)); + _internal_metadata_.Clear(); +} + +bool HeartBeatMessage::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure + ::google::protobuf::uint32 tag; + // @@protoc_insertion_point(parse_start:heartbeat.HeartBeatMessage) + for (;;) { + ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); + tag = p.first; + if (!p.second) goto handle_unusual; + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // int64 dateTime = 1; + case 1: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) { + + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>( + input, &datetime_))); + } else { + goto handle_unusual; + } + break; + } + + // string hostName = 2; + case 2: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(18u /* 18 & 0xFF */)) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_hostname())); + DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->hostname().data(), static_cast(this->hostname().length()), + ::google::protobuf::internal::WireFormatLite::PARSE, + "heartbeat.HeartBeatMessage.hostName")); + } else { + goto handle_unusual; + } + break; + } + + // string ip = 3; + case 3: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_ip())); + DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->ip().data(), static_cast(this->ip().length()), + ::google::protobuf::internal::WireFormatLite::PARSE, + "heartbeat.HeartBeatMessage.ip")); + } else { + goto handle_unusual; + } + break; + } + + // string info = 4; + case 4: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(34u /* 34 & 0xFF */)) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_info())); + DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->info().data(), static_cast(this->info().length()), + ::google::protobuf::internal::WireFormatLite::PARSE, + "heartbeat.HeartBeatMessage.info")); + } else { + goto handle_unusual; + } + break; + } + + // string info2 = 5; + case 5: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(42u /* 42 & 0xFF */)) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_info2())); + DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->info2().data(), static_cast(this->info2().length()), + ::google::protobuf::internal::WireFormatLite::PARSE, + "heartbeat.HeartBeatMessage.info2")); + } else { + goto handle_unusual; + } + break; + } + + // int64 info3 = 6; + case 6: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(48u /* 48 & 0xFF */)) { + + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>( + input, &info3_))); + } else { + goto handle_unusual; + } + break; + } + + default: { + handle_unusual: + if (tag == 0) { + goto success; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, _internal_metadata_.mutable_unknown_fields())); + break; + } + } + } +success: + // @@protoc_insertion_point(parse_success:heartbeat.HeartBeatMessage) + return true; +failure: + // @@protoc_insertion_point(parse_failure:heartbeat.HeartBeatMessage) + return false; +#undef DO_ +} + +void HeartBeatMessage::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:heartbeat.HeartBeatMessage) + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int64 dateTime = 1; + if (this->datetime() != 0) { + ::google::protobuf::internal::WireFormatLite::WriteInt64(1, this->datetime(), output); + } + + // string hostName = 2; + if (this->hostname().size() > 0) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->hostname().data(), static_cast(this->hostname().length()), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "heartbeat.HeartBeatMessage.hostName"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 2, this->hostname(), output); + } + + // string ip = 3; + if (this->ip().size() > 0) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->ip().data(), static_cast(this->ip().length()), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "heartbeat.HeartBeatMessage.ip"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 3, this->ip(), output); + } + + // string info = 4; + if (this->info().size() > 0) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->info().data(), static_cast(this->info().length()), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "heartbeat.HeartBeatMessage.info"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 4, this->info(), output); + } + + // string info2 = 5; + if (this->info2().size() > 0) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->info2().data(), static_cast(this->info2().length()), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "heartbeat.HeartBeatMessage.info2"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 5, this->info2(), output); + } + + // int64 info3 = 6; + if (this->info3() != 0) { + ::google::protobuf::internal::WireFormatLite::WriteInt64(6, this->info3(), output); + } + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); + } + // @@protoc_insertion_point(serialize_end:heartbeat.HeartBeatMessage) +} + +::google::protobuf::uint8* HeartBeatMessage::InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const { + (void)deterministic; // Unused + // @@protoc_insertion_point(serialize_to_array_start:heartbeat.HeartBeatMessage) + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int64 dateTime = 1; + if (this->datetime() != 0) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(1, this->datetime(), target); + } + + // string hostName = 2; + if (this->hostname().size() > 0) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->hostname().data(), static_cast(this->hostname().length()), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "heartbeat.HeartBeatMessage.hostName"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 2, this->hostname(), target); + } + + // string ip = 3; + if (this->ip().size() > 0) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->ip().data(), static_cast(this->ip().length()), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "heartbeat.HeartBeatMessage.ip"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 3, this->ip(), target); + } + + // string info = 4; + if (this->info().size() > 0) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->info().data(), static_cast(this->info().length()), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "heartbeat.HeartBeatMessage.info"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 4, this->info(), target); + } + + // string info2 = 5; + if (this->info2().size() > 0) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->info2().data(), static_cast(this->info2().length()), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "heartbeat.HeartBeatMessage.info2"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 5, this->info2(), target); + } + + // int64 info3 = 6; + if (this->info3() != 0) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(6, this->info3(), target); + } + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + } + // @@protoc_insertion_point(serialize_to_array_end:heartbeat.HeartBeatMessage) + return target; +} + +size_t HeartBeatMessage::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:heartbeat.HeartBeatMessage) + size_t total_size = 0; + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); + } + // string hostName = 2; + if (this->hostname().size() > 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->hostname()); + } + + // string ip = 3; + if (this->ip().size() > 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->ip()); + } + + // string info = 4; + if (this->info().size() > 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->info()); + } + + // string info2 = 5; + if (this->info2().size() > 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->info2()); + } + + // int64 dateTime = 1; + if (this->datetime() != 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int64Size( + this->datetime()); + } + + // int64 info3 = 6; + if (this->info3() != 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int64Size( + this->info3()); + } + + int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void HeartBeatMessage::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:heartbeat.HeartBeatMessage) + GOOGLE_DCHECK_NE(&from, this); + const HeartBeatMessage* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); + if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:heartbeat.HeartBeatMessage) + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:heartbeat.HeartBeatMessage) + MergeFrom(*source); + } +} + +void HeartBeatMessage::MergeFrom(const HeartBeatMessage& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:heartbeat.HeartBeatMessage) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom(from._internal_metadata_); + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.hostname().size() > 0) { + + hostname_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.hostname_); + } + if (from.ip().size() > 0) { + + ip_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.ip_); + } + if (from.info().size() > 0) { + + info_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.info_); + } + if (from.info2().size() > 0) { + + info2_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.info2_); + } + if (from.datetime() != 0) { + set_datetime(from.datetime()); + } + if (from.info3() != 0) { + set_info3(from.info3()); + } +} + +void HeartBeatMessage::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:heartbeat.HeartBeatMessage) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void HeartBeatMessage::CopyFrom(const HeartBeatMessage& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:heartbeat.HeartBeatMessage) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool HeartBeatMessage::IsInitialized() const { + return true; +} + +void HeartBeatMessage::Swap(HeartBeatMessage* other) { + if (other == this) return; + InternalSwap(other); +} +void HeartBeatMessage::InternalSwap(HeartBeatMessage* other) { + using std::swap; + hostname_.Swap(&other->hostname_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); + ip_.Swap(&other->ip_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); + info_.Swap(&other->info_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); + info2_.Swap(&other->info2_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); + swap(datetime_, other->datetime_); + swap(info3_, other->info3_); + _internal_metadata_.Swap(&other->_internal_metadata_); +} + +::google::protobuf::Metadata HeartBeatMessage::GetMetadata() const { + protobuf_heartbeat_2eproto::protobuf_AssignDescriptorsOnce(); + return ::protobuf_heartbeat_2eproto::file_level_metadata[kIndexInFileMessages]; +} + + +// @@protoc_insertion_point(namespace_scope) +} // namespace heartbeat +namespace google { +namespace protobuf { +template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::heartbeat::HeartBeatMessage* Arena::CreateMaybeMessage< ::heartbeat::HeartBeatMessage >(Arena* arena) { + return Arena::CreateInternal< ::heartbeat::HeartBeatMessage >(arena); +} +} // namespace protobuf +} // namespace google + +// @@protoc_insertion_point(global_scope) diff --git a/example_code/pb_demo/heartbeat.pb.h b/example_code/pb_demo/heartbeat.pb.h new file mode 100755 index 0000000..61909d6 --- /dev/null +++ b/example_code/pb_demo/heartbeat.pb.h @@ -0,0 +1,491 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: heartbeat.proto + +#ifndef PROTOBUF_INCLUDED_heartbeat_2eproto +#define PROTOBUF_INCLUDED_heartbeat_2eproto + +#include + +#include + +#if GOOGLE_PROTOBUF_VERSION < 3006001 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 3006001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include // IWYU pragma: export +#include // IWYU pragma: export +#include +// @@protoc_insertion_point(includes) +#define PROTOBUF_INTERNAL_EXPORT_protobuf_heartbeat_2eproto + +namespace protobuf_heartbeat_2eproto { +// Internal implementation detail -- do not use these members. +struct TableStruct { + static const ::google::protobuf::internal::ParseTableField entries[]; + static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; + static const ::google::protobuf::internal::ParseTable schema[1]; + static const ::google::protobuf::internal::FieldMetadata field_metadata[]; + static const ::google::protobuf::internal::SerializationTable serialization_table[]; + static const ::google::protobuf::uint32 offsets[]; +}; +void AddDescriptors(); +} // namespace protobuf_heartbeat_2eproto +namespace heartbeat { +class HeartBeatMessage; +class HeartBeatMessageDefaultTypeInternal; +extern HeartBeatMessageDefaultTypeInternal _HeartBeatMessage_default_instance_; +} // namespace heartbeat +namespace google { +namespace protobuf { +template<> ::heartbeat::HeartBeatMessage* Arena::CreateMaybeMessage<::heartbeat::HeartBeatMessage>(Arena*); +} // namespace protobuf +} // namespace google +namespace heartbeat { + +// =================================================================== + +class HeartBeatMessage : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:heartbeat.HeartBeatMessage) */ { + public: + HeartBeatMessage(); + virtual ~HeartBeatMessage(); + + HeartBeatMessage(const HeartBeatMessage& from); + + inline HeartBeatMessage& operator=(const HeartBeatMessage& from) { + CopyFrom(from); + return *this; + } + #if LANG_CXX11 + HeartBeatMessage(HeartBeatMessage&& from) noexcept + : HeartBeatMessage() { + *this = ::std::move(from); + } + + inline HeartBeatMessage& operator=(HeartBeatMessage&& from) noexcept { + if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + #endif + static const ::google::protobuf::Descriptor* descriptor(); + static const HeartBeatMessage& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const HeartBeatMessage* internal_default_instance() { + return reinterpret_cast( + &_HeartBeatMessage_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + void Swap(HeartBeatMessage* other); + friend void swap(HeartBeatMessage& a, HeartBeatMessage& b) { + a.Swap(&b); + } + + // implements Message ---------------------------------------------- + + inline HeartBeatMessage* New() const final { + return CreateMaybeMessage(NULL); + } + + HeartBeatMessage* New(::google::protobuf::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::google::protobuf::Message& from) final; + void MergeFrom(const ::google::protobuf::Message& from) final; + void CopyFrom(const HeartBeatMessage& from); + void MergeFrom(const HeartBeatMessage& from); + void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) final; + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const final; + ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(HeartBeatMessage* other); + private: + inline ::google::protobuf::Arena* GetArenaNoVirtual() const { + return NULL; + } + inline void* MaybeArenaPtr() const { + return NULL; + } + public: + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // string hostName = 2; + void clear_hostname(); + static const int kHostNameFieldNumber = 2; + const ::std::string& hostname() const; + void set_hostname(const ::std::string& value); + #if LANG_CXX11 + void set_hostname(::std::string&& value); + #endif + void set_hostname(const char* value); + void set_hostname(const char* value, size_t size); + ::std::string* mutable_hostname(); + ::std::string* release_hostname(); + void set_allocated_hostname(::std::string* hostname); + + // string ip = 3; + void clear_ip(); + static const int kIpFieldNumber = 3; + const ::std::string& ip() const; + void set_ip(const ::std::string& value); + #if LANG_CXX11 + void set_ip(::std::string&& value); + #endif + void set_ip(const char* value); + void set_ip(const char* value, size_t size); + ::std::string* mutable_ip(); + ::std::string* release_ip(); + void set_allocated_ip(::std::string* ip); + + // string info = 4; + void clear_info(); + static const int kInfoFieldNumber = 4; + const ::std::string& info() const; + void set_info(const ::std::string& value); + #if LANG_CXX11 + void set_info(::std::string&& value); + #endif + void set_info(const char* value); + void set_info(const char* value, size_t size); + ::std::string* mutable_info(); + ::std::string* release_info(); + void set_allocated_info(::std::string* info); + + // string info2 = 5; + void clear_info2(); + static const int kInfo2FieldNumber = 5; + const ::std::string& info2() const; + void set_info2(const ::std::string& value); + #if LANG_CXX11 + void set_info2(::std::string&& value); + #endif + void set_info2(const char* value); + void set_info2(const char* value, size_t size); + ::std::string* mutable_info2(); + ::std::string* release_info2(); + void set_allocated_info2(::std::string* info2); + + // int64 dateTime = 1; + void clear_datetime(); + static const int kDateTimeFieldNumber = 1; + ::google::protobuf::int64 datetime() const; + void set_datetime(::google::protobuf::int64 value); + + // int64 info3 = 6; + void clear_info3(); + static const int kInfo3FieldNumber = 6; + ::google::protobuf::int64 info3() const; + void set_info3(::google::protobuf::int64 value); + + // @@protoc_insertion_point(class_scope:heartbeat.HeartBeatMessage) + private: + + ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; + ::google::protobuf::internal::ArenaStringPtr hostname_; + ::google::protobuf::internal::ArenaStringPtr ip_; + ::google::protobuf::internal::ArenaStringPtr info_; + ::google::protobuf::internal::ArenaStringPtr info2_; + ::google::protobuf::int64 datetime_; + ::google::protobuf::int64 info3_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + friend struct ::protobuf_heartbeat_2eproto::TableStruct; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// HeartBeatMessage + +// int64 dateTime = 1; +inline void HeartBeatMessage::clear_datetime() { + datetime_ = GOOGLE_LONGLONG(0); +} +inline ::google::protobuf::int64 HeartBeatMessage::datetime() const { + // @@protoc_insertion_point(field_get:heartbeat.HeartBeatMessage.dateTime) + return datetime_; +} +inline void HeartBeatMessage::set_datetime(::google::protobuf::int64 value) { + + datetime_ = value; + // @@protoc_insertion_point(field_set:heartbeat.HeartBeatMessage.dateTime) +} + +// string hostName = 2; +inline void HeartBeatMessage::clear_hostname() { + hostname_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline const ::std::string& HeartBeatMessage::hostname() const { + // @@protoc_insertion_point(field_get:heartbeat.HeartBeatMessage.hostName) + return hostname_.GetNoArena(); +} +inline void HeartBeatMessage::set_hostname(const ::std::string& value) { + + hostname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:heartbeat.HeartBeatMessage.hostName) +} +#if LANG_CXX11 +inline void HeartBeatMessage::set_hostname(::std::string&& value) { + + hostname_.SetNoArena( + &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + // @@protoc_insertion_point(field_set_rvalue:heartbeat.HeartBeatMessage.hostName) +} +#endif +inline void HeartBeatMessage::set_hostname(const char* value) { + GOOGLE_DCHECK(value != NULL); + + hostname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:heartbeat.HeartBeatMessage.hostName) +} +inline void HeartBeatMessage::set_hostname(const char* value, size_t size) { + + hostname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:heartbeat.HeartBeatMessage.hostName) +} +inline ::std::string* HeartBeatMessage::mutable_hostname() { + + // @@protoc_insertion_point(field_mutable:heartbeat.HeartBeatMessage.hostName) + return hostname_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline ::std::string* HeartBeatMessage::release_hostname() { + // @@protoc_insertion_point(field_release:heartbeat.HeartBeatMessage.hostName) + + return hostname_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void HeartBeatMessage::set_allocated_hostname(::std::string* hostname) { + if (hostname != NULL) { + + } else { + + } + hostname_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), hostname); + // @@protoc_insertion_point(field_set_allocated:heartbeat.HeartBeatMessage.hostName) +} + +// string ip = 3; +inline void HeartBeatMessage::clear_ip() { + ip_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline const ::std::string& HeartBeatMessage::ip() const { + // @@protoc_insertion_point(field_get:heartbeat.HeartBeatMessage.ip) + return ip_.GetNoArena(); +} +inline void HeartBeatMessage::set_ip(const ::std::string& value) { + + ip_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:heartbeat.HeartBeatMessage.ip) +} +#if LANG_CXX11 +inline void HeartBeatMessage::set_ip(::std::string&& value) { + + ip_.SetNoArena( + &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + // @@protoc_insertion_point(field_set_rvalue:heartbeat.HeartBeatMessage.ip) +} +#endif +inline void HeartBeatMessage::set_ip(const char* value) { + GOOGLE_DCHECK(value != NULL); + + ip_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:heartbeat.HeartBeatMessage.ip) +} +inline void HeartBeatMessage::set_ip(const char* value, size_t size) { + + ip_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:heartbeat.HeartBeatMessage.ip) +} +inline ::std::string* HeartBeatMessage::mutable_ip() { + + // @@protoc_insertion_point(field_mutable:heartbeat.HeartBeatMessage.ip) + return ip_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline ::std::string* HeartBeatMessage::release_ip() { + // @@protoc_insertion_point(field_release:heartbeat.HeartBeatMessage.ip) + + return ip_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void HeartBeatMessage::set_allocated_ip(::std::string* ip) { + if (ip != NULL) { + + } else { + + } + ip_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ip); + // @@protoc_insertion_point(field_set_allocated:heartbeat.HeartBeatMessage.ip) +} + +// string info = 4; +inline void HeartBeatMessage::clear_info() { + info_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline const ::std::string& HeartBeatMessage::info() const { + // @@protoc_insertion_point(field_get:heartbeat.HeartBeatMessage.info) + return info_.GetNoArena(); +} +inline void HeartBeatMessage::set_info(const ::std::string& value) { + + info_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:heartbeat.HeartBeatMessage.info) +} +#if LANG_CXX11 +inline void HeartBeatMessage::set_info(::std::string&& value) { + + info_.SetNoArena( + &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + // @@protoc_insertion_point(field_set_rvalue:heartbeat.HeartBeatMessage.info) +} +#endif +inline void HeartBeatMessage::set_info(const char* value) { + GOOGLE_DCHECK(value != NULL); + + info_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:heartbeat.HeartBeatMessage.info) +} +inline void HeartBeatMessage::set_info(const char* value, size_t size) { + + info_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:heartbeat.HeartBeatMessage.info) +} +inline ::std::string* HeartBeatMessage::mutable_info() { + + // @@protoc_insertion_point(field_mutable:heartbeat.HeartBeatMessage.info) + return info_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline ::std::string* HeartBeatMessage::release_info() { + // @@protoc_insertion_point(field_release:heartbeat.HeartBeatMessage.info) + + return info_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void HeartBeatMessage::set_allocated_info(::std::string* info) { + if (info != NULL) { + + } else { + + } + info_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), info); + // @@protoc_insertion_point(field_set_allocated:heartbeat.HeartBeatMessage.info) +} + +// string info2 = 5; +inline void HeartBeatMessage::clear_info2() { + info2_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline const ::std::string& HeartBeatMessage::info2() const { + // @@protoc_insertion_point(field_get:heartbeat.HeartBeatMessage.info2) + return info2_.GetNoArena(); +} +inline void HeartBeatMessage::set_info2(const ::std::string& value) { + + info2_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:heartbeat.HeartBeatMessage.info2) +} +#if LANG_CXX11 +inline void HeartBeatMessage::set_info2(::std::string&& value) { + + info2_.SetNoArena( + &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + // @@protoc_insertion_point(field_set_rvalue:heartbeat.HeartBeatMessage.info2) +} +#endif +inline void HeartBeatMessage::set_info2(const char* value) { + GOOGLE_DCHECK(value != NULL); + + info2_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:heartbeat.HeartBeatMessage.info2) +} +inline void HeartBeatMessage::set_info2(const char* value, size_t size) { + + info2_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:heartbeat.HeartBeatMessage.info2) +} +inline ::std::string* HeartBeatMessage::mutable_info2() { + + // @@protoc_insertion_point(field_mutable:heartbeat.HeartBeatMessage.info2) + return info2_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline ::std::string* HeartBeatMessage::release_info2() { + // @@protoc_insertion_point(field_release:heartbeat.HeartBeatMessage.info2) + + return info2_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void HeartBeatMessage::set_allocated_info2(::std::string* info2) { + if (info2 != NULL) { + + } else { + + } + info2_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), info2); + // @@protoc_insertion_point(field_set_allocated:heartbeat.HeartBeatMessage.info2) +} + +// int64 info3 = 6; +inline void HeartBeatMessage::clear_info3() { + info3_ = GOOGLE_LONGLONG(0); +} +inline ::google::protobuf::int64 HeartBeatMessage::info3() const { + // @@protoc_insertion_point(field_get:heartbeat.HeartBeatMessage.info3) + return info3_; +} +inline void HeartBeatMessage::set_info3(::google::protobuf::int64 value) { + + info3_ = value; + // @@protoc_insertion_point(field_set:heartbeat.HeartBeatMessage.info3) +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) + +} // namespace heartbeat + +// @@protoc_insertion_point(global_scope) + +#endif // PROTOBUF_INCLUDED_heartbeat_2eproto diff --git a/example_code/pb_demo/heartbeat.proto b/example_code/pb_demo/heartbeat.proto new file mode 100755 index 0000000..1b91f97 --- /dev/null +++ b/example_code/pb_demo/heartbeat.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; +package heartbeat; + +message HeartBeatMessage{ + int64 dateTime = 1; + string hostName = 2; + string ip = 3; + string info = 4; + string info2 = 5; + int64 info3 = 6; +} \ No newline at end of file diff --git a/example_code/pb_demo/protoc-gen/helloworld/build.sh b/example_code/pb_demo/protoc-gen/helloworld/build.sh new file mode 100755 index 0000000..853cb51 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/helloworld/build.sh @@ -0,0 +1,11 @@ +# init go mod +go mod init protoc-gen-helloworld + +# 查看结果 +# ls $GOPATH/bin + +# build +# go install . + +# run +protoc --helloworld_out=./out demo.proto \ No newline at end of file diff --git a/example_code/pb_demo/protoc-gen/helloworld/demo.proto b/example_code/pb_demo/protoc-gen/helloworld/demo.proto new file mode 100755 index 0000000..ff1adbf --- /dev/null +++ b/example_code/pb_demo/protoc-gen/helloworld/demo.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; +option go_package = ".;protocol"; + +message UserMsg +{ + uint32 id = 1; + uint32 age = 2; + uint32 passwd = 3; +} \ No newline at end of file diff --git a/example_code/pb_demo/protoc-gen/helloworld/go.mod b/example_code/pb_demo/protoc-gen/helloworld/go.mod new file mode 100755 index 0000000..08255e9 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/helloworld/go.mod @@ -0,0 +1,5 @@ +module protoc-gen-helloworld + +go 1.17 + +require google.golang.org/protobuf v1.28.0 // indirect diff --git a/example_code/pb_demo/protoc-gen/helloworld/go.sum b/example_code/pb_demo/protoc-gen/helloworld/go.sum new file mode 100755 index 0000000..e38d2e3 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/helloworld/go.sum @@ -0,0 +1,6 @@ +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= diff --git a/example_code/pb_demo/protoc-gen/helloworld/main.go b/example_code/pb_demo/protoc-gen/helloworld/main.go new file mode 100755 index 0000000..40cab29 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/helloworld/main.go @@ -0,0 +1,47 @@ +package main + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + + "google.golang.org/protobuf/compiler/protogen" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/pluginpb" +) + +func main() { + // 1. 读取标准输入,接收proto 解析的文件内容,并解析成结构体 + input, _ := ioutil.ReadAll(os.Stdin) + var req pluginpb.CodeGeneratorRequest + proto.Unmarshal(input, &req) + + // 2. 生成插件 + opts := protogen.Options{} + plugin, err := opts.New(&req) + if err != nil { + panic(err) + } + + // 3. 写入内容 + var buf bytes.Buffer + pkg := fmt.Sprintf("hello world") + buf.Write([]byte(pkg)) + + // 指定输入文件名 + filename := "hello.txt" + file := plugin.NewGeneratedFile(filename, ".") + // 将内容写入插件文件内容 + file.Write(buf.Bytes()) + + // 4. 生成响应 + stdout := plugin.Response() + out, err := proto.Marshal(stdout) + if err != nil { + panic(err) + } + + // 5. 将响应写回标准输入, protoc会读取这个内容 + fmt.Fprintf(os.Stdout, string(out)) +} diff --git a/example_code/pb_demo/protoc-gen/helloworld/out/hello.txt b/example_code/pb_demo/protoc-gen/helloworld/out/hello.txt new file mode 100755 index 0000000..95d09f2 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/helloworld/out/hello.txt @@ -0,0 +1 @@ +hello world \ No newline at end of file diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/Makefile b/example_code/pb_demo/protoc-gen/protoc-gen-pod/Makefile new file mode 100755 index 0000000..6b21e6f --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/Makefile @@ -0,0 +1,22 @@ +.PHONY: gen gen_cpp gen_go is clean + +gen_go: + protoc --go_out=./out ./proto/*.proto + +gen_cpp: + protoc --cpp_out=./out ./proto/*.proto + +is: + go install . + +gen: + protoc --demo_out=./out ./proto/*.proto + +clean: + rm out/custom/*.cpp out/custom/*.h + +all: + make gen_go + make gen_protoc + make gen_cpp + make gen diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/build.sh b/example_code/pb_demo/protoc-gen/protoc-gen-pod/build.sh new file mode 100755 index 0000000..2fca8ea --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/build.sh @@ -0,0 +1,6 @@ +#!/bin/bash +go mod init protoc-gen-demo + +# ls $GOPATH/bin + +# go install github.com/golang/protobuf/protoc-gen-go \ No newline at end of file diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/go.mod b/example_code/pb_demo/protoc-gen/protoc-gen-pod/go.mod new file mode 100755 index 0000000..24f4668 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/go.mod @@ -0,0 +1,8 @@ +module protoc-gen-demo + +go 1.17 + +require ( + github.com/golang/protobuf v1.5.2 // indirect + google.golang.org/protobuf v1.28.0 // indirect +) diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/go.sum b/example_code/pb_demo/protoc-gen/protoc-gen-pod/go.sum new file mode 100755 index 0000000..e648ad2 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/go.sum @@ -0,0 +1,9 @@ +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/main.go b/example_code/pb_demo/protoc-gen/protoc-gen-pod/main.go new file mode 100755 index 0000000..2fe009f --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/main.go @@ -0,0 +1,304 @@ +package main + +import ( + "bytes" + "fmt" + "io/ioutil" + "os" + "strings" + + "protoc-gen-demo/out/custom" + + "google.golang.org/protobuf/compiler/protogen" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + "google.golang.org/protobuf/types/descriptorpb" + "google.golang.org/protobuf/types/pluginpb" +) + +// https://godocs.io/google.golang.org/protobuf/compiler/protogen +func main() { + //1.读取标准输入,接收proto 解析的文件内容,并解析成结构体 + input, _ := ioutil.ReadAll(os.Stdin) + var req pluginpb.CodeGeneratorRequest + proto.Unmarshal(input, &req) + + //2.生成插件 + opts := protogen.Options{} + plugin, err := opts.New(&req) + if err != nil { + panic(err) + } + + pb_gen(plugin) + + // 生成响应 + stdout := plugin.Response() + out, err := proto.Marshal(stdout) + if err != nil { + panic(err) + } + // 将响应写回标准输入, protoc会读取这个内容 + fmt.Fprintf(os.Stdout, string(out)) +} + +func pb_gen(plugin *protogen.Plugin) { + pb_gen_hpp(plugin) + pb_gen_cpp(plugin) +} + +func pb_gen_hpp(plugin *protogen.Plugin) { + // 3.在插件plugin.Files就是demo.proto 的内容了,是一个切片,每个切片元素代表一个文件内容 + // 我们只需要遍历这个文件就能获取到文件的信息了 + // 生成hpp文件 + for _, file := range plugin.Files { + //创建一个buf 写入生成的文件内容 + + var buf bytes.Buffer + // 写入go 文件的package名 + content := "" + content += pb_gen_hpp_header(file) + + //遍历消息,这个内容就是protobuf的每个消息 + for _, msg := range file.Messages { + content += fmt.Sprintf("struct POD%s // pb name %s \n", msg.GoIdent.GoName, msg.GoIdent.GoName) + content += fmt.Sprintf("{\n") + //遍历消息的每个字段 + for _, field := range msg.Fields { + custom_opt := "" + if field_has_optcount(field) { + value := field_get_optcount(field) + if value != "" { + custom_opt += fmt.Sprintf("[%s]", value) + } + } + + // https://godocs.io/google.golang.org/protobuf/reflect/protoreflect#Kind + // https://pkg.go.dev/github.com/golang/protobuf/v2/reflect/protoreflect#Descriptor + if field.Desc.Kind() == protoreflect.EnumKind { + content += fmt.Sprintf(" %s::%s %s; // %s \n", msg.GoIdent.GoName, field.Desc.Enum().Name(), field.Desc.TextName(), field.Desc.Enum().Values()) + } else if field.Desc.Kind() == protoreflect.MessageKind { + content += fmt.Sprintf(" POD%s %s%s;\n", field.Desc.Message().FullName(), field.Desc.TextName(), custom_opt) + } else { + content += fmt.Sprintf(" %s %s%s; // %s = %d \n", pb_to_cpp_type(field.Desc.Kind()), field.Desc.TextName(), custom_opt, field.Desc.TextName(), field.Desc.Number()) + } + } + + // method + content += fmt.Sprintf("\n // method \n") + content += fmt.Sprintf(" void clear();\n") + content += fmt.Sprintf(" int pb2pod(const %s & pb);\n", msg.GoIdent.GoName) + content += fmt.Sprintf(" int pod2pb(%s * pb);\n", msg.GoIdent.GoName) + content += fmt.Sprintf("};\n\n") + } + + content += fmt.Sprintf("#endif\n") + buf.Write([]byte(content)) + //指定输入文件名,输出文件名为demo.foo.go + filename := file.GeneratedFilenamePrefix + ".h" + file := plugin.NewGeneratedFile(filename, ".") + // 将内容写入插件文件内容 + file.Write(buf.Bytes()) + } +} + +func pb_gen_cpp(plugin *protogen.Plugin) { + // 生成cpp文件 + for _, file := range plugin.Files { + //创建一个buf 写入生成的文件内容 + var buf bytes.Buffer + content := "" + content += pb_gen_cpp_header(file) + + //遍历消息,这个内容就是protobuf的每个消息 + for _, msg := range file.Messages { + // method + content += fmt.Sprintf("\n// method \n") + + // clear() + content += fmt.Sprintf("void POD%s::clear()\n", msg.GoIdent.GoName) + content += fmt.Sprintf("{\n") + for _, field := range msg.Fields { + opt_str := "" + opt_noindex_str := "" + if field_has_optcount(field) { + field_cnt := field_get_optcount(field) + content += fmt.Sprintf(" for (int i = 0; i < %s; i++) {\n", field_cnt) + opt_str += "[i]" + opt_noindex_str += "i" + } + + if field.Desc.Kind() == protoreflect.EnumKind { + if field.Desc.Enum().Values().Len() > 0 { + content += fmt.Sprintf(" %s = %s::%s; \n", field.Desc.TextName(), msg.GoIdent.GoName, field.Desc.Enum().Values().Get(0).Name()) + } + } else if field.Desc.Kind() == protoreflect.MessageKind { + content += fmt.Sprintf(" %s%s.clear(); \n", field.Desc.TextName(), opt_str) + } else { + content += fmt.Sprintf(" %s%s = 0; \n", field.Desc.TextName(), opt_str) + } + + if opt_str != "" { + content += fmt.Sprintf(" }\n") + } + } + content += fmt.Sprintf("}\n") + content += fmt.Sprintf("\n") + + // pb2pod + content += fmt.Sprintf("int POD%s::pb2pod(const %s & pb)\n", msg.GoIdent.GoName, msg.GoIdent.GoName) + content += fmt.Sprintf("{\n") + + for _, field := range msg.Fields { + opt_str := "" + opt_noindex_str := "" + if field_has_optcount(field) { + field_cnt := field_get_optcount(field) + content += fmt.Sprintf(" for (int i = 0; i < %s; i++) {\n", field_cnt) + opt_str += "[i]" + opt_noindex_str += "i" + } + + if field.Desc.Kind() == protoreflect.MessageKind { + content += fmt.Sprintf(" %s%s.pb2pod(pb.%s(%s)); \n", field.Desc.TextName(), opt_str, field.Desc.TextName(), opt_noindex_str) + } else { + content += fmt.Sprintf(" %s%s = pb.%s(%s); \n", field.Desc.TextName(), opt_str, field.Desc.TextName(), opt_noindex_str) + } + + if opt_str != "" { + content += fmt.Sprintf(" }\n") + } + } + content += fmt.Sprintf(" return 0;\n") + content += fmt.Sprintf("}\n") + content += fmt.Sprintf("\n") + + // pod2pb + content += fmt.Sprintf("int POD%s::pod2pb(%s * pb)\n", msg.GoIdent.GoName, msg.GoIdent.GoName) + content += fmt.Sprintf("{\n") + for _, field := range msg.Fields { + + opt_str := "" + if field_has_optcount(field) { + field_cnt := field_get_optcount(field) + content += fmt.Sprintf(" for (int i = 0; i < %s; i++) {\n", field_cnt) + opt_str += "[i]" + } + + if field.Desc.Kind() == protoreflect.MessageKind { + if opt_str != "" { + content += fmt.Sprintf(" %s%s.pod2pb(pb->add_%s()); \n", field.Desc.TextName(), opt_str, field.Desc.TextName()) + } else { + content += fmt.Sprintf(" %s.pod2pb(pb->mutable_%s()); \n", field.Desc.TextName(), field.Desc.TextName()) + } + } else { + if opt_str != "" { + content += fmt.Sprintf(" pb->add_%s(%s%s); \n", field.Desc.TextName(), field.Desc.TextName(), opt_str) + } else { + content += fmt.Sprintf(" pb->set_%s(%s); \n", field.Desc.TextName(), field.Desc.TextName()) + } + } + + if opt_str != "" { + content += fmt.Sprintf(" }\n") + } + } + content += fmt.Sprintf(" return 0;\n") + content += fmt.Sprintf("}\n") + content += fmt.Sprintf("\n") + } + buf.Write([]byte(content)) + //指定输入文件名,输出文件名为demo.foo.go + filename := file.GeneratedFilenamePrefix + ".cpp" + file := plugin.NewGeneratedFile(filename, ".") + // 将内容写入插件文件内容 + file.Write(buf.Bytes()) + } +} + +func pb_gen_hpp_header(file *protogen.File) string { + content := "" + file_name_str := strings.Split(file.GeneratedFilenamePrefix, "/") + content += fmt.Sprintf("#ifndef __%s_H_\n", strings.ToUpper(file_name_str[len(file_name_str)-1])) + content += fmt.Sprintf("#define __%s_H_\n\n", strings.ToUpper(file_name_str[len(file_name_str)-1])) + + content += fmt.Sprintf("#include \n") + content += fmt.Sprintf("#include \"%s.pb.h\" \n", file_name_str[len(file_name_str)-1]) + return content +} + +func pb_gen_cpp_header(file *protogen.File) string { + content := "" + file_name_str := strings.Split(file.GeneratedFilenamePrefix, "/") + content += fmt.Sprintf("#include \"%s.h\" \n", file_name_str[len(file_name_str)-1]) + content += fmt.Sprintf("#include \"%s.pb.h\" \n", file_name_str[len(file_name_str)-1]) + return content +} + +func pb_to_cpp_type(pb_type protoreflect.Kind) string { + switch pb_type { + case protoreflect.BoolKind: + return "bool" + case protoreflect.Int32Kind: + case protoreflect.Sint32Kind: + return "int32_t" + + case protoreflect.Uint32Kind: + return "uint32_t" + + case protoreflect.Sint64Kind: + case protoreflect.Int64Kind: + return "int64_t" + case protoreflect.Uint64Kind: + return "uint64_t" + case protoreflect.MessageKind: + return "Message" + default: + return "unkown_type" + } + return "unkown_type" +} + +// https://pkg.go.dev/google.golang.org/protobuf/compiler/protogen#Plugin +// https://stackoverflow.com/questions/69311708/how-to-retrieve-fieldoption-value +// https://pkg.go.dev/google.golang.org/protobuf/proto#GetExtension +func GetOptionMaxCount(field *descriptorpb.FieldOptions) string { + if field == nil { + return "" + } + v := proto.GetExtension(field, custom.E_OptCount) + str := fmt.Sprintf("%v", v) + return str +} + +func field_has_optcount(field *protogen.Field) bool { + op, ok := field.Desc.Options().(*descriptorpb.FieldOptions) + if ok == false { + return false + } + + if op == nil { + return false + } + + v := proto.GetExtension(op, custom.E_OptCount) + str := fmt.Sprintf("%v", v) + if str == "" { + return false + } + return true +} + +func field_get_optcount(field *protogen.Field) string { + op, ok := field.Desc.Options().(*descriptorpb.FieldOptions) + if ok == false { + return "" + } + + if op == nil { + return "" + } + v := proto.GetExtension(op, custom.E_OptCount) + str := fmt.Sprintf("%v", v) + return str +} diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/build.sh b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/build.sh new file mode 100755 index 0000000..328c84c --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/build.sh @@ -0,0 +1,5 @@ +#!/bin/bash +rm test_main +g++ *.cpp proto/*.cc -o test_main -L/usr/local/lib -lprotobuf -lpthread -I. -Iproto + +# g++ demo.cpp heartbeat.cpp machine.cpp test_main.cpp proto/custom_opt.pb.cc proto/demo.pb.cc proto/heartbeat.pb.cc proto/machine.pb.cc -o test_main -L/usr/local/lib -lprotobuf -lpthread -I. -Iproto \ No newline at end of file diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/custom/custom_opt.cpp b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/custom/custom_opt.cpp new file mode 100755 index 0000000..7e07f95 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/custom/custom_opt.cpp @@ -0,0 +1,2 @@ +#include "custom_opt.h" +#include "custom_opt.pb.h" diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/custom/custom_opt.h b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/custom/custom_opt.h new file mode 100755 index 0000000..e467813 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/custom/custom_opt.h @@ -0,0 +1,6 @@ +#ifndef __CUSTOM_OPT_H_ +#define __CUSTOM_OPT_H_ + +#include +#include "custom_opt.pb.h" +#endif diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/custom/custom_opt.pb.go b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/custom/custom_opt.pb.go new file mode 100755 index 0000000..5a46bc6 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/custom/custom_opt.pb.go @@ -0,0 +1,92 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.0 +// protoc v3.19.1 +// source: proto/custom_opt.proto + +package custom + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + descriptorpb "google.golang.org/protobuf/types/descriptorpb" + reflect "reflect" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +var file_proto_custom_opt_proto_extTypes = []protoimpl.ExtensionInfo{ + { + ExtendedType: (*descriptorpb.FieldOptions)(nil), + ExtensionType: (*uint32)(nil), + Field: 50000, + Name: "custom.opt_count", + Tag: "varint,50000,opt,name=opt_count", + Filename: "proto/custom_opt.proto", + }, +} + +// Extension fields to descriptorpb.FieldOptions. +var ( + // max count for repeated + // + // optional uint32 opt_count = 50000; + E_OptCount = &file_proto_custom_opt_proto_extTypes[0] +) + +var File_proto_custom_opt_proto protoreflect.FileDescriptor + +var file_proto_custom_opt_proto_rawDesc = []byte{ + 0x0a, 0x16, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, + 0x70, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, + 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x3a, 0x3f, 0x0a, 0x09, 0x6f, 0x70, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, + 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xd0, + 0x86, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6f, 0x70, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x88, 0x01, 0x01, 0x42, 0x09, 0x5a, 0x07, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var file_proto_custom_opt_proto_goTypes = []interface{}{ + (*descriptorpb.FieldOptions)(nil), // 0: google.protobuf.FieldOptions +} +var file_proto_custom_opt_proto_depIdxs = []int32{ + 0, // 0: custom.opt_count:extendee -> google.protobuf.FieldOptions + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 0, // [0:1] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_proto_custom_opt_proto_init() } +func file_proto_custom_opt_proto_init() { + if File_proto_custom_opt_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_custom_opt_proto_rawDesc, + NumEnums: 0, + NumMessages: 0, + NumExtensions: 1, + NumServices: 0, + }, + GoTypes: file_proto_custom_opt_proto_goTypes, + DependencyIndexes: file_proto_custom_opt_proto_depIdxs, + ExtensionInfos: file_proto_custom_opt_proto_extTypes, + }.Build() + File_proto_custom_opt_proto = out.File + file_proto_custom_opt_proto_rawDesc = nil + file_proto_custom_opt_proto_goTypes = nil + file_proto_custom_opt_proto_depIdxs = nil +} diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/demo.cpp b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/demo.cpp new file mode 100755 index 0000000..4ab44fb --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/demo.cpp @@ -0,0 +1,61 @@ +#include "demo.h" +#include "demo.pb.h" + +// method +void PODUserMsg::clear() +{ + id = 0; + age = 0; + passwd = 0; +} + +int PODUserMsg::pb2pod(const UserMsg & pb) +{ + id = pb.id(); + age = pb.age(); + passwd = pb.passwd(); + return 0; +} + +int PODUserMsg::pod2pb(UserMsg * pb) +{ + pb->set_id(id); + pb->set_age(age); + pb->set_passwd(passwd); + return 0; +} + + +// method +void PODFamilyMsg::clear() +{ + for (int i = 0; i < 10; i++) { + familys[i].clear(); + } + for (int i = 0; i < 50; i++) { + rid_arrs[i] = 0; + } +} + +int PODFamilyMsg::pb2pod(const FamilyMsg & pb) +{ + for (int i = 0; i < 10; i++) { + familys[i].pb2pod(pb.familys(i)); + } + for (int i = 0; i < 50; i++) { + rid_arrs[i] = pb.rid_arrs(i); + } + return 0; +} + +int PODFamilyMsg::pod2pb(FamilyMsg * pb) +{ + for (int i = 0; i < 10; i++) { + familys[i].pod2pb(pb->add_familys()); + } + for (int i = 0; i < 50; i++) { + pb->add_rid_arrs(rid_arrs[i]); + } + return 0; +} + diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/demo.h b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/demo.h new file mode 100755 index 0000000..afc16e5 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/demo.h @@ -0,0 +1,29 @@ +#ifndef __DEMO_H_ +#define __DEMO_H_ + +#include +#include "demo.pb.h" +struct PODUserMsg // pb name UserMsg +{ + uint32_t id; // id = 1 + uint32_t age; // age = 2 + uint32_t passwd; // passwd = 3 + + // method + void clear(); + int pb2pod(const UserMsg & pb); + int pod2pb(UserMsg * pb); +}; + +struct PODFamilyMsg // pb name FamilyMsg +{ + PODUserMsg familys[10]; + uint32_t rid_arrs[50]; // rid_arrs = 2 + + // method + void clear(); + int pb2pod(const FamilyMsg & pb); + int pod2pb(FamilyMsg * pb); +}; + +#endif diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/demo.pb.go b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/demo.pb.go new file mode 100755 index 0000000..3015cd1 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/demo.pb.go @@ -0,0 +1,236 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.0 +// protoc v3.19.1 +// source: proto/demo.proto + +package protocol + +import ( + _ "/custom" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type UserMsg struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id uint32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Age uint32 `protobuf:"varint,2,opt,name=age,proto3" json:"age,omitempty"` + Passwd uint32 `protobuf:"varint,3,opt,name=passwd,proto3" json:"passwd,omitempty"` +} + +func (x *UserMsg) Reset() { + *x = UserMsg{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_demo_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UserMsg) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UserMsg) ProtoMessage() {} + +func (x *UserMsg) ProtoReflect() protoreflect.Message { + mi := &file_proto_demo_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UserMsg.ProtoReflect.Descriptor instead. +func (*UserMsg) Descriptor() ([]byte, []int) { + return file_proto_demo_proto_rawDescGZIP(), []int{0} +} + +func (x *UserMsg) GetId() uint32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *UserMsg) GetAge() uint32 { + if x != nil { + return x.Age + } + return 0 +} + +func (x *UserMsg) GetPasswd() uint32 { + if x != nil { + return x.Passwd + } + return 0 +} + +type FamilyMsg struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Familys []*UserMsg `protobuf:"bytes,1,rep,name=familys,proto3" json:"familys,omitempty"` + RidArrs []uint32 `protobuf:"varint,2,rep,packed,name=rid_arrs,json=ridArrs,proto3" json:"rid_arrs,omitempty"` +} + +func (x *FamilyMsg) Reset() { + *x = FamilyMsg{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_demo_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FamilyMsg) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FamilyMsg) ProtoMessage() {} + +func (x *FamilyMsg) ProtoReflect() protoreflect.Message { + mi := &file_proto_demo_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FamilyMsg.ProtoReflect.Descriptor instead. +func (*FamilyMsg) Descriptor() ([]byte, []int) { + return file_proto_demo_proto_rawDescGZIP(), []int{1} +} + +func (x *FamilyMsg) GetFamilys() []*UserMsg { + if x != nil { + return x.Familys + } + return nil +} + +func (x *FamilyMsg) GetRidArrs() []uint32 { + if x != nil { + return x.RidArrs + } + return nil +} + +var File_proto_demo_proto protoreflect.FileDescriptor + +var file_proto_demo_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x64, 0x65, 0x6d, 0x6f, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x1a, 0x16, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, + 0x5f, 0x6f, 0x70, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x43, 0x0a, 0x07, 0x55, 0x73, + 0x65, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x03, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x73, 0x73, 0x77, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x70, 0x61, 0x73, 0x73, 0x77, 0x64, 0x22, + 0x56, 0x0a, 0x09, 0x46, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x4d, 0x73, 0x67, 0x12, 0x28, 0x0a, 0x07, + 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x08, 0x2e, + 0x55, 0x73, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x42, 0x04, 0x80, 0xb5, 0x18, 0x0a, 0x52, 0x07, 0x66, + 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x73, 0x12, 0x1f, 0x0a, 0x08, 0x72, 0x69, 0x64, 0x5f, 0x61, 0x72, + 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0d, 0x42, 0x04, 0x80, 0xb5, 0x18, 0x32, 0x52, 0x07, + 0x72, 0x69, 0x64, 0x41, 0x72, 0x72, 0x73, 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x3b, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_proto_demo_proto_rawDescOnce sync.Once + file_proto_demo_proto_rawDescData = file_proto_demo_proto_rawDesc +) + +func file_proto_demo_proto_rawDescGZIP() []byte { + file_proto_demo_proto_rawDescOnce.Do(func() { + file_proto_demo_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_demo_proto_rawDescData) + }) + return file_proto_demo_proto_rawDescData +} + +var file_proto_demo_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_proto_demo_proto_goTypes = []interface{}{ + (*UserMsg)(nil), // 0: UserMsg + (*FamilyMsg)(nil), // 1: FamilyMsg +} +var file_proto_demo_proto_depIdxs = []int32{ + 0, // 0: FamilyMsg.familys:type_name -> UserMsg + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_proto_demo_proto_init() } +func file_proto_demo_proto_init() { + if File_proto_demo_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_proto_demo_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UserMsg); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_demo_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*FamilyMsg); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_demo_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_proto_demo_proto_goTypes, + DependencyIndexes: file_proto_demo_proto_depIdxs, + MessageInfos: file_proto_demo_proto_msgTypes, + }.Build() + File_proto_demo_proto = out.File + file_proto_demo_proto_rawDesc = nil + file_proto_demo_proto_goTypes = nil + file_proto_demo_proto_depIdxs = nil +} diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/google.golang.org/protobuf/types/descriptorpb/descriptor.cpp b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/google.golang.org/protobuf/types/descriptorpb/descriptor.cpp new file mode 100755 index 0000000..890776b --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/google.golang.org/protobuf/types/descriptorpb/descriptor.cpp @@ -0,0 +1,665 @@ +#include "descriptor.h" +#include "descriptor.pb.h" + +// method +void PODFileDescriptorSet::clear() +{ + file.clear(); +} + +int PODFileDescriptorSet::pb2pod(const FileDescriptorSet & pb) +{ + file.pb2pod(pb.file()); + return 0; +} + +int PODFileDescriptorSet::pod2pb(FileDescriptorSet * pb) +{ + file.pod2pb(pb->mutable_file()); + return 0; +} + + +// method +void PODFileDescriptorProto::clear() +{ + name = 0; + package = 0; + dependency = 0; + public_dependency = 0; + weak_dependency = 0; + message_type.clear(); + enum_type.clear(); + service.clear(); + extension.clear(); + options.clear(); + source_code_info.clear(); + syntax = 0; +} + +int PODFileDescriptorProto::pb2pod(const FileDescriptorProto & pb) +{ + name = pb.name(); + package = pb.package(); + dependency = pb.dependency(); + public_dependency = pb.public_dependency(); + weak_dependency = pb.weak_dependency(); + message_type.pb2pod(pb.message_type()); + enum_type.pb2pod(pb.enum_type()); + service.pb2pod(pb.service()); + extension.pb2pod(pb.extension()); + options.pb2pod(pb.options()); + source_code_info.pb2pod(pb.source_code_info()); + syntax = pb.syntax(); + return 0; +} + +int PODFileDescriptorProto::pod2pb(FileDescriptorProto * pb) +{ + pb->set_name(name); + pb->set_package(package); + pb->set_dependency(dependency); + pb->set_public_dependency(public_dependency); + pb->set_weak_dependency(weak_dependency); + message_type.pod2pb(pb->mutable_message_type()); + enum_type.pod2pb(pb->mutable_enum_type()); + service.pod2pb(pb->mutable_service()); + extension.pod2pb(pb->mutable_extension()); + options.pod2pb(pb->mutable_options()); + source_code_info.pod2pb(pb->mutable_source_code_info()); + pb->set_syntax(syntax); + return 0; +} + + +// method +void PODDescriptorProto::clear() +{ + name = 0; + field.clear(); + extension.clear(); + nested_type.clear(); + enum_type.clear(); + extension_range.clear(); + oneof_decl.clear(); + options.clear(); + reserved_range.clear(); + reserved_name = 0; +} + +int PODDescriptorProto::pb2pod(const DescriptorProto & pb) +{ + name = pb.name(); + field.pb2pod(pb.field()); + extension.pb2pod(pb.extension()); + nested_type.pb2pod(pb.nested_type()); + enum_type.pb2pod(pb.enum_type()); + extension_range.pb2pod(pb.extension_range()); + oneof_decl.pb2pod(pb.oneof_decl()); + options.pb2pod(pb.options()); + reserved_range.pb2pod(pb.reserved_range()); + reserved_name = pb.reserved_name(); + return 0; +} + +int PODDescriptorProto::pod2pb(DescriptorProto * pb) +{ + pb->set_name(name); + field.pod2pb(pb->mutable_field()); + extension.pod2pb(pb->mutable_extension()); + nested_type.pod2pb(pb->mutable_nested_type()); + enum_type.pod2pb(pb->mutable_enum_type()); + extension_range.pod2pb(pb->mutable_extension_range()); + oneof_decl.pod2pb(pb->mutable_oneof_decl()); + options.pod2pb(pb->mutable_options()); + reserved_range.pod2pb(pb->mutable_reserved_range()); + pb->set_reserved_name(reserved_name); + return 0; +} + + +// method +void PODExtensionRangeOptions::clear() +{ + uninterpreted_option.clear(); +} + +int PODExtensionRangeOptions::pb2pod(const ExtensionRangeOptions & pb) +{ + uninterpreted_option.pb2pod(pb.uninterpreted_option()); + return 0; +} + +int PODExtensionRangeOptions::pod2pb(ExtensionRangeOptions * pb) +{ + uninterpreted_option.pod2pb(pb->mutable_uninterpreted_option()); + return 0; +} + + +// method +void PODFieldDescriptorProto::clear() +{ + name = 0; + number = 0; + label = FieldDescriptorProto::LABEL_OPTIONAL; + type = FieldDescriptorProto::TYPE_DOUBLE; + type_name = 0; + extendee = 0; + default_value = 0; + oneof_index = 0; + json_name = 0; + options.clear(); + proto3_optional = 0; +} + +int PODFieldDescriptorProto::pb2pod(const FieldDescriptorProto & pb) +{ + name = pb.name(); + number = pb.number(); + label = pb.label(); + type = pb.type(); + type_name = pb.type_name(); + extendee = pb.extendee(); + default_value = pb.default_value(); + oneof_index = pb.oneof_index(); + json_name = pb.json_name(); + options.pb2pod(pb.options()); + proto3_optional = pb.proto3_optional(); + return 0; +} + +int PODFieldDescriptorProto::pod2pb(FieldDescriptorProto * pb) +{ + pb->set_name(name); + pb->set_number(number); + pb->set_label(label); + pb->set_type(type); + pb->set_type_name(type_name); + pb->set_extendee(extendee); + pb->set_default_value(default_value); + pb->set_oneof_index(oneof_index); + pb->set_json_name(json_name); + options.pod2pb(pb->mutable_options()); + pb->set_proto3_optional(proto3_optional); + return 0; +} + + +// method +void PODOneofDescriptorProto::clear() +{ + name = 0; + options.clear(); +} + +int PODOneofDescriptorProto::pb2pod(const OneofDescriptorProto & pb) +{ + name = pb.name(); + options.pb2pod(pb.options()); + return 0; +} + +int PODOneofDescriptorProto::pod2pb(OneofDescriptorProto * pb) +{ + pb->set_name(name); + options.pod2pb(pb->mutable_options()); + return 0; +} + + +// method +void PODEnumDescriptorProto::clear() +{ + name = 0; + value.clear(); + options.clear(); + reserved_range.clear(); + reserved_name = 0; +} + +int PODEnumDescriptorProto::pb2pod(const EnumDescriptorProto & pb) +{ + name = pb.name(); + value.pb2pod(pb.value()); + options.pb2pod(pb.options()); + reserved_range.pb2pod(pb.reserved_range()); + reserved_name = pb.reserved_name(); + return 0; +} + +int PODEnumDescriptorProto::pod2pb(EnumDescriptorProto * pb) +{ + pb->set_name(name); + value.pod2pb(pb->mutable_value()); + options.pod2pb(pb->mutable_options()); + reserved_range.pod2pb(pb->mutable_reserved_range()); + pb->set_reserved_name(reserved_name); + return 0; +} + + +// method +void PODEnumValueDescriptorProto::clear() +{ + name = 0; + number = 0; + options.clear(); +} + +int PODEnumValueDescriptorProto::pb2pod(const EnumValueDescriptorProto & pb) +{ + name = pb.name(); + number = pb.number(); + options.pb2pod(pb.options()); + return 0; +} + +int PODEnumValueDescriptorProto::pod2pb(EnumValueDescriptorProto * pb) +{ + pb->set_name(name); + pb->set_number(number); + options.pod2pb(pb->mutable_options()); + return 0; +} + + +// method +void PODServiceDescriptorProto::clear() +{ + name = 0; + method.clear(); + options.clear(); +} + +int PODServiceDescriptorProto::pb2pod(const ServiceDescriptorProto & pb) +{ + name = pb.name(); + method.pb2pod(pb.method()); + options.pb2pod(pb.options()); + return 0; +} + +int PODServiceDescriptorProto::pod2pb(ServiceDescriptorProto * pb) +{ + pb->set_name(name); + method.pod2pb(pb->mutable_method()); + options.pod2pb(pb->mutable_options()); + return 0; +} + + +// method +void PODMethodDescriptorProto::clear() +{ + name = 0; + input_type = 0; + output_type = 0; + options.clear(); + client_streaming = 0; + server_streaming = 0; +} + +int PODMethodDescriptorProto::pb2pod(const MethodDescriptorProto & pb) +{ + name = pb.name(); + input_type = pb.input_type(); + output_type = pb.output_type(); + options.pb2pod(pb.options()); + client_streaming = pb.client_streaming(); + server_streaming = pb.server_streaming(); + return 0; +} + +int PODMethodDescriptorProto::pod2pb(MethodDescriptorProto * pb) +{ + pb->set_name(name); + pb->set_input_type(input_type); + pb->set_output_type(output_type); + options.pod2pb(pb->mutable_options()); + pb->set_client_streaming(client_streaming); + pb->set_server_streaming(server_streaming); + return 0; +} + + +// method +void PODFileOptions::clear() +{ + java_package = 0; + java_outer_classname = 0; + java_multiple_files = 0; + for (int i = 0; i < 0; i++) { + java_generate_equals_and_hash[i] = 0; + } + java_string_check_utf8 = 0; + optimize_for = FileOptions::SPEED; + go_package = 0; + cc_generic_services = 0; + java_generic_services = 0; + py_generic_services = 0; + php_generic_services = 0; + deprecated = 0; + cc_enable_arenas = 0; + objc_class_prefix = 0; + csharp_namespace = 0; + swift_prefix = 0; + php_class_prefix = 0; + php_namespace = 0; + php_metadata_namespace = 0; + ruby_package = 0; + uninterpreted_option.clear(); +} + +int PODFileOptions::pb2pod(const FileOptions & pb) +{ + java_package = pb.java_package(); + java_outer_classname = pb.java_outer_classname(); + java_multiple_files = pb.java_multiple_files(); + for (int i = 0; i < 0; i++) { + java_generate_equals_and_hash[i] = pb.java_generate_equals_and_hash(i); + } + java_string_check_utf8 = pb.java_string_check_utf8(); + optimize_for = pb.optimize_for(); + go_package = pb.go_package(); + cc_generic_services = pb.cc_generic_services(); + java_generic_services = pb.java_generic_services(); + py_generic_services = pb.py_generic_services(); + php_generic_services = pb.php_generic_services(); + deprecated = pb.deprecated(); + cc_enable_arenas = pb.cc_enable_arenas(); + objc_class_prefix = pb.objc_class_prefix(); + csharp_namespace = pb.csharp_namespace(); + swift_prefix = pb.swift_prefix(); + php_class_prefix = pb.php_class_prefix(); + php_namespace = pb.php_namespace(); + php_metadata_namespace = pb.php_metadata_namespace(); + ruby_package = pb.ruby_package(); + uninterpreted_option.pb2pod(pb.uninterpreted_option()); + return 0; +} + +int PODFileOptions::pod2pb(FileOptions * pb) +{ + pb->set_java_package(java_package); + pb->set_java_outer_classname(java_outer_classname); + pb->set_java_multiple_files(java_multiple_files); + for (int i = 0; i < 0; i++) { + pb->add_java_generate_equals_and_hash(java_generate_equals_and_hash[i]); + } + pb->set_java_string_check_utf8(java_string_check_utf8); + pb->set_optimize_for(optimize_for); + pb->set_go_package(go_package); + pb->set_cc_generic_services(cc_generic_services); + pb->set_java_generic_services(java_generic_services); + pb->set_py_generic_services(py_generic_services); + pb->set_php_generic_services(php_generic_services); + pb->set_deprecated(deprecated); + pb->set_cc_enable_arenas(cc_enable_arenas); + pb->set_objc_class_prefix(objc_class_prefix); + pb->set_csharp_namespace(csharp_namespace); + pb->set_swift_prefix(swift_prefix); + pb->set_php_class_prefix(php_class_prefix); + pb->set_php_namespace(php_namespace); + pb->set_php_metadata_namespace(php_metadata_namespace); + pb->set_ruby_package(ruby_package); + uninterpreted_option.pod2pb(pb->mutable_uninterpreted_option()); + return 0; +} + + +// method +void PODMessageOptions::clear() +{ + message_set_wire_format = 0; + no_standard_descriptor_accessor = 0; + deprecated = 0; + map_entry = 0; + uninterpreted_option.clear(); +} + +int PODMessageOptions::pb2pod(const MessageOptions & pb) +{ + message_set_wire_format = pb.message_set_wire_format(); + no_standard_descriptor_accessor = pb.no_standard_descriptor_accessor(); + deprecated = pb.deprecated(); + map_entry = pb.map_entry(); + uninterpreted_option.pb2pod(pb.uninterpreted_option()); + return 0; +} + +int PODMessageOptions::pod2pb(MessageOptions * pb) +{ + pb->set_message_set_wire_format(message_set_wire_format); + pb->set_no_standard_descriptor_accessor(no_standard_descriptor_accessor); + pb->set_deprecated(deprecated); + pb->set_map_entry(map_entry); + uninterpreted_option.pod2pb(pb->mutable_uninterpreted_option()); + return 0; +} + + +// method +void PODFieldOptions::clear() +{ + ctype = FieldOptions::STRING; + packed = 0; + jstype = FieldOptions::JS_NORMAL; + lazy = 0; + deprecated = 0; + weak = 0; + uninterpreted_option.clear(); +} + +int PODFieldOptions::pb2pod(const FieldOptions & pb) +{ + ctype = pb.ctype(); + packed = pb.packed(); + jstype = pb.jstype(); + lazy = pb.lazy(); + deprecated = pb.deprecated(); + weak = pb.weak(); + uninterpreted_option.pb2pod(pb.uninterpreted_option()); + return 0; +} + +int PODFieldOptions::pod2pb(FieldOptions * pb) +{ + pb->set_ctype(ctype); + pb->set_packed(packed); + pb->set_jstype(jstype); + pb->set_lazy(lazy); + pb->set_deprecated(deprecated); + pb->set_weak(weak); + uninterpreted_option.pod2pb(pb->mutable_uninterpreted_option()); + return 0; +} + + +// method +void PODOneofOptions::clear() +{ + uninterpreted_option.clear(); +} + +int PODOneofOptions::pb2pod(const OneofOptions & pb) +{ + uninterpreted_option.pb2pod(pb.uninterpreted_option()); + return 0; +} + +int PODOneofOptions::pod2pb(OneofOptions * pb) +{ + uninterpreted_option.pod2pb(pb->mutable_uninterpreted_option()); + return 0; +} + + +// method +void PODEnumOptions::clear() +{ + allow_alias = 0; + deprecated = 0; + uninterpreted_option.clear(); +} + +int PODEnumOptions::pb2pod(const EnumOptions & pb) +{ + allow_alias = pb.allow_alias(); + deprecated = pb.deprecated(); + uninterpreted_option.pb2pod(pb.uninterpreted_option()); + return 0; +} + +int PODEnumOptions::pod2pb(EnumOptions * pb) +{ + pb->set_allow_alias(allow_alias); + pb->set_deprecated(deprecated); + uninterpreted_option.pod2pb(pb->mutable_uninterpreted_option()); + return 0; +} + + +// method +void PODEnumValueOptions::clear() +{ + deprecated = 0; + uninterpreted_option.clear(); +} + +int PODEnumValueOptions::pb2pod(const EnumValueOptions & pb) +{ + deprecated = pb.deprecated(); + uninterpreted_option.pb2pod(pb.uninterpreted_option()); + return 0; +} + +int PODEnumValueOptions::pod2pb(EnumValueOptions * pb) +{ + pb->set_deprecated(deprecated); + uninterpreted_option.pod2pb(pb->mutable_uninterpreted_option()); + return 0; +} + + +// method +void PODServiceOptions::clear() +{ + deprecated = 0; + uninterpreted_option.clear(); +} + +int PODServiceOptions::pb2pod(const ServiceOptions & pb) +{ + deprecated = pb.deprecated(); + uninterpreted_option.pb2pod(pb.uninterpreted_option()); + return 0; +} + +int PODServiceOptions::pod2pb(ServiceOptions * pb) +{ + pb->set_deprecated(deprecated); + uninterpreted_option.pod2pb(pb->mutable_uninterpreted_option()); + return 0; +} + + +// method +void PODMethodOptions::clear() +{ + deprecated = 0; + idempotency_level = MethodOptions::IDEMPOTENCY_UNKNOWN; + uninterpreted_option.clear(); +} + +int PODMethodOptions::pb2pod(const MethodOptions & pb) +{ + deprecated = pb.deprecated(); + idempotency_level = pb.idempotency_level(); + uninterpreted_option.pb2pod(pb.uninterpreted_option()); + return 0; +} + +int PODMethodOptions::pod2pb(MethodOptions * pb) +{ + pb->set_deprecated(deprecated); + pb->set_idempotency_level(idempotency_level); + uninterpreted_option.pod2pb(pb->mutable_uninterpreted_option()); + return 0; +} + + +// method +void PODUninterpretedOption::clear() +{ + name.clear(); + identifier_value = 0; + positive_int_value = 0; + negative_int_value = 0; + double_value = 0; + string_value = 0; + aggregate_value = 0; +} + +int PODUninterpretedOption::pb2pod(const UninterpretedOption & pb) +{ + name.pb2pod(pb.name()); + identifier_value = pb.identifier_value(); + positive_int_value = pb.positive_int_value(); + negative_int_value = pb.negative_int_value(); + double_value = pb.double_value(); + string_value = pb.string_value(); + aggregate_value = pb.aggregate_value(); + return 0; +} + +int PODUninterpretedOption::pod2pb(UninterpretedOption * pb) +{ + name.pod2pb(pb->mutable_name()); + pb->set_identifier_value(identifier_value); + pb->set_positive_int_value(positive_int_value); + pb->set_negative_int_value(negative_int_value); + pb->set_double_value(double_value); + pb->set_string_value(string_value); + pb->set_aggregate_value(aggregate_value); + return 0; +} + + +// method +void PODSourceCodeInfo::clear() +{ + location.clear(); +} + +int PODSourceCodeInfo::pb2pod(const SourceCodeInfo & pb) +{ + location.pb2pod(pb.location()); + return 0; +} + +int PODSourceCodeInfo::pod2pb(SourceCodeInfo * pb) +{ + location.pod2pb(pb->mutable_location()); + return 0; +} + + +// method +void PODGeneratedCodeInfo::clear() +{ + annotation.clear(); +} + +int PODGeneratedCodeInfo::pb2pod(const GeneratedCodeInfo & pb) +{ + annotation.pb2pod(pb.annotation()); + return 0; +} + +int PODGeneratedCodeInfo::pod2pb(GeneratedCodeInfo * pb) +{ + annotation.pod2pb(pb->mutable_annotation()); + return 0; +} + diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/google.golang.org/protobuf/types/descriptorpb/descriptor.h b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/google.golang.org/protobuf/types/descriptorpb/descriptor.h new file mode 100755 index 0000000..6096144 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/google.golang.org/protobuf/types/descriptorpb/descriptor.h @@ -0,0 +1,302 @@ +#ifndef __DESCRIPTOR_H_ +#define __DESCRIPTOR_H_ + +#include +#include "descriptor.pb.h" +struct PODFileDescriptorSet // pb name FileDescriptorSet +{ + PODgoogle.protobuf.FileDescriptorProto file; + + // method + void clear(); + int pb2pod(const FileDescriptorSet & pb); + int pod2pb(FileDescriptorSet * pb); +}; + +struct PODFileDescriptorProto // pb name FileDescriptorProto +{ + unkown_type name; // name = 1 + unkown_type package; // package = 2 + unkown_type dependency; // dependency = 3 + unkown_type public_dependency; // public_dependency = 10 + unkown_type weak_dependency; // weak_dependency = 11 + PODgoogle.protobuf.DescriptorProto message_type; + PODgoogle.protobuf.EnumDescriptorProto enum_type; + PODgoogle.protobuf.ServiceDescriptorProto service; + PODgoogle.protobuf.FieldDescriptorProto extension; + PODgoogle.protobuf.FileOptions options; + PODgoogle.protobuf.SourceCodeInfo source_code_info; + unkown_type syntax; // syntax = 12 + + // method + void clear(); + int pb2pod(const FileDescriptorProto & pb); + int pod2pb(FileDescriptorProto * pb); +}; + +struct PODDescriptorProto // pb name DescriptorProto +{ + unkown_type name; // name = 1 + PODgoogle.protobuf.FieldDescriptorProto field; + PODgoogle.protobuf.FieldDescriptorProto extension; + PODgoogle.protobuf.DescriptorProto nested_type; + PODgoogle.protobuf.EnumDescriptorProto enum_type; + PODgoogle.protobuf.DescriptorProto.ExtensionRange extension_range; + PODgoogle.protobuf.OneofDescriptorProto oneof_decl; + PODgoogle.protobuf.MessageOptions options; + PODgoogle.protobuf.DescriptorProto.ReservedRange reserved_range; + unkown_type reserved_name; // reserved_name = 10 + + // method + void clear(); + int pb2pod(const DescriptorProto & pb); + int pod2pb(DescriptorProto * pb); +}; + +struct PODExtensionRangeOptions // pb name ExtensionRangeOptions +{ + PODgoogle.protobuf.UninterpretedOption uninterpreted_option; + + // method + void clear(); + int pb2pod(const ExtensionRangeOptions & pb); + int pod2pb(ExtensionRangeOptions * pb); +}; + +struct PODFieldDescriptorProto // pb name FieldDescriptorProto +{ + unkown_type name; // name = 1 + unkown_type number; // number = 3 + FieldDescriptorProto::Label label; // EnumValues{{Name: LABEL_OPTIONAL, Number: 1}, {Name: LABEL_REQUIRED, Number: 2}, {Name: LABEL_REPEATED, Number: 3}} + FieldDescriptorProto::Type type; // EnumValues{{Name: TYPE_DOUBLE, Number: 1}, {Name: TYPE_FLOAT, Number: 2}, {Name: TYPE_INT64, Number: 3}, {Name: TYPE_UINT64, Number: 4}, {Name: TYPE_INT32, Number: 5}, {Name: TYPE_FIXED64, Number: 6}, {Name: TYPE_FIXED32, Number: 7}, {Name: TYPE_BOOL, Number: 8}, {Name: TYPE_STRING, Number: 9}, {Name: TYPE_GROUP, Number: 10}, {Name: TYPE_MESSAGE, Number: 11}, {Name: TYPE_BYTES, Number: 12}, {Name: TYPE_UINT32, Number: 13}, {Name: TYPE_ENUM, Number: 14}, {Name: TYPE_SFIXED32, Number: 15}, {Name: TYPE_SFIXED64, Number: 16}, {Name: TYPE_SINT32, Number: 17}, {Name: TYPE_SINT64, Number: 18}} + unkown_type type_name; // type_name = 6 + unkown_type extendee; // extendee = 2 + unkown_type default_value; // default_value = 7 + unkown_type oneof_index; // oneof_index = 9 + unkown_type json_name; // json_name = 10 + PODgoogle.protobuf.FieldOptions options; + bool proto3_optional; // proto3_optional = 17 + + // method + void clear(); + int pb2pod(const FieldDescriptorProto & pb); + int pod2pb(FieldDescriptorProto * pb); +}; + +struct PODOneofDescriptorProto // pb name OneofDescriptorProto +{ + unkown_type name; // name = 1 + PODgoogle.protobuf.OneofOptions options; + + // method + void clear(); + int pb2pod(const OneofDescriptorProto & pb); + int pod2pb(OneofDescriptorProto * pb); +}; + +struct PODEnumDescriptorProto // pb name EnumDescriptorProto +{ + unkown_type name; // name = 1 + PODgoogle.protobuf.EnumValueDescriptorProto value; + PODgoogle.protobuf.EnumOptions options; + PODgoogle.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range; + unkown_type reserved_name; // reserved_name = 5 + + // method + void clear(); + int pb2pod(const EnumDescriptorProto & pb); + int pod2pb(EnumDescriptorProto * pb); +}; + +struct PODEnumValueDescriptorProto // pb name EnumValueDescriptorProto +{ + unkown_type name; // name = 1 + unkown_type number; // number = 2 + PODgoogle.protobuf.EnumValueOptions options; + + // method + void clear(); + int pb2pod(const EnumValueDescriptorProto & pb); + int pod2pb(EnumValueDescriptorProto * pb); +}; + +struct PODServiceDescriptorProto // pb name ServiceDescriptorProto +{ + unkown_type name; // name = 1 + PODgoogle.protobuf.MethodDescriptorProto method; + PODgoogle.protobuf.ServiceOptions options; + + // method + void clear(); + int pb2pod(const ServiceDescriptorProto & pb); + int pod2pb(ServiceDescriptorProto * pb); +}; + +struct PODMethodDescriptorProto // pb name MethodDescriptorProto +{ + unkown_type name; // name = 1 + unkown_type input_type; // input_type = 2 + unkown_type output_type; // output_type = 3 + PODgoogle.protobuf.MethodOptions options; + bool client_streaming; // client_streaming = 5 + bool server_streaming; // server_streaming = 6 + + // method + void clear(); + int pb2pod(const MethodDescriptorProto & pb); + int pod2pb(MethodDescriptorProto * pb); +}; + +struct PODFileOptions // pb name FileOptions +{ + unkown_type java_package; // java_package = 1 + unkown_type java_outer_classname; // java_outer_classname = 8 + bool java_multiple_files; // java_multiple_files = 10 + bool java_generate_equals_and_hash[0]; // java_generate_equals_and_hash = 20 + bool java_string_check_utf8; // java_string_check_utf8 = 27 + FileOptions::OptimizeMode optimize_for; // EnumValues{{Name: SPEED, Number: 1}, {Name: CODE_SIZE, Number: 2}, {Name: LITE_RUNTIME, Number: 3}} + unkown_type go_package; // go_package = 11 + bool cc_generic_services; // cc_generic_services = 16 + bool java_generic_services; // java_generic_services = 17 + bool py_generic_services; // py_generic_services = 18 + bool php_generic_services; // php_generic_services = 42 + bool deprecated; // deprecated = 23 + bool cc_enable_arenas; // cc_enable_arenas = 31 + unkown_type objc_class_prefix; // objc_class_prefix = 36 + unkown_type csharp_namespace; // csharp_namespace = 37 + unkown_type swift_prefix; // swift_prefix = 39 + unkown_type php_class_prefix; // php_class_prefix = 40 + unkown_type php_namespace; // php_namespace = 41 + unkown_type php_metadata_namespace; // php_metadata_namespace = 44 + unkown_type ruby_package; // ruby_package = 45 + PODgoogle.protobuf.UninterpretedOption uninterpreted_option; + + // method + void clear(); + int pb2pod(const FileOptions & pb); + int pod2pb(FileOptions * pb); +}; + +struct PODMessageOptions // pb name MessageOptions +{ + bool message_set_wire_format; // message_set_wire_format = 1 + bool no_standard_descriptor_accessor; // no_standard_descriptor_accessor = 2 + bool deprecated; // deprecated = 3 + bool map_entry; // map_entry = 7 + PODgoogle.protobuf.UninterpretedOption uninterpreted_option; + + // method + void clear(); + int pb2pod(const MessageOptions & pb); + int pod2pb(MessageOptions * pb); +}; + +struct PODFieldOptions // pb name FieldOptions +{ + FieldOptions::CType ctype; // EnumValues{{Name: STRING}, {Name: CORD, Number: 1}, {Name: STRING_PIECE, Number: 2}} + bool packed; // packed = 2 + FieldOptions::JSType jstype; // EnumValues{{Name: JS_NORMAL}, {Name: JS_STRING, Number: 1}, {Name: JS_NUMBER, Number: 2}} + bool lazy; // lazy = 5 + bool deprecated; // deprecated = 3 + bool weak; // weak = 10 + PODgoogle.protobuf.UninterpretedOption uninterpreted_option; + + // method + void clear(); + int pb2pod(const FieldOptions & pb); + int pod2pb(FieldOptions * pb); +}; + +struct PODOneofOptions // pb name OneofOptions +{ + PODgoogle.protobuf.UninterpretedOption uninterpreted_option; + + // method + void clear(); + int pb2pod(const OneofOptions & pb); + int pod2pb(OneofOptions * pb); +}; + +struct PODEnumOptions // pb name EnumOptions +{ + bool allow_alias; // allow_alias = 2 + bool deprecated; // deprecated = 3 + PODgoogle.protobuf.UninterpretedOption uninterpreted_option; + + // method + void clear(); + int pb2pod(const EnumOptions & pb); + int pod2pb(EnumOptions * pb); +}; + +struct PODEnumValueOptions // pb name EnumValueOptions +{ + bool deprecated; // deprecated = 1 + PODgoogle.protobuf.UninterpretedOption uninterpreted_option; + + // method + void clear(); + int pb2pod(const EnumValueOptions & pb); + int pod2pb(EnumValueOptions * pb); +}; + +struct PODServiceOptions // pb name ServiceOptions +{ + bool deprecated; // deprecated = 33 + PODgoogle.protobuf.UninterpretedOption uninterpreted_option; + + // method + void clear(); + int pb2pod(const ServiceOptions & pb); + int pod2pb(ServiceOptions * pb); +}; + +struct PODMethodOptions // pb name MethodOptions +{ + bool deprecated; // deprecated = 33 + MethodOptions::IdempotencyLevel idempotency_level; // EnumValues{{Name: IDEMPOTENCY_UNKNOWN}, {Name: NO_SIDE_EFFECTS, Number: 1}, {Name: IDEMPOTENT, Number: 2}} + PODgoogle.protobuf.UninterpretedOption uninterpreted_option; + + // method + void clear(); + int pb2pod(const MethodOptions & pb); + int pod2pb(MethodOptions * pb); +}; + +struct PODUninterpretedOption // pb name UninterpretedOption +{ + PODgoogle.protobuf.UninterpretedOption.NamePart name; + unkown_type identifier_value; // identifier_value = 3 + uint64_t positive_int_value; // positive_int_value = 4 + int64_t negative_int_value; // negative_int_value = 5 + unkown_type double_value; // double_value = 6 + unkown_type string_value; // string_value = 7 + unkown_type aggregate_value; // aggregate_value = 8 + + // method + void clear(); + int pb2pod(const UninterpretedOption & pb); + int pod2pb(UninterpretedOption * pb); +}; + +struct PODSourceCodeInfo // pb name SourceCodeInfo +{ + PODgoogle.protobuf.SourceCodeInfo.Location location; + + // method + void clear(); + int pb2pod(const SourceCodeInfo & pb); + int pod2pb(SourceCodeInfo * pb); +}; + +struct PODGeneratedCodeInfo // pb name GeneratedCodeInfo +{ + PODgoogle.protobuf.GeneratedCodeInfo.Annotation annotation; + + // method + void clear(); + int pb2pod(const GeneratedCodeInfo & pb); + int pod2pb(GeneratedCodeInfo * pb); +}; + +#endif diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/heartbeat.cpp b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/heartbeat.cpp new file mode 100755 index 0000000..ccf8c40 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/heartbeat.cpp @@ -0,0 +1,52 @@ +#include "heartbeat.h" +#include "heartbeat.pb.h" + +// method +void PODHeartBeatReqMessage::clear() +{ + trace_id = 0; + ip = 0; + time = 0; + type = HeartBeatReqMessage::E_PC; +} + +int PODHeartBeatReqMessage::pb2pod(const HeartBeatReqMessage & pb) +{ + trace_id = pb.trace_id(); + ip = pb.ip(); + time = pb.time(); + type = pb.type(); + return 0; +} + +int PODHeartBeatReqMessage::pod2pb(HeartBeatReqMessage * pb) +{ + pb->set_trace_id(trace_id); + pb->set_ip(ip); + pb->set_time(time); + pb->set_type(type); + return 0; +} + + +// method +void PODHeartBeatRspMessage::clear() +{ + trace_id = 0; + ret = 0; +} + +int PODHeartBeatRspMessage::pb2pod(const HeartBeatRspMessage & pb) +{ + trace_id = pb.trace_id(); + ret = pb.ret(); + return 0; +} + +int PODHeartBeatRspMessage::pod2pb(HeartBeatRspMessage * pb) +{ + pb->set_trace_id(trace_id); + pb->set_ret(ret); + return 0; +} + diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/heartbeat.h b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/heartbeat.h new file mode 100755 index 0000000..4c5c899 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/heartbeat.h @@ -0,0 +1,30 @@ +#ifndef __HEARTBEAT_H_ +#define __HEARTBEAT_H_ + +#include +#include "heartbeat.pb.h" +struct PODHeartBeatReqMessage // pb name HeartBeatReqMessage +{ + uint32_t trace_id; // trace_id = 1 + uint32_t ip; // ip = 2 + uint32_t time; // time = 3 + HeartBeatReqMessage::MachineEnum type; // EnumValues{{Name: E_PC}, {Name: E_IOS, Number: 1}, {Name: E_ANDRIOD, Number: 2}} + + // method + void clear(); + int pb2pod(const HeartBeatReqMessage & pb); + int pod2pb(HeartBeatReqMessage * pb); +}; + +struct PODHeartBeatRspMessage // pb name HeartBeatRspMessage +{ + uint32_t trace_id; // trace_id = 1 + uint32_t ret; // ret = 2 + + // method + void clear(); + int pb2pod(const HeartBeatRspMessage & pb); + int pod2pb(HeartBeatRspMessage * pb); +}; + +#endif diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/heartbeat.pb.go b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/heartbeat.pb.go new file mode 100755 index 0000000..ddbf583 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/heartbeat.pb.go @@ -0,0 +1,301 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.0 +// protoc v3.19.1 +// source: proto/heartbeat.proto + +package protocol + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type HeartBeatReqMessage_MachineEnum int32 + +const ( + HeartBeatReqMessage_E_PC HeartBeatReqMessage_MachineEnum = 0 + HeartBeatReqMessage_E_IOS HeartBeatReqMessage_MachineEnum = 1 + HeartBeatReqMessage_E_ANDRIOD HeartBeatReqMessage_MachineEnum = 2 +) + +// Enum value maps for HeartBeatReqMessage_MachineEnum. +var ( + HeartBeatReqMessage_MachineEnum_name = map[int32]string{ + 0: "E_PC", + 1: "E_IOS", + 2: "E_ANDRIOD", + } + HeartBeatReqMessage_MachineEnum_value = map[string]int32{ + "E_PC": 0, + "E_IOS": 1, + "E_ANDRIOD": 2, + } +) + +func (x HeartBeatReqMessage_MachineEnum) Enum() *HeartBeatReqMessage_MachineEnum { + p := new(HeartBeatReqMessage_MachineEnum) + *p = x + return p +} + +func (x HeartBeatReqMessage_MachineEnum) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (HeartBeatReqMessage_MachineEnum) Descriptor() protoreflect.EnumDescriptor { + return file_proto_heartbeat_proto_enumTypes[0].Descriptor() +} + +func (HeartBeatReqMessage_MachineEnum) Type() protoreflect.EnumType { + return &file_proto_heartbeat_proto_enumTypes[0] +} + +func (x HeartBeatReqMessage_MachineEnum) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use HeartBeatReqMessage_MachineEnum.Descriptor instead. +func (HeartBeatReqMessage_MachineEnum) EnumDescriptor() ([]byte, []int) { + return file_proto_heartbeat_proto_rawDescGZIP(), []int{0, 0} +} + +type HeartBeatReqMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TraceId uint32 `protobuf:"varint,1,opt,name=trace_id,json=traceId,proto3" json:"trace_id,omitempty"` + Ip uint32 `protobuf:"varint,2,opt,name=ip,proto3" json:"ip,omitempty"` + Time uint32 `protobuf:"varint,3,opt,name=time,proto3" json:"time,omitempty"` + Type HeartBeatReqMessage_MachineEnum `protobuf:"varint,4,opt,name=type,proto3,enum=HeartBeatReqMessage_MachineEnum" json:"type,omitempty"` +} + +func (x *HeartBeatReqMessage) Reset() { + *x = HeartBeatReqMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_heartbeat_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HeartBeatReqMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HeartBeatReqMessage) ProtoMessage() {} + +func (x *HeartBeatReqMessage) ProtoReflect() protoreflect.Message { + mi := &file_proto_heartbeat_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HeartBeatReqMessage.ProtoReflect.Descriptor instead. +func (*HeartBeatReqMessage) Descriptor() ([]byte, []int) { + return file_proto_heartbeat_proto_rawDescGZIP(), []int{0} +} + +func (x *HeartBeatReqMessage) GetTraceId() uint32 { + if x != nil { + return x.TraceId + } + return 0 +} + +func (x *HeartBeatReqMessage) GetIp() uint32 { + if x != nil { + return x.Ip + } + return 0 +} + +func (x *HeartBeatReqMessage) GetTime() uint32 { + if x != nil { + return x.Time + } + return 0 +} + +func (x *HeartBeatReqMessage) GetType() HeartBeatReqMessage_MachineEnum { + if x != nil { + return x.Type + } + return HeartBeatReqMessage_E_PC +} + +type HeartBeatRspMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TraceId uint32 `protobuf:"varint,1,opt,name=trace_id,json=traceId,proto3" json:"trace_id,omitempty"` + Ret uint32 `protobuf:"varint,2,opt,name=ret,proto3" json:"ret,omitempty"` +} + +func (x *HeartBeatRspMessage) Reset() { + *x = HeartBeatRspMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_heartbeat_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HeartBeatRspMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HeartBeatRspMessage) ProtoMessage() {} + +func (x *HeartBeatRspMessage) ProtoReflect() protoreflect.Message { + mi := &file_proto_heartbeat_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HeartBeatRspMessage.ProtoReflect.Descriptor instead. +func (*HeartBeatRspMessage) Descriptor() ([]byte, []int) { + return file_proto_heartbeat_proto_rawDescGZIP(), []int{1} +} + +func (x *HeartBeatRspMessage) GetTraceId() uint32 { + if x != nil { + return x.TraceId + } + return 0 +} + +func (x *HeartBeatRspMessage) GetRet() uint32 { + if x != nil { + return x.Ret + } + return 0 +} + +var File_proto_heartbeat_proto protoreflect.FileDescriptor + +var file_proto_heartbeat_proto_rawDesc = []byte{ + 0x0a, 0x15, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, + 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbd, 0x01, 0x0a, 0x13, 0x48, 0x65, 0x61, 0x72, + 0x74, 0x42, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x19, 0x0a, 0x08, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x07, 0x74, 0x72, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, + 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x34, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x48, + 0x65, 0x61, 0x72, 0x74, 0x42, 0x65, 0x61, 0x74, 0x52, 0x65, 0x71, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x2e, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x22, 0x31, 0x0a, 0x0b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x45, + 0x6e, 0x75, 0x6d, 0x12, 0x08, 0x0a, 0x04, 0x45, 0x5f, 0x50, 0x43, 0x10, 0x00, 0x12, 0x09, 0x0a, + 0x05, 0x45, 0x5f, 0x49, 0x4f, 0x53, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x45, 0x5f, 0x41, 0x4e, + 0x44, 0x52, 0x49, 0x4f, 0x44, 0x10, 0x02, 0x22, 0x42, 0x0a, 0x13, 0x48, 0x65, 0x61, 0x72, 0x74, + 0x42, 0x65, 0x61, 0x74, 0x52, 0x73, 0x70, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x19, + 0x0a, 0x08, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x07, 0x74, 0x72, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x72, 0x65, 0x74, 0x42, 0x0c, 0x5a, 0x0a, 0x2e, + 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, +} + +var ( + file_proto_heartbeat_proto_rawDescOnce sync.Once + file_proto_heartbeat_proto_rawDescData = file_proto_heartbeat_proto_rawDesc +) + +func file_proto_heartbeat_proto_rawDescGZIP() []byte { + file_proto_heartbeat_proto_rawDescOnce.Do(func() { + file_proto_heartbeat_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_heartbeat_proto_rawDescData) + }) + return file_proto_heartbeat_proto_rawDescData +} + +var file_proto_heartbeat_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_proto_heartbeat_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_proto_heartbeat_proto_goTypes = []interface{}{ + (HeartBeatReqMessage_MachineEnum)(0), // 0: HeartBeatReqMessage.MachineEnum + (*HeartBeatReqMessage)(nil), // 1: HeartBeatReqMessage + (*HeartBeatRspMessage)(nil), // 2: HeartBeatRspMessage +} +var file_proto_heartbeat_proto_depIdxs = []int32{ + 0, // 0: HeartBeatReqMessage.type:type_name -> HeartBeatReqMessage.MachineEnum + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_proto_heartbeat_proto_init() } +func file_proto_heartbeat_proto_init() { + if File_proto_heartbeat_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_proto_heartbeat_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HeartBeatReqMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_heartbeat_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HeartBeatRspMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_heartbeat_proto_rawDesc, + NumEnums: 1, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_proto_heartbeat_proto_goTypes, + DependencyIndexes: file_proto_heartbeat_proto_depIdxs, + EnumInfos: file_proto_heartbeat_proto_enumTypes, + MessageInfos: file_proto_heartbeat_proto_msgTypes, + }.Build() + File_proto_heartbeat_proto = out.File + file_proto_heartbeat_proto_rawDesc = nil + file_proto_heartbeat_proto_goTypes = nil + file_proto_heartbeat_proto_depIdxs = nil +} diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/machine.cpp b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/machine.cpp new file mode 100755 index 0000000..0c2b833 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/machine.cpp @@ -0,0 +1,49 @@ +#include "machine.h" +#include "machine.pb.h" + +// method +void PODInfoMessage::clear() +{ + ip = 0; + time = 0; +} + +int PODInfoMessage::pb2pod(const InfoMessage & pb) +{ + ip = pb.ip(); + time = pb.time(); + return 0; +} + +int PODInfoMessage::pod2pb(InfoMessage * pb) +{ + pb->set_ip(ip); + pb->set_time(time); + return 0; +} + + +// method +void PODMachineInfoMessage::clear() +{ + trace_id = 0; + info.clear(); + type = 0; +} + +int PODMachineInfoMessage::pb2pod(const MachineInfoMessage & pb) +{ + trace_id = pb.trace_id(); + info.pb2pod(pb.info()); + type = pb.type(); + return 0; +} + +int PODMachineInfoMessage::pod2pb(MachineInfoMessage * pb) +{ + pb->set_trace_id(trace_id); + info.pod2pb(pb->mutable_info()); + pb->set_type(type); + return 0; +} + diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/machine.h b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/machine.h new file mode 100755 index 0000000..63987a0 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/machine.h @@ -0,0 +1,29 @@ +#ifndef __MACHINE_H_ +#define __MACHINE_H_ + +#include +#include "machine.pb.h" +struct PODInfoMessage // pb name InfoMessage +{ + uint32_t ip; // ip = 1 + uint32_t time; // time = 2 + + // method + void clear(); + int pb2pod(const InfoMessage & pb); + int pod2pb(InfoMessage * pb); +}; + +struct PODMachineInfoMessage // pb name MachineInfoMessage +{ + uint32_t trace_id; // trace_id = 1 + PODInfoMessage info; + uint32_t type; // type = 3 + + // method + void clear(); + int pb2pod(const MachineInfoMessage & pb); + int pod2pb(MachineInfoMessage * pb); +}; + +#endif diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/machine.pb.go b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/machine.pb.go new file mode 100755 index 0000000..d4a18a5 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/machine.pb.go @@ -0,0 +1,234 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.0 +// protoc v3.19.1 +// source: proto/machine.proto + +package protocol + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type InfoMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ip uint32 `protobuf:"varint,1,opt,name=ip,proto3" json:"ip,omitempty"` + Time uint32 `protobuf:"varint,2,opt,name=time,proto3" json:"time,omitempty"` +} + +func (x *InfoMessage) Reset() { + *x = InfoMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_machine_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InfoMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InfoMessage) ProtoMessage() {} + +func (x *InfoMessage) ProtoReflect() protoreflect.Message { + mi := &file_proto_machine_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InfoMessage.ProtoReflect.Descriptor instead. +func (*InfoMessage) Descriptor() ([]byte, []int) { + return file_proto_machine_proto_rawDescGZIP(), []int{0} +} + +func (x *InfoMessage) GetIp() uint32 { + if x != nil { + return x.Ip + } + return 0 +} + +func (x *InfoMessage) GetTime() uint32 { + if x != nil { + return x.Time + } + return 0 +} + +type MachineInfoMessage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TraceId uint32 `protobuf:"varint,1,opt,name=trace_id,json=traceId,proto3" json:"trace_id,omitempty"` + Info *InfoMessage `protobuf:"bytes,2,opt,name=info,proto3" json:"info,omitempty"` + Type uint32 `protobuf:"varint,3,opt,name=type,proto3" json:"type,omitempty"` +} + +func (x *MachineInfoMessage) Reset() { + *x = MachineInfoMessage{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_machine_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MachineInfoMessage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MachineInfoMessage) ProtoMessage() {} + +func (x *MachineInfoMessage) ProtoReflect() protoreflect.Message { + mi := &file_proto_machine_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MachineInfoMessage.ProtoReflect.Descriptor instead. +func (*MachineInfoMessage) Descriptor() ([]byte, []int) { + return file_proto_machine_proto_rawDescGZIP(), []int{1} +} + +func (x *MachineInfoMessage) GetTraceId() uint32 { + if x != nil { + return x.TraceId + } + return 0 +} + +func (x *MachineInfoMessage) GetInfo() *InfoMessage { + if x != nil { + return x.Info + } + return nil +} + +func (x *MachineInfoMessage) GetType() uint32 { + if x != nil { + return x.Type + } + return 0 +} + +var File_proto_machine_proto protoreflect.FileDescriptor + +var file_proto_machine_proto_rawDesc = []byte{ + 0x0a, 0x13, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x31, 0x0a, 0x0b, 0x49, 0x6e, 0x66, 0x6f, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x02, 0x69, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x65, 0x0a, 0x12, 0x4d, 0x61, 0x63, 0x68, + 0x69, 0x6e, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x19, + 0x0a, 0x08, 0x74, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x07, 0x74, 0x72, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x04, 0x69, 0x6e, 0x66, + 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x49, 0x6e, 0x66, 0x6f, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x42, + 0x0c, 0x5a, 0x0a, 0x2e, 0x3b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_proto_machine_proto_rawDescOnce sync.Once + file_proto_machine_proto_rawDescData = file_proto_machine_proto_rawDesc +) + +func file_proto_machine_proto_rawDescGZIP() []byte { + file_proto_machine_proto_rawDescOnce.Do(func() { + file_proto_machine_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_machine_proto_rawDescData) + }) + return file_proto_machine_proto_rawDescData +} + +var file_proto_machine_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_proto_machine_proto_goTypes = []interface{}{ + (*InfoMessage)(nil), // 0: InfoMessage + (*MachineInfoMessage)(nil), // 1: MachineInfoMessage +} +var file_proto_machine_proto_depIdxs = []int32{ + 0, // 0: MachineInfoMessage.info:type_name -> InfoMessage + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_proto_machine_proto_init() } +func file_proto_machine_proto_init() { + if File_proto_machine_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_proto_machine_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*InfoMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_machine_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MachineInfoMessage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_machine_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_proto_machine_proto_goTypes, + DependencyIndexes: file_proto_machine_proto_depIdxs, + MessageInfos: file_proto_machine_proto_msgTypes, + }.Build() + File_proto_machine_proto = out.File + file_proto_machine_proto_rawDesc = nil + file_proto_machine_proto_goTypes = nil + file_proto_machine_proto_depIdxs = nil +} diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/custom_opt.pb.cc b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/custom_opt.pb.cc new file mode 100755 index 0000000..94a2e2e --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/custom_opt.pb.cc @@ -0,0 +1,60 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: proto/custom_opt.proto + +#include "proto/custom_opt.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) +#include + +PROTOBUF_PRAGMA_INIT_SEG +namespace custom { +} // namespace custom +static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_proto_2fcustom_5fopt_2eproto = nullptr; +static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_proto_2fcustom_5fopt_2eproto = nullptr; +const uint32_t TableStruct_proto_2fcustom_5fopt_2eproto::offsets[1] = {}; +static constexpr ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema* schemas = nullptr; +static constexpr ::PROTOBUF_NAMESPACE_ID::Message* const* file_default_instances = nullptr; + +const char descriptor_table_protodef_proto_2fcustom_5fopt_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\026proto/custom_opt.proto\022\006custom\032 google" + "/protobuf/descriptor.proto:5\n\topt_count\022" + "\035.google.protobuf.FieldOptions\030\320\206\003 \001(\r\210\001" + "\001B\tZ\007/customb\006proto3" + ; +static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_proto_2fcustom_5fopt_2eproto_deps[1] = { + &::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, +}; +static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_proto_2fcustom_5fopt_2eproto_once; +const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_proto_2fcustom_5fopt_2eproto = { + false, false, 140, descriptor_table_protodef_proto_2fcustom_5fopt_2eproto, "proto/custom_opt.proto", + &descriptor_table_proto_2fcustom_5fopt_2eproto_once, descriptor_table_proto_2fcustom_5fopt_2eproto_deps, 1, 0, + schemas, file_default_instances, TableStruct_proto_2fcustom_5fopt_2eproto::offsets, + nullptr, file_level_enum_descriptors_proto_2fcustom_5fopt_2eproto, file_level_service_descriptors_proto_2fcustom_5fopt_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_proto_2fcustom_5fopt_2eproto_getter() { + return &descriptor_table_proto_2fcustom_5fopt_2eproto; +} + +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_proto_2fcustom_5fopt_2eproto(&descriptor_table_proto_2fcustom_5fopt_2eproto); +namespace custom { +PROTOBUF_ATTRIBUTE_INIT_PRIORITY ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< ::PROTOBUF_NAMESPACE_ID::FieldOptions, + ::PROTOBUF_NAMESPACE_ID::internal::PrimitiveTypeTraits< uint32_t >, 13, false > + opt_count(kOptCountFieldNumber, 0u); + +// @@protoc_insertion_point(namespace_scope) +} // namespace custom +PROTOBUF_NAMESPACE_OPEN +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/custom_opt.pb.h b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/custom_opt.pb.h new file mode 100755 index 0000000..1e34cba --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/custom_opt.pb.h @@ -0,0 +1,86 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: proto/custom_opt.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_proto_2fcustom_5fopt_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_proto_2fcustom_5fopt_2eproto + +#include +#include + +#include +#if PROTOBUF_VERSION < 3019000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 3019001 < PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include // IWYU pragma: export +#include // IWYU pragma: export +#include +// @@protoc_insertion_point(includes) +#include +#define PROTOBUF_INTERNAL_EXPORT_proto_2fcustom_5fopt_2eproto +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct TableStruct_proto_2fcustom_5fopt_2eproto { + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; + static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; + static const uint32_t offsets[]; +}; +extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_proto_2fcustom_5fopt_2eproto; +PROTOBUF_NAMESPACE_OPEN +PROTOBUF_NAMESPACE_CLOSE +namespace custom { + +// =================================================================== + + +// =================================================================== + +static const int kOptCountFieldNumber = 50000; +extern ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< ::PROTOBUF_NAMESPACE_ID::FieldOptions, + ::PROTOBUF_NAMESPACE_ID::internal::PrimitiveTypeTraits< uint32_t >, 13, false > + opt_count; + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) + +} // namespace custom + +// @@protoc_insertion_point(global_scope) + +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_proto_2fcustom_5fopt_2eproto diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/demo.pb.cc b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/demo.pb.cc new file mode 100755 index 0000000..4912b36 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/demo.pb.cc @@ -0,0 +1,574 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: proto/demo.proto + +#include "proto/demo.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) +#include + +PROTOBUF_PRAGMA_INIT_SEG +constexpr UserMsg::UserMsg( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : id_(0u) + , age_(0u) + , passwd_(0u){} +struct UserMsgDefaultTypeInternal { + constexpr UserMsgDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~UserMsgDefaultTypeInternal() {} + union { + UserMsg _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT UserMsgDefaultTypeInternal _UserMsg_default_instance_; +constexpr FamilyMsg::FamilyMsg( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : familys_() + , rid_arrs_() + , _rid_arrs_cached_byte_size_(0){} +struct FamilyMsgDefaultTypeInternal { + constexpr FamilyMsgDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~FamilyMsgDefaultTypeInternal() {} + union { + FamilyMsg _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT FamilyMsgDefaultTypeInternal _FamilyMsg_default_instance_; +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_proto_2fdemo_2eproto[2]; +static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_proto_2fdemo_2eproto = nullptr; +static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_proto_2fdemo_2eproto = nullptr; + +const uint32_t TableStruct_proto_2fdemo_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::UserMsg, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::UserMsg, id_), + PROTOBUF_FIELD_OFFSET(::UserMsg, age_), + PROTOBUF_FIELD_OFFSET(::UserMsg, passwd_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::FamilyMsg, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::FamilyMsg, familys_), + PROTOBUF_FIELD_OFFSET(::FamilyMsg, rid_arrs_), +}; +static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, -1, sizeof(::UserMsg)}, + { 9, -1, -1, sizeof(::FamilyMsg)}, +}; + +static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { + reinterpret_cast(&::_UserMsg_default_instance_), + reinterpret_cast(&::_FamilyMsg_default_instance_), +}; + +const char descriptor_table_protodef_proto_2fdemo_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\020proto/demo.proto\032\026proto/custom_opt.pro" + "to\"2\n\007UserMsg\022\n\n\002id\030\001 \001(\r\022\013\n\003age\030\002 \001(\r\022\016" + "\n\006passwd\030\003 \001(\r\"D\n\tFamilyMsg\022\037\n\007familys\030\001" + " \003(\0132\010.UserMsgB\004\200\265\030\n\022\026\n\010rid_arrs\030\002 \003(\rB\004" + "\200\265\0302B\014Z\n.;protocolb\006proto3" + ; +static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_proto_2fdemo_2eproto_deps[1] = { + &::descriptor_table_proto_2fcustom_5fopt_2eproto, +}; +static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_proto_2fdemo_2eproto_once; +const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_proto_2fdemo_2eproto = { + false, false, 186, descriptor_table_protodef_proto_2fdemo_2eproto, "proto/demo.proto", + &descriptor_table_proto_2fdemo_2eproto_once, descriptor_table_proto_2fdemo_2eproto_deps, 1, 2, + schemas, file_default_instances, TableStruct_proto_2fdemo_2eproto::offsets, + file_level_metadata_proto_2fdemo_2eproto, file_level_enum_descriptors_proto_2fdemo_2eproto, file_level_service_descriptors_proto_2fdemo_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_proto_2fdemo_2eproto_getter() { + return &descriptor_table_proto_2fdemo_2eproto; +} + +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_proto_2fdemo_2eproto(&descriptor_table_proto_2fdemo_2eproto); + +// =================================================================== + +class UserMsg::_Internal { + public: +}; + +UserMsg::UserMsg(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(); + if (!is_message_owned) { + RegisterArenaDtor(arena); + } + // @@protoc_insertion_point(arena_constructor:UserMsg) +} +UserMsg::UserMsg(const UserMsg& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&id_, &from.id_, + static_cast(reinterpret_cast(&passwd_) - + reinterpret_cast(&id_)) + sizeof(passwd_)); + // @@protoc_insertion_point(copy_constructor:UserMsg) +} + +inline void UserMsg::SharedCtor() { +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&id_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&passwd_) - + reinterpret_cast(&id_)) + sizeof(passwd_)); +} + +UserMsg::~UserMsg() { + // @@protoc_insertion_point(destructor:UserMsg) + if (GetArenaForAllocation() != nullptr) return; + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +inline void UserMsg::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); +} + +void UserMsg::ArenaDtor(void* object) { + UserMsg* _this = reinterpret_cast< UserMsg* >(object); + (void)_this; +} +void UserMsg::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void UserMsg::SetCachedSize(int size) const { + _cached_size_.Set(size); +} + +void UserMsg::Clear() { +// @@protoc_insertion_point(message_clear_start:UserMsg) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + ::memset(&id_, 0, static_cast( + reinterpret_cast(&passwd_) - + reinterpret_cast(&id_)) + sizeof(passwd_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* UserMsg::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + switch (tag >> 3) { + // uint32 id = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 8)) { + id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // uint32 age = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 16)) { + age_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // uint32 passwd = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 24)) { + passwd_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* UserMsg::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:UserMsg) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // uint32 id = 1; + if (this->_internal_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(1, this->_internal_id(), target); + } + + // uint32 age = 2; + if (this->_internal_age() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(2, this->_internal_age(), target); + } + + // uint32 passwd = 3; + if (this->_internal_passwd() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(3, this->_internal_passwd(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:UserMsg) + return target; +} + +size_t UserMsg::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:UserMsg) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // uint32 id = 1; + if (this->_internal_id() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_id()); + } + + // uint32 age = 2; + if (this->_internal_age() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_age()); + } + + // uint32 passwd = 3; + if (this->_internal_passwd() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_passwd()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData UserMsg::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck, + UserMsg::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*UserMsg::GetClassData() const { return &_class_data_; } + +void UserMsg::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, + const ::PROTOBUF_NAMESPACE_ID::Message& from) { + static_cast(to)->MergeFrom( + static_cast(from)); +} + + +void UserMsg::MergeFrom(const UserMsg& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:UserMsg) + GOOGLE_DCHECK_NE(&from, this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (from._internal_id() != 0) { + _internal_set_id(from._internal_id()); + } + if (from._internal_age() != 0) { + _internal_set_age(from._internal_age()); + } + if (from._internal_passwd() != 0) { + _internal_set_passwd(from._internal_passwd()); + } + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void UserMsg::CopyFrom(const UserMsg& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:UserMsg) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool UserMsg::IsInitialized() const { + return true; +} + +void UserMsg::InternalSwap(UserMsg* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(UserMsg, passwd_) + + sizeof(UserMsg::passwd_) + - PROTOBUF_FIELD_OFFSET(UserMsg, id_)>( + reinterpret_cast(&id_), + reinterpret_cast(&other->id_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata UserMsg::GetMetadata() const { + return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors( + &descriptor_table_proto_2fdemo_2eproto_getter, &descriptor_table_proto_2fdemo_2eproto_once, + file_level_metadata_proto_2fdemo_2eproto[0]); +} + +// =================================================================== + +class FamilyMsg::_Internal { + public: +}; + +FamilyMsg::FamilyMsg(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned), + familys_(arena), + rid_arrs_(arena) { + SharedCtor(); + if (!is_message_owned) { + RegisterArenaDtor(arena); + } + // @@protoc_insertion_point(arena_constructor:FamilyMsg) +} +FamilyMsg::FamilyMsg(const FamilyMsg& from) + : ::PROTOBUF_NAMESPACE_ID::Message(), + familys_(from.familys_), + rid_arrs_(from.rid_arrs_) { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + // @@protoc_insertion_point(copy_constructor:FamilyMsg) +} + +inline void FamilyMsg::SharedCtor() { +} + +FamilyMsg::~FamilyMsg() { + // @@protoc_insertion_point(destructor:FamilyMsg) + if (GetArenaForAllocation() != nullptr) return; + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +inline void FamilyMsg::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); +} + +void FamilyMsg::ArenaDtor(void* object) { + FamilyMsg* _this = reinterpret_cast< FamilyMsg* >(object); + (void)_this; +} +void FamilyMsg::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void FamilyMsg::SetCachedSize(int size) const { + _cached_size_.Set(size); +} + +void FamilyMsg::Clear() { +// @@protoc_insertion_point(message_clear_start:FamilyMsg) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + familys_.Clear(); + rid_arrs_.Clear(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* FamilyMsg::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + switch (tag >> 3) { + // repeated .UserMsg familys = 1 [(.custom.opt_count) = 10]; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 10)) { + ptr -= 1; + do { + ptr += 1; + ptr = ctx->ParseMessage(_internal_add_familys(), ptr); + CHK_(ptr); + if (!ctx->DataAvailable(ptr)) break; + } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr)); + } else + goto handle_unusual; + continue; + // repeated uint32 rid_arrs = 2 [(.custom.opt_count) = 50]; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 18)) { + ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedUInt32Parser(_internal_mutable_rid_arrs(), ptr, ctx); + CHK_(ptr); + } else if (static_cast(tag) == 16) { + _internal_add_rid_arrs(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr)); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* FamilyMsg::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:FamilyMsg) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // repeated .UserMsg familys = 1 [(.custom.opt_count) = 10]; + for (unsigned int i = 0, + n = static_cast(this->_internal_familys_size()); i < n; i++) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(1, this->_internal_familys(i), target, stream); + } + + // repeated uint32 rid_arrs = 2 [(.custom.opt_count) = 50]; + { + int byte_size = _rid_arrs_cached_byte_size_.load(std::memory_order_relaxed); + if (byte_size > 0) { + target = stream->WriteUInt32Packed( + 2, _internal_rid_arrs(), byte_size, target); + } + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:FamilyMsg) + return target; +} + +size_t FamilyMsg::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:FamilyMsg) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // repeated .UserMsg familys = 1 [(.custom.opt_count) = 10]; + total_size += 1UL * this->_internal_familys_size(); + for (const auto& msg : this->familys_) { + total_size += + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(msg); + } + + // repeated uint32 rid_arrs = 2 [(.custom.opt_count) = 50]; + { + size_t data_size = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + UInt32Size(this->rid_arrs_); + if (data_size > 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::Int32Size( + static_cast(data_size)); + } + int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(data_size); + _rid_arrs_cached_byte_size_.store(cached_size, + std::memory_order_relaxed); + total_size += data_size; + } + + return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData FamilyMsg::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck, + FamilyMsg::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*FamilyMsg::GetClassData() const { return &_class_data_; } + +void FamilyMsg::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, + const ::PROTOBUF_NAMESPACE_ID::Message& from) { + static_cast(to)->MergeFrom( + static_cast(from)); +} + + +void FamilyMsg::MergeFrom(const FamilyMsg& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:FamilyMsg) + GOOGLE_DCHECK_NE(&from, this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + familys_.MergeFrom(from.familys_); + rid_arrs_.MergeFrom(from.rid_arrs_); + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void FamilyMsg::CopyFrom(const FamilyMsg& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:FamilyMsg) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool FamilyMsg::IsInitialized() const { + return true; +} + +void FamilyMsg::InternalSwap(FamilyMsg* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + familys_.InternalSwap(&other->familys_); + rid_arrs_.InternalSwap(&other->rid_arrs_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata FamilyMsg::GetMetadata() const { + return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors( + &descriptor_table_proto_2fdemo_2eproto_getter, &descriptor_table_proto_2fdemo_2eproto_once, + file_level_metadata_proto_2fdemo_2eproto[1]); +} + +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::UserMsg* Arena::CreateMaybeMessage< ::UserMsg >(Arena* arena) { + return Arena::CreateMessageInternal< ::UserMsg >(arena); +} +template<> PROTOBUF_NOINLINE ::FamilyMsg* Arena::CreateMaybeMessage< ::FamilyMsg >(Arena* arena) { + return Arena::CreateMessageInternal< ::FamilyMsg >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/demo.pb.h b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/demo.pb.h new file mode 100755 index 0000000..5d0bf32 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/demo.pb.h @@ -0,0 +1,590 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: proto/demo.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_proto_2fdemo_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_proto_2fdemo_2eproto + +#include +#include + +#include +#if PROTOBUF_VERSION < 3019000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 3019001 < PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // IWYU pragma: export +#include // IWYU pragma: export +#include +#include "proto/custom_opt.pb.h" +// @@protoc_insertion_point(includes) +#include +#define PROTOBUF_INTERNAL_EXPORT_proto_2fdemo_2eproto +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct TableStruct_proto_2fdemo_2eproto { + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[2] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; + static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; + static const uint32_t offsets[]; +}; +extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_proto_2fdemo_2eproto; +class FamilyMsg; +struct FamilyMsgDefaultTypeInternal; +extern FamilyMsgDefaultTypeInternal _FamilyMsg_default_instance_; +class UserMsg; +struct UserMsgDefaultTypeInternal; +extern UserMsgDefaultTypeInternal _UserMsg_default_instance_; +PROTOBUF_NAMESPACE_OPEN +template<> ::FamilyMsg* Arena::CreateMaybeMessage<::FamilyMsg>(Arena*); +template<> ::UserMsg* Arena::CreateMaybeMessage<::UserMsg>(Arena*); +PROTOBUF_NAMESPACE_CLOSE + +// =================================================================== + +class UserMsg final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:UserMsg) */ { + public: + inline UserMsg() : UserMsg(nullptr) {} + ~UserMsg() override; + explicit constexpr UserMsg(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + UserMsg(const UserMsg& from); + UserMsg(UserMsg&& from) noexcept + : UserMsg() { + *this = ::std::move(from); + } + + inline UserMsg& operator=(const UserMsg& from) { + CopyFrom(from); + return *this; + } + inline UserMsg& operator=(UserMsg&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const UserMsg& default_instance() { + return *internal_default_instance(); + } + static inline const UserMsg* internal_default_instance() { + return reinterpret_cast( + &_UserMsg_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(UserMsg& a, UserMsg& b) { + a.Swap(&b); + } + inline void Swap(UserMsg* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(UserMsg* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + UserMsg* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const UserMsg& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom(const UserMsg& from); + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(UserMsg* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "UserMsg"; + } + protected: + explicit UserMsg(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kIdFieldNumber = 1, + kAgeFieldNumber = 2, + kPasswdFieldNumber = 3, + }; + // uint32 id = 1; + void clear_id(); + uint32_t id() const; + void set_id(uint32_t value); + private: + uint32_t _internal_id() const; + void _internal_set_id(uint32_t value); + public: + + // uint32 age = 2; + void clear_age(); + uint32_t age() const; + void set_age(uint32_t value); + private: + uint32_t _internal_age() const; + void _internal_set_age(uint32_t value); + public: + + // uint32 passwd = 3; + void clear_passwd(); + uint32_t passwd() const; + void set_passwd(uint32_t value); + private: + uint32_t _internal_passwd() const; + void _internal_set_passwd(uint32_t value); + public: + + // @@protoc_insertion_point(class_scope:UserMsg) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + uint32_t id_; + uint32_t age_; + uint32_t passwd_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_proto_2fdemo_2eproto; +}; +// ------------------------------------------------------------------- + +class FamilyMsg final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:FamilyMsg) */ { + public: + inline FamilyMsg() : FamilyMsg(nullptr) {} + ~FamilyMsg() override; + explicit constexpr FamilyMsg(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + FamilyMsg(const FamilyMsg& from); + FamilyMsg(FamilyMsg&& from) noexcept + : FamilyMsg() { + *this = ::std::move(from); + } + + inline FamilyMsg& operator=(const FamilyMsg& from) { + CopyFrom(from); + return *this; + } + inline FamilyMsg& operator=(FamilyMsg&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const FamilyMsg& default_instance() { + return *internal_default_instance(); + } + static inline const FamilyMsg* internal_default_instance() { + return reinterpret_cast( + &_FamilyMsg_default_instance_); + } + static constexpr int kIndexInFileMessages = + 1; + + friend void swap(FamilyMsg& a, FamilyMsg& b) { + a.Swap(&b); + } + inline void Swap(FamilyMsg* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(FamilyMsg* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + FamilyMsg* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const FamilyMsg& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom(const FamilyMsg& from); + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(FamilyMsg* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "FamilyMsg"; + } + protected: + explicit FamilyMsg(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kFamilysFieldNumber = 1, + kRidArrsFieldNumber = 2, + }; + // repeated .UserMsg familys = 1 [(.custom.opt_count) = 10]; + int familys_size() const; + private: + int _internal_familys_size() const; + public: + void clear_familys(); + ::UserMsg* mutable_familys(int index); + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::UserMsg >* + mutable_familys(); + private: + const ::UserMsg& _internal_familys(int index) const; + ::UserMsg* _internal_add_familys(); + public: + const ::UserMsg& familys(int index) const; + ::UserMsg* add_familys(); + const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::UserMsg >& + familys() const; + + // repeated uint32 rid_arrs = 2 [(.custom.opt_count) = 50]; + int rid_arrs_size() const; + private: + int _internal_rid_arrs_size() const; + public: + void clear_rid_arrs(); + private: + uint32_t _internal_rid_arrs(int index) const; + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< uint32_t >& + _internal_rid_arrs() const; + void _internal_add_rid_arrs(uint32_t value); + ::PROTOBUF_NAMESPACE_ID::RepeatedField< uint32_t >* + _internal_mutable_rid_arrs(); + public: + uint32_t rid_arrs(int index) const; + void set_rid_arrs(int index, uint32_t value); + void add_rid_arrs(uint32_t value); + const ::PROTOBUF_NAMESPACE_ID::RepeatedField< uint32_t >& + rid_arrs() const; + ::PROTOBUF_NAMESPACE_ID::RepeatedField< uint32_t >* + mutable_rid_arrs(); + + // @@protoc_insertion_point(class_scope:FamilyMsg) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::UserMsg > familys_; + ::PROTOBUF_NAMESPACE_ID::RepeatedField< uint32_t > rid_arrs_; + mutable std::atomic _rid_arrs_cached_byte_size_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_proto_2fdemo_2eproto; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// UserMsg + +// uint32 id = 1; +inline void UserMsg::clear_id() { + id_ = 0u; +} +inline uint32_t UserMsg::_internal_id() const { + return id_; +} +inline uint32_t UserMsg::id() const { + // @@protoc_insertion_point(field_get:UserMsg.id) + return _internal_id(); +} +inline void UserMsg::_internal_set_id(uint32_t value) { + + id_ = value; +} +inline void UserMsg::set_id(uint32_t value) { + _internal_set_id(value); + // @@protoc_insertion_point(field_set:UserMsg.id) +} + +// uint32 age = 2; +inline void UserMsg::clear_age() { + age_ = 0u; +} +inline uint32_t UserMsg::_internal_age() const { + return age_; +} +inline uint32_t UserMsg::age() const { + // @@protoc_insertion_point(field_get:UserMsg.age) + return _internal_age(); +} +inline void UserMsg::_internal_set_age(uint32_t value) { + + age_ = value; +} +inline void UserMsg::set_age(uint32_t value) { + _internal_set_age(value); + // @@protoc_insertion_point(field_set:UserMsg.age) +} + +// uint32 passwd = 3; +inline void UserMsg::clear_passwd() { + passwd_ = 0u; +} +inline uint32_t UserMsg::_internal_passwd() const { + return passwd_; +} +inline uint32_t UserMsg::passwd() const { + // @@protoc_insertion_point(field_get:UserMsg.passwd) + return _internal_passwd(); +} +inline void UserMsg::_internal_set_passwd(uint32_t value) { + + passwd_ = value; +} +inline void UserMsg::set_passwd(uint32_t value) { + _internal_set_passwd(value); + // @@protoc_insertion_point(field_set:UserMsg.passwd) +} + +// ------------------------------------------------------------------- + +// FamilyMsg + +// repeated .UserMsg familys = 1 [(.custom.opt_count) = 10]; +inline int FamilyMsg::_internal_familys_size() const { + return familys_.size(); +} +inline int FamilyMsg::familys_size() const { + return _internal_familys_size(); +} +inline void FamilyMsg::clear_familys() { + familys_.Clear(); +} +inline ::UserMsg* FamilyMsg::mutable_familys(int index) { + // @@protoc_insertion_point(field_mutable:FamilyMsg.familys) + return familys_.Mutable(index); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::UserMsg >* +FamilyMsg::mutable_familys() { + // @@protoc_insertion_point(field_mutable_list:FamilyMsg.familys) + return &familys_; +} +inline const ::UserMsg& FamilyMsg::_internal_familys(int index) const { + return familys_.Get(index); +} +inline const ::UserMsg& FamilyMsg::familys(int index) const { + // @@protoc_insertion_point(field_get:FamilyMsg.familys) + return _internal_familys(index); +} +inline ::UserMsg* FamilyMsg::_internal_add_familys() { + return familys_.Add(); +} +inline ::UserMsg* FamilyMsg::add_familys() { + ::UserMsg* _add = _internal_add_familys(); + // @@protoc_insertion_point(field_add:FamilyMsg.familys) + return _add; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::UserMsg >& +FamilyMsg::familys() const { + // @@protoc_insertion_point(field_list:FamilyMsg.familys) + return familys_; +} + +// repeated uint32 rid_arrs = 2 [(.custom.opt_count) = 50]; +inline int FamilyMsg::_internal_rid_arrs_size() const { + return rid_arrs_.size(); +} +inline int FamilyMsg::rid_arrs_size() const { + return _internal_rid_arrs_size(); +} +inline void FamilyMsg::clear_rid_arrs() { + rid_arrs_.Clear(); +} +inline uint32_t FamilyMsg::_internal_rid_arrs(int index) const { + return rid_arrs_.Get(index); +} +inline uint32_t FamilyMsg::rid_arrs(int index) const { + // @@protoc_insertion_point(field_get:FamilyMsg.rid_arrs) + return _internal_rid_arrs(index); +} +inline void FamilyMsg::set_rid_arrs(int index, uint32_t value) { + rid_arrs_.Set(index, value); + // @@protoc_insertion_point(field_set:FamilyMsg.rid_arrs) +} +inline void FamilyMsg::_internal_add_rid_arrs(uint32_t value) { + rid_arrs_.Add(value); +} +inline void FamilyMsg::add_rid_arrs(uint32_t value) { + _internal_add_rid_arrs(value); + // @@protoc_insertion_point(field_add:FamilyMsg.rid_arrs) +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< uint32_t >& +FamilyMsg::_internal_rid_arrs() const { + return rid_arrs_; +} +inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< uint32_t >& +FamilyMsg::rid_arrs() const { + // @@protoc_insertion_point(field_list:FamilyMsg.rid_arrs) + return _internal_rid_arrs(); +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< uint32_t >* +FamilyMsg::_internal_mutable_rid_arrs() { + return &rid_arrs_; +} +inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< uint32_t >* +FamilyMsg::mutable_rid_arrs() { + // @@protoc_insertion_point(field_mutable_list:FamilyMsg.rid_arrs) + return _internal_mutable_rid_arrs(); +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ +// ------------------------------------------------------------------- + + +// @@protoc_insertion_point(namespace_scope) + + +// @@protoc_insertion_point(global_scope) + +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_proto_2fdemo_2eproto diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/heartbeat.pb.cc b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/heartbeat.pb.cc new file mode 100755 index 0000000..97bea26 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/heartbeat.pb.cc @@ -0,0 +1,610 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: proto/heartbeat.proto + +#include "proto/heartbeat.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) +#include + +PROTOBUF_PRAGMA_INIT_SEG +constexpr HeartBeatReqMessage::HeartBeatReqMessage( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : trace_id_(0u) + , ip_(0u) + , time_(0u) + , type_(0) +{} +struct HeartBeatReqMessageDefaultTypeInternal { + constexpr HeartBeatReqMessageDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~HeartBeatReqMessageDefaultTypeInternal() {} + union { + HeartBeatReqMessage _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT HeartBeatReqMessageDefaultTypeInternal _HeartBeatReqMessage_default_instance_; +constexpr HeartBeatRspMessage::HeartBeatRspMessage( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : trace_id_(0u) + , ret_(0u){} +struct HeartBeatRspMessageDefaultTypeInternal { + constexpr HeartBeatRspMessageDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~HeartBeatRspMessageDefaultTypeInternal() {} + union { + HeartBeatRspMessage _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT HeartBeatRspMessageDefaultTypeInternal _HeartBeatRspMessage_default_instance_; +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_proto_2fheartbeat_2eproto[2]; +static const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* file_level_enum_descriptors_proto_2fheartbeat_2eproto[1]; +static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_proto_2fheartbeat_2eproto = nullptr; + +const uint32_t TableStruct_proto_2fheartbeat_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::HeartBeatReqMessage, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::HeartBeatReqMessage, trace_id_), + PROTOBUF_FIELD_OFFSET(::HeartBeatReqMessage, ip_), + PROTOBUF_FIELD_OFFSET(::HeartBeatReqMessage, time_), + PROTOBUF_FIELD_OFFSET(::HeartBeatReqMessage, type_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::HeartBeatRspMessage, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::HeartBeatRspMessage, trace_id_), + PROTOBUF_FIELD_OFFSET(::HeartBeatRspMessage, ret_), +}; +static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, -1, sizeof(::HeartBeatReqMessage)}, + { 10, -1, -1, sizeof(::HeartBeatRspMessage)}, +}; + +static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { + reinterpret_cast(&::_HeartBeatReqMessage_default_instance_), + reinterpret_cast(&::_HeartBeatRspMessage_default_instance_), +}; + +const char descriptor_table_protodef_proto_2fheartbeat_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\025proto/heartbeat.proto\"\244\001\n\023HeartBeatReq" + "Message\022\020\n\010trace_id\030\001 \001(\r\022\n\n\002ip\030\002 \001(\r\022\014\n" + "\004time\030\003 \001(\r\022.\n\004type\030\004 \001(\0162 .HeartBeatReq" + "Message.MachineEnum\"1\n\013MachineEnum\022\010\n\004E_" + "PC\020\000\022\t\n\005E_IOS\020\001\022\r\n\tE_ANDRIOD\020\002\"4\n\023HeartB" + "eatRspMessage\022\020\n\010trace_id\030\001 \001(\r\022\013\n\003ret\030\002" + " \001(\rB\014Z\n.;protocolb\006proto3" + ; +static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_proto_2fheartbeat_2eproto_once; +const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_proto_2fheartbeat_2eproto = { + false, false, 266, descriptor_table_protodef_proto_2fheartbeat_2eproto, "proto/heartbeat.proto", + &descriptor_table_proto_2fheartbeat_2eproto_once, nullptr, 0, 2, + schemas, file_default_instances, TableStruct_proto_2fheartbeat_2eproto::offsets, + file_level_metadata_proto_2fheartbeat_2eproto, file_level_enum_descriptors_proto_2fheartbeat_2eproto, file_level_service_descriptors_proto_2fheartbeat_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_proto_2fheartbeat_2eproto_getter() { + return &descriptor_table_proto_2fheartbeat_2eproto; +} + +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_proto_2fheartbeat_2eproto(&descriptor_table_proto_2fheartbeat_2eproto); +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* HeartBeatReqMessage_MachineEnum_descriptor() { + ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_proto_2fheartbeat_2eproto); + return file_level_enum_descriptors_proto_2fheartbeat_2eproto[0]; +} +bool HeartBeatReqMessage_MachineEnum_IsValid(int value) { + switch (value) { + case 0: + case 1: + case 2: + return true; + default: + return false; + } +} + +#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) +constexpr HeartBeatReqMessage_MachineEnum HeartBeatReqMessage::E_PC; +constexpr HeartBeatReqMessage_MachineEnum HeartBeatReqMessage::E_IOS; +constexpr HeartBeatReqMessage_MachineEnum HeartBeatReqMessage::E_ANDRIOD; +constexpr HeartBeatReqMessage_MachineEnum HeartBeatReqMessage::MachineEnum_MIN; +constexpr HeartBeatReqMessage_MachineEnum HeartBeatReqMessage::MachineEnum_MAX; +constexpr int HeartBeatReqMessage::MachineEnum_ARRAYSIZE; +#endif // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912)) + +// =================================================================== + +class HeartBeatReqMessage::_Internal { + public: +}; + +HeartBeatReqMessage::HeartBeatReqMessage(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(); + if (!is_message_owned) { + RegisterArenaDtor(arena); + } + // @@protoc_insertion_point(arena_constructor:HeartBeatReqMessage) +} +HeartBeatReqMessage::HeartBeatReqMessage(const HeartBeatReqMessage& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&trace_id_, &from.trace_id_, + static_cast(reinterpret_cast(&type_) - + reinterpret_cast(&trace_id_)) + sizeof(type_)); + // @@protoc_insertion_point(copy_constructor:HeartBeatReqMessage) +} + +inline void HeartBeatReqMessage::SharedCtor() { +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&trace_id_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&type_) - + reinterpret_cast(&trace_id_)) + sizeof(type_)); +} + +HeartBeatReqMessage::~HeartBeatReqMessage() { + // @@protoc_insertion_point(destructor:HeartBeatReqMessage) + if (GetArenaForAllocation() != nullptr) return; + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +inline void HeartBeatReqMessage::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); +} + +void HeartBeatReqMessage::ArenaDtor(void* object) { + HeartBeatReqMessage* _this = reinterpret_cast< HeartBeatReqMessage* >(object); + (void)_this; +} +void HeartBeatReqMessage::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void HeartBeatReqMessage::SetCachedSize(int size) const { + _cached_size_.Set(size); +} + +void HeartBeatReqMessage::Clear() { +// @@protoc_insertion_point(message_clear_start:HeartBeatReqMessage) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + ::memset(&trace_id_, 0, static_cast( + reinterpret_cast(&type_) - + reinterpret_cast(&trace_id_)) + sizeof(type_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* HeartBeatReqMessage::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + switch (tag >> 3) { + // uint32 trace_id = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 8)) { + trace_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // uint32 ip = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 16)) { + ip_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // uint32 time = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 24)) { + time_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // .HeartBeatReqMessage.MachineEnum type = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 32)) { + uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + _internal_set_type(static_cast<::HeartBeatReqMessage_MachineEnum>(val)); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* HeartBeatReqMessage::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:HeartBeatReqMessage) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // uint32 trace_id = 1; + if (this->_internal_trace_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(1, this->_internal_trace_id(), target); + } + + // uint32 ip = 2; + if (this->_internal_ip() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(2, this->_internal_ip(), target); + } + + // uint32 time = 3; + if (this->_internal_time() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(3, this->_internal_time(), target); + } + + // .HeartBeatReqMessage.MachineEnum type = 4; + if (this->_internal_type() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray( + 4, this->_internal_type(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:HeartBeatReqMessage) + return target; +} + +size_t HeartBeatReqMessage::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:HeartBeatReqMessage) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // uint32 trace_id = 1; + if (this->_internal_trace_id() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_trace_id()); + } + + // uint32 ip = 2; + if (this->_internal_ip() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_ip()); + } + + // uint32 time = 3; + if (this->_internal_time() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_time()); + } + + // .HeartBeatReqMessage.MachineEnum type = 4; + if (this->_internal_type() != 0) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_type()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData HeartBeatReqMessage::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck, + HeartBeatReqMessage::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*HeartBeatReqMessage::GetClassData() const { return &_class_data_; } + +void HeartBeatReqMessage::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, + const ::PROTOBUF_NAMESPACE_ID::Message& from) { + static_cast(to)->MergeFrom( + static_cast(from)); +} + + +void HeartBeatReqMessage::MergeFrom(const HeartBeatReqMessage& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:HeartBeatReqMessage) + GOOGLE_DCHECK_NE(&from, this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (from._internal_trace_id() != 0) { + _internal_set_trace_id(from._internal_trace_id()); + } + if (from._internal_ip() != 0) { + _internal_set_ip(from._internal_ip()); + } + if (from._internal_time() != 0) { + _internal_set_time(from._internal_time()); + } + if (from._internal_type() != 0) { + _internal_set_type(from._internal_type()); + } + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void HeartBeatReqMessage::CopyFrom(const HeartBeatReqMessage& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:HeartBeatReqMessage) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool HeartBeatReqMessage::IsInitialized() const { + return true; +} + +void HeartBeatReqMessage::InternalSwap(HeartBeatReqMessage* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(HeartBeatReqMessage, type_) + + sizeof(HeartBeatReqMessage::type_) + - PROTOBUF_FIELD_OFFSET(HeartBeatReqMessage, trace_id_)>( + reinterpret_cast(&trace_id_), + reinterpret_cast(&other->trace_id_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata HeartBeatReqMessage::GetMetadata() const { + return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors( + &descriptor_table_proto_2fheartbeat_2eproto_getter, &descriptor_table_proto_2fheartbeat_2eproto_once, + file_level_metadata_proto_2fheartbeat_2eproto[0]); +} + +// =================================================================== + +class HeartBeatRspMessage::_Internal { + public: +}; + +HeartBeatRspMessage::HeartBeatRspMessage(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(); + if (!is_message_owned) { + RegisterArenaDtor(arena); + } + // @@protoc_insertion_point(arena_constructor:HeartBeatRspMessage) +} +HeartBeatRspMessage::HeartBeatRspMessage(const HeartBeatRspMessage& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&trace_id_, &from.trace_id_, + static_cast(reinterpret_cast(&ret_) - + reinterpret_cast(&trace_id_)) + sizeof(ret_)); + // @@protoc_insertion_point(copy_constructor:HeartBeatRspMessage) +} + +inline void HeartBeatRspMessage::SharedCtor() { +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&trace_id_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&ret_) - + reinterpret_cast(&trace_id_)) + sizeof(ret_)); +} + +HeartBeatRspMessage::~HeartBeatRspMessage() { + // @@protoc_insertion_point(destructor:HeartBeatRspMessage) + if (GetArenaForAllocation() != nullptr) return; + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +inline void HeartBeatRspMessage::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); +} + +void HeartBeatRspMessage::ArenaDtor(void* object) { + HeartBeatRspMessage* _this = reinterpret_cast< HeartBeatRspMessage* >(object); + (void)_this; +} +void HeartBeatRspMessage::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void HeartBeatRspMessage::SetCachedSize(int size) const { + _cached_size_.Set(size); +} + +void HeartBeatRspMessage::Clear() { +// @@protoc_insertion_point(message_clear_start:HeartBeatRspMessage) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + ::memset(&trace_id_, 0, static_cast( + reinterpret_cast(&ret_) - + reinterpret_cast(&trace_id_)) + sizeof(ret_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* HeartBeatRspMessage::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + switch (tag >> 3) { + // uint32 trace_id = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 8)) { + trace_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // uint32 ret = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 16)) { + ret_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* HeartBeatRspMessage::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:HeartBeatRspMessage) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // uint32 trace_id = 1; + if (this->_internal_trace_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(1, this->_internal_trace_id(), target); + } + + // uint32 ret = 2; + if (this->_internal_ret() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(2, this->_internal_ret(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:HeartBeatRspMessage) + return target; +} + +size_t HeartBeatRspMessage::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:HeartBeatRspMessage) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // uint32 trace_id = 1; + if (this->_internal_trace_id() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_trace_id()); + } + + // uint32 ret = 2; + if (this->_internal_ret() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_ret()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData HeartBeatRspMessage::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck, + HeartBeatRspMessage::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*HeartBeatRspMessage::GetClassData() const { return &_class_data_; } + +void HeartBeatRspMessage::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, + const ::PROTOBUF_NAMESPACE_ID::Message& from) { + static_cast(to)->MergeFrom( + static_cast(from)); +} + + +void HeartBeatRspMessage::MergeFrom(const HeartBeatRspMessage& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:HeartBeatRspMessage) + GOOGLE_DCHECK_NE(&from, this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (from._internal_trace_id() != 0) { + _internal_set_trace_id(from._internal_trace_id()); + } + if (from._internal_ret() != 0) { + _internal_set_ret(from._internal_ret()); + } + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void HeartBeatRspMessage::CopyFrom(const HeartBeatRspMessage& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:HeartBeatRspMessage) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool HeartBeatRspMessage::IsInitialized() const { + return true; +} + +void HeartBeatRspMessage::InternalSwap(HeartBeatRspMessage* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(HeartBeatRspMessage, ret_) + + sizeof(HeartBeatRspMessage::ret_) + - PROTOBUF_FIELD_OFFSET(HeartBeatRspMessage, trace_id_)>( + reinterpret_cast(&trace_id_), + reinterpret_cast(&other->trace_id_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata HeartBeatRspMessage::GetMetadata() const { + return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors( + &descriptor_table_proto_2fheartbeat_2eproto_getter, &descriptor_table_proto_2fheartbeat_2eproto_once, + file_level_metadata_proto_2fheartbeat_2eproto[1]); +} + +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::HeartBeatReqMessage* Arena::CreateMaybeMessage< ::HeartBeatReqMessage >(Arena* arena) { + return Arena::CreateMessageInternal< ::HeartBeatReqMessage >(arena); +} +template<> PROTOBUF_NOINLINE ::HeartBeatRspMessage* Arena::CreateMaybeMessage< ::HeartBeatRspMessage >(Arena* arena) { + return Arena::CreateMessageInternal< ::HeartBeatRspMessage >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/heartbeat.pb.h b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/heartbeat.pb.h new file mode 100755 index 0000000..83bd0c6 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/heartbeat.pb.h @@ -0,0 +1,619 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: proto/heartbeat.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_proto_2fheartbeat_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_proto_2fheartbeat_2eproto + +#include +#include + +#include +#if PROTOBUF_VERSION < 3019000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 3019001 < PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // IWYU pragma: export +#include // IWYU pragma: export +#include +#include +// @@protoc_insertion_point(includes) +#include +#define PROTOBUF_INTERNAL_EXPORT_proto_2fheartbeat_2eproto +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct TableStruct_proto_2fheartbeat_2eproto { + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[2] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; + static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; + static const uint32_t offsets[]; +}; +extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_proto_2fheartbeat_2eproto; +class HeartBeatReqMessage; +struct HeartBeatReqMessageDefaultTypeInternal; +extern HeartBeatReqMessageDefaultTypeInternal _HeartBeatReqMessage_default_instance_; +class HeartBeatRspMessage; +struct HeartBeatRspMessageDefaultTypeInternal; +extern HeartBeatRspMessageDefaultTypeInternal _HeartBeatRspMessage_default_instance_; +PROTOBUF_NAMESPACE_OPEN +template<> ::HeartBeatReqMessage* Arena::CreateMaybeMessage<::HeartBeatReqMessage>(Arena*); +template<> ::HeartBeatRspMessage* Arena::CreateMaybeMessage<::HeartBeatRspMessage>(Arena*); +PROTOBUF_NAMESPACE_CLOSE + +enum HeartBeatReqMessage_MachineEnum : int { + HeartBeatReqMessage_MachineEnum_E_PC = 0, + HeartBeatReqMessage_MachineEnum_E_IOS = 1, + HeartBeatReqMessage_MachineEnum_E_ANDRIOD = 2, + HeartBeatReqMessage_MachineEnum_HeartBeatReqMessage_MachineEnum_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits::min(), + HeartBeatReqMessage_MachineEnum_HeartBeatReqMessage_MachineEnum_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits::max() +}; +bool HeartBeatReqMessage_MachineEnum_IsValid(int value); +constexpr HeartBeatReqMessage_MachineEnum HeartBeatReqMessage_MachineEnum_MachineEnum_MIN = HeartBeatReqMessage_MachineEnum_E_PC; +constexpr HeartBeatReqMessage_MachineEnum HeartBeatReqMessage_MachineEnum_MachineEnum_MAX = HeartBeatReqMessage_MachineEnum_E_ANDRIOD; +constexpr int HeartBeatReqMessage_MachineEnum_MachineEnum_ARRAYSIZE = HeartBeatReqMessage_MachineEnum_MachineEnum_MAX + 1; + +const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* HeartBeatReqMessage_MachineEnum_descriptor(); +template +inline const std::string& HeartBeatReqMessage_MachineEnum_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function HeartBeatReqMessage_MachineEnum_Name."); + return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum( + HeartBeatReqMessage_MachineEnum_descriptor(), enum_t_value); +} +inline bool HeartBeatReqMessage_MachineEnum_Parse( + ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, HeartBeatReqMessage_MachineEnum* value) { + return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum( + HeartBeatReqMessage_MachineEnum_descriptor(), name, value); +} +// =================================================================== + +class HeartBeatReqMessage final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:HeartBeatReqMessage) */ { + public: + inline HeartBeatReqMessage() : HeartBeatReqMessage(nullptr) {} + ~HeartBeatReqMessage() override; + explicit constexpr HeartBeatReqMessage(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + HeartBeatReqMessage(const HeartBeatReqMessage& from); + HeartBeatReqMessage(HeartBeatReqMessage&& from) noexcept + : HeartBeatReqMessage() { + *this = ::std::move(from); + } + + inline HeartBeatReqMessage& operator=(const HeartBeatReqMessage& from) { + CopyFrom(from); + return *this; + } + inline HeartBeatReqMessage& operator=(HeartBeatReqMessage&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const HeartBeatReqMessage& default_instance() { + return *internal_default_instance(); + } + static inline const HeartBeatReqMessage* internal_default_instance() { + return reinterpret_cast( + &_HeartBeatReqMessage_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(HeartBeatReqMessage& a, HeartBeatReqMessage& b) { + a.Swap(&b); + } + inline void Swap(HeartBeatReqMessage* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(HeartBeatReqMessage* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + HeartBeatReqMessage* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const HeartBeatReqMessage& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom(const HeartBeatReqMessage& from); + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(HeartBeatReqMessage* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "HeartBeatReqMessage"; + } + protected: + explicit HeartBeatReqMessage(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + typedef HeartBeatReqMessage_MachineEnum MachineEnum; + static constexpr MachineEnum E_PC = + HeartBeatReqMessage_MachineEnum_E_PC; + static constexpr MachineEnum E_IOS = + HeartBeatReqMessage_MachineEnum_E_IOS; + static constexpr MachineEnum E_ANDRIOD = + HeartBeatReqMessage_MachineEnum_E_ANDRIOD; + static inline bool MachineEnum_IsValid(int value) { + return HeartBeatReqMessage_MachineEnum_IsValid(value); + } + static constexpr MachineEnum MachineEnum_MIN = + HeartBeatReqMessage_MachineEnum_MachineEnum_MIN; + static constexpr MachineEnum MachineEnum_MAX = + HeartBeatReqMessage_MachineEnum_MachineEnum_MAX; + static constexpr int MachineEnum_ARRAYSIZE = + HeartBeatReqMessage_MachineEnum_MachineEnum_ARRAYSIZE; + static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* + MachineEnum_descriptor() { + return HeartBeatReqMessage_MachineEnum_descriptor(); + } + template + static inline const std::string& MachineEnum_Name(T enum_t_value) { + static_assert(::std::is_same::value || + ::std::is_integral::value, + "Incorrect type passed to function MachineEnum_Name."); + return HeartBeatReqMessage_MachineEnum_Name(enum_t_value); + } + static inline bool MachineEnum_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name, + MachineEnum* value) { + return HeartBeatReqMessage_MachineEnum_Parse(name, value); + } + + // accessors ------------------------------------------------------- + + enum : int { + kTraceIdFieldNumber = 1, + kIpFieldNumber = 2, + kTimeFieldNumber = 3, + kTypeFieldNumber = 4, + }; + // uint32 trace_id = 1; + void clear_trace_id(); + uint32_t trace_id() const; + void set_trace_id(uint32_t value); + private: + uint32_t _internal_trace_id() const; + void _internal_set_trace_id(uint32_t value); + public: + + // uint32 ip = 2; + void clear_ip(); + uint32_t ip() const; + void set_ip(uint32_t value); + private: + uint32_t _internal_ip() const; + void _internal_set_ip(uint32_t value); + public: + + // uint32 time = 3; + void clear_time(); + uint32_t time() const; + void set_time(uint32_t value); + private: + uint32_t _internal_time() const; + void _internal_set_time(uint32_t value); + public: + + // .HeartBeatReqMessage.MachineEnum type = 4; + void clear_type(); + ::HeartBeatReqMessage_MachineEnum type() const; + void set_type(::HeartBeatReqMessage_MachineEnum value); + private: + ::HeartBeatReqMessage_MachineEnum _internal_type() const; + void _internal_set_type(::HeartBeatReqMessage_MachineEnum value); + public: + + // @@protoc_insertion_point(class_scope:HeartBeatReqMessage) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + uint32_t trace_id_; + uint32_t ip_; + uint32_t time_; + int type_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_proto_2fheartbeat_2eproto; +}; +// ------------------------------------------------------------------- + +class HeartBeatRspMessage final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:HeartBeatRspMessage) */ { + public: + inline HeartBeatRspMessage() : HeartBeatRspMessage(nullptr) {} + ~HeartBeatRspMessage() override; + explicit constexpr HeartBeatRspMessage(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + HeartBeatRspMessage(const HeartBeatRspMessage& from); + HeartBeatRspMessage(HeartBeatRspMessage&& from) noexcept + : HeartBeatRspMessage() { + *this = ::std::move(from); + } + + inline HeartBeatRspMessage& operator=(const HeartBeatRspMessage& from) { + CopyFrom(from); + return *this; + } + inline HeartBeatRspMessage& operator=(HeartBeatRspMessage&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const HeartBeatRspMessage& default_instance() { + return *internal_default_instance(); + } + static inline const HeartBeatRspMessage* internal_default_instance() { + return reinterpret_cast( + &_HeartBeatRspMessage_default_instance_); + } + static constexpr int kIndexInFileMessages = + 1; + + friend void swap(HeartBeatRspMessage& a, HeartBeatRspMessage& b) { + a.Swap(&b); + } + inline void Swap(HeartBeatRspMessage* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(HeartBeatRspMessage* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + HeartBeatRspMessage* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const HeartBeatRspMessage& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom(const HeartBeatRspMessage& from); + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(HeartBeatRspMessage* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "HeartBeatRspMessage"; + } + protected: + explicit HeartBeatRspMessage(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kTraceIdFieldNumber = 1, + kRetFieldNumber = 2, + }; + // uint32 trace_id = 1; + void clear_trace_id(); + uint32_t trace_id() const; + void set_trace_id(uint32_t value); + private: + uint32_t _internal_trace_id() const; + void _internal_set_trace_id(uint32_t value); + public: + + // uint32 ret = 2; + void clear_ret(); + uint32_t ret() const; + void set_ret(uint32_t value); + private: + uint32_t _internal_ret() const; + void _internal_set_ret(uint32_t value); + public: + + // @@protoc_insertion_point(class_scope:HeartBeatRspMessage) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + uint32_t trace_id_; + uint32_t ret_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_proto_2fheartbeat_2eproto; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// HeartBeatReqMessage + +// uint32 trace_id = 1; +inline void HeartBeatReqMessage::clear_trace_id() { + trace_id_ = 0u; +} +inline uint32_t HeartBeatReqMessage::_internal_trace_id() const { + return trace_id_; +} +inline uint32_t HeartBeatReqMessage::trace_id() const { + // @@protoc_insertion_point(field_get:HeartBeatReqMessage.trace_id) + return _internal_trace_id(); +} +inline void HeartBeatReqMessage::_internal_set_trace_id(uint32_t value) { + + trace_id_ = value; +} +inline void HeartBeatReqMessage::set_trace_id(uint32_t value) { + _internal_set_trace_id(value); + // @@protoc_insertion_point(field_set:HeartBeatReqMessage.trace_id) +} + +// uint32 ip = 2; +inline void HeartBeatReqMessage::clear_ip() { + ip_ = 0u; +} +inline uint32_t HeartBeatReqMessage::_internal_ip() const { + return ip_; +} +inline uint32_t HeartBeatReqMessage::ip() const { + // @@protoc_insertion_point(field_get:HeartBeatReqMessage.ip) + return _internal_ip(); +} +inline void HeartBeatReqMessage::_internal_set_ip(uint32_t value) { + + ip_ = value; +} +inline void HeartBeatReqMessage::set_ip(uint32_t value) { + _internal_set_ip(value); + // @@protoc_insertion_point(field_set:HeartBeatReqMessage.ip) +} + +// uint32 time = 3; +inline void HeartBeatReqMessage::clear_time() { + time_ = 0u; +} +inline uint32_t HeartBeatReqMessage::_internal_time() const { + return time_; +} +inline uint32_t HeartBeatReqMessage::time() const { + // @@protoc_insertion_point(field_get:HeartBeatReqMessage.time) + return _internal_time(); +} +inline void HeartBeatReqMessage::_internal_set_time(uint32_t value) { + + time_ = value; +} +inline void HeartBeatReqMessage::set_time(uint32_t value) { + _internal_set_time(value); + // @@protoc_insertion_point(field_set:HeartBeatReqMessage.time) +} + +// .HeartBeatReqMessage.MachineEnum type = 4; +inline void HeartBeatReqMessage::clear_type() { + type_ = 0; +} +inline ::HeartBeatReqMessage_MachineEnum HeartBeatReqMessage::_internal_type() const { + return static_cast< ::HeartBeatReqMessage_MachineEnum >(type_); +} +inline ::HeartBeatReqMessage_MachineEnum HeartBeatReqMessage::type() const { + // @@protoc_insertion_point(field_get:HeartBeatReqMessage.type) + return _internal_type(); +} +inline void HeartBeatReqMessage::_internal_set_type(::HeartBeatReqMessage_MachineEnum value) { + + type_ = value; +} +inline void HeartBeatReqMessage::set_type(::HeartBeatReqMessage_MachineEnum value) { + _internal_set_type(value); + // @@protoc_insertion_point(field_set:HeartBeatReqMessage.type) +} + +// ------------------------------------------------------------------- + +// HeartBeatRspMessage + +// uint32 trace_id = 1; +inline void HeartBeatRspMessage::clear_trace_id() { + trace_id_ = 0u; +} +inline uint32_t HeartBeatRspMessage::_internal_trace_id() const { + return trace_id_; +} +inline uint32_t HeartBeatRspMessage::trace_id() const { + // @@protoc_insertion_point(field_get:HeartBeatRspMessage.trace_id) + return _internal_trace_id(); +} +inline void HeartBeatRspMessage::_internal_set_trace_id(uint32_t value) { + + trace_id_ = value; +} +inline void HeartBeatRspMessage::set_trace_id(uint32_t value) { + _internal_set_trace_id(value); + // @@protoc_insertion_point(field_set:HeartBeatRspMessage.trace_id) +} + +// uint32 ret = 2; +inline void HeartBeatRspMessage::clear_ret() { + ret_ = 0u; +} +inline uint32_t HeartBeatRspMessage::_internal_ret() const { + return ret_; +} +inline uint32_t HeartBeatRspMessage::ret() const { + // @@protoc_insertion_point(field_get:HeartBeatRspMessage.ret) + return _internal_ret(); +} +inline void HeartBeatRspMessage::_internal_set_ret(uint32_t value) { + + ret_ = value; +} +inline void HeartBeatRspMessage::set_ret(uint32_t value) { + _internal_set_ret(value); + // @@protoc_insertion_point(field_set:HeartBeatRspMessage.ret) +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ +// ------------------------------------------------------------------- + + +// @@protoc_insertion_point(namespace_scope) + + +PROTOBUF_NAMESPACE_OPEN + +template <> struct is_proto_enum< ::HeartBeatReqMessage_MachineEnum> : ::std::true_type {}; +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::HeartBeatReqMessage_MachineEnum>() { + return ::HeartBeatReqMessage_MachineEnum_descriptor(); +} + +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) + +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_proto_2fheartbeat_2eproto diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/machine.pb.cc b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/machine.pb.cc new file mode 100755 index 0000000..b60b84b --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/machine.pb.cc @@ -0,0 +1,576 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: proto/machine.proto + +#include "proto/machine.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) +#include + +PROTOBUF_PRAGMA_INIT_SEG +constexpr InfoMessage::InfoMessage( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : ip_(0u) + , time_(0u){} +struct InfoMessageDefaultTypeInternal { + constexpr InfoMessageDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~InfoMessageDefaultTypeInternal() {} + union { + InfoMessage _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT InfoMessageDefaultTypeInternal _InfoMessage_default_instance_; +constexpr MachineInfoMessage::MachineInfoMessage( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : info_(nullptr) + , trace_id_(0u) + , type_(0u){} +struct MachineInfoMessageDefaultTypeInternal { + constexpr MachineInfoMessageDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~MachineInfoMessageDefaultTypeInternal() {} + union { + MachineInfoMessage _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT MachineInfoMessageDefaultTypeInternal _MachineInfoMessage_default_instance_; +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_proto_2fmachine_2eproto[2]; +static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_proto_2fmachine_2eproto = nullptr; +static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_proto_2fmachine_2eproto = nullptr; + +const uint32_t TableStruct_proto_2fmachine_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::InfoMessage, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::InfoMessage, ip_), + PROTOBUF_FIELD_OFFSET(::InfoMessage, time_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::MachineInfoMessage, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::MachineInfoMessage, trace_id_), + PROTOBUF_FIELD_OFFSET(::MachineInfoMessage, info_), + PROTOBUF_FIELD_OFFSET(::MachineInfoMessage, type_), +}; +static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, -1, sizeof(::InfoMessage)}, + { 8, -1, -1, sizeof(::MachineInfoMessage)}, +}; + +static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { + reinterpret_cast(&::_InfoMessage_default_instance_), + reinterpret_cast(&::_MachineInfoMessage_default_instance_), +}; + +const char descriptor_table_protodef_proto_2fmachine_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\023proto/machine.proto\"\'\n\013InfoMessage\022\n\n\002" + "ip\030\001 \001(\r\022\014\n\004time\030\002 \001(\r\"P\n\022MachineInfoMes" + "sage\022\020\n\010trace_id\030\001 \001(\r\022\032\n\004info\030\002 \001(\0132\014.I" + "nfoMessage\022\014\n\004type\030\003 \001(\rB\014Z\n.;protocolb\006" + "proto3" + ; +static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_proto_2fmachine_2eproto_once; +const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_proto_2fmachine_2eproto = { + false, false, 166, descriptor_table_protodef_proto_2fmachine_2eproto, "proto/machine.proto", + &descriptor_table_proto_2fmachine_2eproto_once, nullptr, 0, 2, + schemas, file_default_instances, TableStruct_proto_2fmachine_2eproto::offsets, + file_level_metadata_proto_2fmachine_2eproto, file_level_enum_descriptors_proto_2fmachine_2eproto, file_level_service_descriptors_proto_2fmachine_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_proto_2fmachine_2eproto_getter() { + return &descriptor_table_proto_2fmachine_2eproto; +} + +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_proto_2fmachine_2eproto(&descriptor_table_proto_2fmachine_2eproto); + +// =================================================================== + +class InfoMessage::_Internal { + public: +}; + +InfoMessage::InfoMessage(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(); + if (!is_message_owned) { + RegisterArenaDtor(arena); + } + // @@protoc_insertion_point(arena_constructor:InfoMessage) +} +InfoMessage::InfoMessage(const InfoMessage& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&ip_, &from.ip_, + static_cast(reinterpret_cast(&time_) - + reinterpret_cast(&ip_)) + sizeof(time_)); + // @@protoc_insertion_point(copy_constructor:InfoMessage) +} + +inline void InfoMessage::SharedCtor() { +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&ip_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&time_) - + reinterpret_cast(&ip_)) + sizeof(time_)); +} + +InfoMessage::~InfoMessage() { + // @@protoc_insertion_point(destructor:InfoMessage) + if (GetArenaForAllocation() != nullptr) return; + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +inline void InfoMessage::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); +} + +void InfoMessage::ArenaDtor(void* object) { + InfoMessage* _this = reinterpret_cast< InfoMessage* >(object); + (void)_this; +} +void InfoMessage::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void InfoMessage::SetCachedSize(int size) const { + _cached_size_.Set(size); +} + +void InfoMessage::Clear() { +// @@protoc_insertion_point(message_clear_start:InfoMessage) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + ::memset(&ip_, 0, static_cast( + reinterpret_cast(&time_) - + reinterpret_cast(&ip_)) + sizeof(time_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* InfoMessage::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + switch (tag >> 3) { + // uint32 ip = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 8)) { + ip_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // uint32 time = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 16)) { + time_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* InfoMessage::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:InfoMessage) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // uint32 ip = 1; + if (this->_internal_ip() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(1, this->_internal_ip(), target); + } + + // uint32 time = 2; + if (this->_internal_time() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(2, this->_internal_time(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:InfoMessage) + return target; +} + +size_t InfoMessage::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:InfoMessage) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // uint32 ip = 1; + if (this->_internal_ip() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_ip()); + } + + // uint32 time = 2; + if (this->_internal_time() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_time()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData InfoMessage::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck, + InfoMessage::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*InfoMessage::GetClassData() const { return &_class_data_; } + +void InfoMessage::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, + const ::PROTOBUF_NAMESPACE_ID::Message& from) { + static_cast(to)->MergeFrom( + static_cast(from)); +} + + +void InfoMessage::MergeFrom(const InfoMessage& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:InfoMessage) + GOOGLE_DCHECK_NE(&from, this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (from._internal_ip() != 0) { + _internal_set_ip(from._internal_ip()); + } + if (from._internal_time() != 0) { + _internal_set_time(from._internal_time()); + } + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void InfoMessage::CopyFrom(const InfoMessage& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:InfoMessage) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool InfoMessage::IsInitialized() const { + return true; +} + +void InfoMessage::InternalSwap(InfoMessage* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(InfoMessage, time_) + + sizeof(InfoMessage::time_) + - PROTOBUF_FIELD_OFFSET(InfoMessage, ip_)>( + reinterpret_cast(&ip_), + reinterpret_cast(&other->ip_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata InfoMessage::GetMetadata() const { + return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors( + &descriptor_table_proto_2fmachine_2eproto_getter, &descriptor_table_proto_2fmachine_2eproto_once, + file_level_metadata_proto_2fmachine_2eproto[0]); +} + +// =================================================================== + +class MachineInfoMessage::_Internal { + public: + static const ::InfoMessage& info(const MachineInfoMessage* msg); +}; + +const ::InfoMessage& +MachineInfoMessage::_Internal::info(const MachineInfoMessage* msg) { + return *msg->info_; +} +MachineInfoMessage::MachineInfoMessage(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(); + if (!is_message_owned) { + RegisterArenaDtor(arena); + } + // @@protoc_insertion_point(arena_constructor:MachineInfoMessage) +} +MachineInfoMessage::MachineInfoMessage(const MachineInfoMessage& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + if (from._internal_has_info()) { + info_ = new ::InfoMessage(*from.info_); + } else { + info_ = nullptr; + } + ::memcpy(&trace_id_, &from.trace_id_, + static_cast(reinterpret_cast(&type_) - + reinterpret_cast(&trace_id_)) + sizeof(type_)); + // @@protoc_insertion_point(copy_constructor:MachineInfoMessage) +} + +inline void MachineInfoMessage::SharedCtor() { +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&info_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&type_) - + reinterpret_cast(&info_)) + sizeof(type_)); +} + +MachineInfoMessage::~MachineInfoMessage() { + // @@protoc_insertion_point(destructor:MachineInfoMessage) + if (GetArenaForAllocation() != nullptr) return; + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +inline void MachineInfoMessage::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + if (this != internal_default_instance()) delete info_; +} + +void MachineInfoMessage::ArenaDtor(void* object) { + MachineInfoMessage* _this = reinterpret_cast< MachineInfoMessage* >(object); + (void)_this; +} +void MachineInfoMessage::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void MachineInfoMessage::SetCachedSize(int size) const { + _cached_size_.Set(size); +} + +void MachineInfoMessage::Clear() { +// @@protoc_insertion_point(message_clear_start:MachineInfoMessage) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + if (GetArenaForAllocation() == nullptr && info_ != nullptr) { + delete info_; + } + info_ = nullptr; + ::memset(&trace_id_, 0, static_cast( + reinterpret_cast(&type_) - + reinterpret_cast(&trace_id_)) + sizeof(type_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* MachineInfoMessage::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + switch (tag >> 3) { + // uint32 trace_id = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 8)) { + trace_id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // .InfoMessage info = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 18)) { + ptr = ctx->ParseMessage(_internal_mutable_info(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // uint32 type = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 24)) { + type_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* MachineInfoMessage::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:MachineInfoMessage) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // uint32 trace_id = 1; + if (this->_internal_trace_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(1, this->_internal_trace_id(), target); + } + + // .InfoMessage info = 2; + if (this->_internal_has_info()) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage( + 2, _Internal::info(this), target, stream); + } + + // uint32 type = 3; + if (this->_internal_type() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(3, this->_internal_type(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:MachineInfoMessage) + return target; +} + +size_t MachineInfoMessage::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:MachineInfoMessage) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // .InfoMessage info = 2; + if (this->_internal_has_info()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *info_); + } + + // uint32 trace_id = 1; + if (this->_internal_trace_id() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_trace_id()); + } + + // uint32 type = 3; + if (this->_internal_type() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_type()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData MachineInfoMessage::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck, + MachineInfoMessage::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*MachineInfoMessage::GetClassData() const { return &_class_data_; } + +void MachineInfoMessage::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, + const ::PROTOBUF_NAMESPACE_ID::Message& from) { + static_cast(to)->MergeFrom( + static_cast(from)); +} + + +void MachineInfoMessage::MergeFrom(const MachineInfoMessage& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:MachineInfoMessage) + GOOGLE_DCHECK_NE(&from, this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (from._internal_has_info()) { + _internal_mutable_info()->::InfoMessage::MergeFrom(from._internal_info()); + } + if (from._internal_trace_id() != 0) { + _internal_set_trace_id(from._internal_trace_id()); + } + if (from._internal_type() != 0) { + _internal_set_type(from._internal_type()); + } + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void MachineInfoMessage::CopyFrom(const MachineInfoMessage& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:MachineInfoMessage) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool MachineInfoMessage::IsInitialized() const { + return true; +} + +void MachineInfoMessage::InternalSwap(MachineInfoMessage* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(MachineInfoMessage, type_) + + sizeof(MachineInfoMessage::type_) + - PROTOBUF_FIELD_OFFSET(MachineInfoMessage, info_)>( + reinterpret_cast(&info_), + reinterpret_cast(&other->info_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata MachineInfoMessage::GetMetadata() const { + return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors( + &descriptor_table_proto_2fmachine_2eproto_getter, &descriptor_table_proto_2fmachine_2eproto_once, + file_level_metadata_proto_2fmachine_2eproto[1]); +} + +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::InfoMessage* Arena::CreateMaybeMessage< ::InfoMessage >(Arena* arena) { + return Arena::CreateMessageInternal< ::InfoMessage >(arena); +} +template<> PROTOBUF_NOINLINE ::MachineInfoMessage* Arena::CreateMaybeMessage< ::MachineInfoMessage >(Arena* arena) { + return Arena::CreateMessageInternal< ::MachineInfoMessage >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/machine.pb.h b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/machine.pb.h new file mode 100755 index 0000000..aeccedb --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/proto/machine.pb.h @@ -0,0 +1,598 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: proto/machine.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_proto_2fmachine_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_proto_2fmachine_2eproto + +#include +#include + +#include +#if PROTOBUF_VERSION < 3019000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 3019001 < PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // IWYU pragma: export +#include // IWYU pragma: export +#include +// @@protoc_insertion_point(includes) +#include +#define PROTOBUF_INTERNAL_EXPORT_proto_2fmachine_2eproto +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct TableStruct_proto_2fmachine_2eproto { + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[2] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; + static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; + static const uint32_t offsets[]; +}; +extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_proto_2fmachine_2eproto; +class InfoMessage; +struct InfoMessageDefaultTypeInternal; +extern InfoMessageDefaultTypeInternal _InfoMessage_default_instance_; +class MachineInfoMessage; +struct MachineInfoMessageDefaultTypeInternal; +extern MachineInfoMessageDefaultTypeInternal _MachineInfoMessage_default_instance_; +PROTOBUF_NAMESPACE_OPEN +template<> ::InfoMessage* Arena::CreateMaybeMessage<::InfoMessage>(Arena*); +template<> ::MachineInfoMessage* Arena::CreateMaybeMessage<::MachineInfoMessage>(Arena*); +PROTOBUF_NAMESPACE_CLOSE + +// =================================================================== + +class InfoMessage final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:InfoMessage) */ { + public: + inline InfoMessage() : InfoMessage(nullptr) {} + ~InfoMessage() override; + explicit constexpr InfoMessage(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + InfoMessage(const InfoMessage& from); + InfoMessage(InfoMessage&& from) noexcept + : InfoMessage() { + *this = ::std::move(from); + } + + inline InfoMessage& operator=(const InfoMessage& from) { + CopyFrom(from); + return *this; + } + inline InfoMessage& operator=(InfoMessage&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const InfoMessage& default_instance() { + return *internal_default_instance(); + } + static inline const InfoMessage* internal_default_instance() { + return reinterpret_cast( + &_InfoMessage_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(InfoMessage& a, InfoMessage& b) { + a.Swap(&b); + } + inline void Swap(InfoMessage* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(InfoMessage* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + InfoMessage* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const InfoMessage& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom(const InfoMessage& from); + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(InfoMessage* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "InfoMessage"; + } + protected: + explicit InfoMessage(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kIpFieldNumber = 1, + kTimeFieldNumber = 2, + }; + // uint32 ip = 1; + void clear_ip(); + uint32_t ip() const; + void set_ip(uint32_t value); + private: + uint32_t _internal_ip() const; + void _internal_set_ip(uint32_t value); + public: + + // uint32 time = 2; + void clear_time(); + uint32_t time() const; + void set_time(uint32_t value); + private: + uint32_t _internal_time() const; + void _internal_set_time(uint32_t value); + public: + + // @@protoc_insertion_point(class_scope:InfoMessage) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + uint32_t ip_; + uint32_t time_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_proto_2fmachine_2eproto; +}; +// ------------------------------------------------------------------- + +class MachineInfoMessage final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:MachineInfoMessage) */ { + public: + inline MachineInfoMessage() : MachineInfoMessage(nullptr) {} + ~MachineInfoMessage() override; + explicit constexpr MachineInfoMessage(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + MachineInfoMessage(const MachineInfoMessage& from); + MachineInfoMessage(MachineInfoMessage&& from) noexcept + : MachineInfoMessage() { + *this = ::std::move(from); + } + + inline MachineInfoMessage& operator=(const MachineInfoMessage& from) { + CopyFrom(from); + return *this; + } + inline MachineInfoMessage& operator=(MachineInfoMessage&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const MachineInfoMessage& default_instance() { + return *internal_default_instance(); + } + static inline const MachineInfoMessage* internal_default_instance() { + return reinterpret_cast( + &_MachineInfoMessage_default_instance_); + } + static constexpr int kIndexInFileMessages = + 1; + + friend void swap(MachineInfoMessage& a, MachineInfoMessage& b) { + a.Swap(&b); + } + inline void Swap(MachineInfoMessage* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(MachineInfoMessage* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + MachineInfoMessage* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const MachineInfoMessage& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom(const MachineInfoMessage& from); + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(MachineInfoMessage* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "MachineInfoMessage"; + } + protected: + explicit MachineInfoMessage(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kInfoFieldNumber = 2, + kTraceIdFieldNumber = 1, + kTypeFieldNumber = 3, + }; + // .InfoMessage info = 2; + bool has_info() const; + private: + bool _internal_has_info() const; + public: + void clear_info(); + const ::InfoMessage& info() const; + PROTOBUF_NODISCARD ::InfoMessage* release_info(); + ::InfoMessage* mutable_info(); + void set_allocated_info(::InfoMessage* info); + private: + const ::InfoMessage& _internal_info() const; + ::InfoMessage* _internal_mutable_info(); + public: + void unsafe_arena_set_allocated_info( + ::InfoMessage* info); + ::InfoMessage* unsafe_arena_release_info(); + + // uint32 trace_id = 1; + void clear_trace_id(); + uint32_t trace_id() const; + void set_trace_id(uint32_t value); + private: + uint32_t _internal_trace_id() const; + void _internal_set_trace_id(uint32_t value); + public: + + // uint32 type = 3; + void clear_type(); + uint32_t type() const; + void set_type(uint32_t value); + private: + uint32_t _internal_type() const; + void _internal_set_type(uint32_t value); + public: + + // @@protoc_insertion_point(class_scope:MachineInfoMessage) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::InfoMessage* info_; + uint32_t trace_id_; + uint32_t type_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_proto_2fmachine_2eproto; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// InfoMessage + +// uint32 ip = 1; +inline void InfoMessage::clear_ip() { + ip_ = 0u; +} +inline uint32_t InfoMessage::_internal_ip() const { + return ip_; +} +inline uint32_t InfoMessage::ip() const { + // @@protoc_insertion_point(field_get:InfoMessage.ip) + return _internal_ip(); +} +inline void InfoMessage::_internal_set_ip(uint32_t value) { + + ip_ = value; +} +inline void InfoMessage::set_ip(uint32_t value) { + _internal_set_ip(value); + // @@protoc_insertion_point(field_set:InfoMessage.ip) +} + +// uint32 time = 2; +inline void InfoMessage::clear_time() { + time_ = 0u; +} +inline uint32_t InfoMessage::_internal_time() const { + return time_; +} +inline uint32_t InfoMessage::time() const { + // @@protoc_insertion_point(field_get:InfoMessage.time) + return _internal_time(); +} +inline void InfoMessage::_internal_set_time(uint32_t value) { + + time_ = value; +} +inline void InfoMessage::set_time(uint32_t value) { + _internal_set_time(value); + // @@protoc_insertion_point(field_set:InfoMessage.time) +} + +// ------------------------------------------------------------------- + +// MachineInfoMessage + +// uint32 trace_id = 1; +inline void MachineInfoMessage::clear_trace_id() { + trace_id_ = 0u; +} +inline uint32_t MachineInfoMessage::_internal_trace_id() const { + return trace_id_; +} +inline uint32_t MachineInfoMessage::trace_id() const { + // @@protoc_insertion_point(field_get:MachineInfoMessage.trace_id) + return _internal_trace_id(); +} +inline void MachineInfoMessage::_internal_set_trace_id(uint32_t value) { + + trace_id_ = value; +} +inline void MachineInfoMessage::set_trace_id(uint32_t value) { + _internal_set_trace_id(value); + // @@protoc_insertion_point(field_set:MachineInfoMessage.trace_id) +} + +// .InfoMessage info = 2; +inline bool MachineInfoMessage::_internal_has_info() const { + return this != internal_default_instance() && info_ != nullptr; +} +inline bool MachineInfoMessage::has_info() const { + return _internal_has_info(); +} +inline void MachineInfoMessage::clear_info() { + if (GetArenaForAllocation() == nullptr && info_ != nullptr) { + delete info_; + } + info_ = nullptr; +} +inline const ::InfoMessage& MachineInfoMessage::_internal_info() const { + const ::InfoMessage* p = info_; + return p != nullptr ? *p : reinterpret_cast( + ::_InfoMessage_default_instance_); +} +inline const ::InfoMessage& MachineInfoMessage::info() const { + // @@protoc_insertion_point(field_get:MachineInfoMessage.info) + return _internal_info(); +} +inline void MachineInfoMessage::unsafe_arena_set_allocated_info( + ::InfoMessage* info) { + if (GetArenaForAllocation() == nullptr) { + delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(info_); + } + info_ = info; + if (info) { + + } else { + + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:MachineInfoMessage.info) +} +inline ::InfoMessage* MachineInfoMessage::release_info() { + + ::InfoMessage* temp = info_; + info_ = nullptr; +#ifdef PROTOBUF_FORCE_COPY_IN_RELEASE + auto* old = reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(temp); + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + if (GetArenaForAllocation() == nullptr) { delete old; } +#else // PROTOBUF_FORCE_COPY_IN_RELEASE + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } +#endif // !PROTOBUF_FORCE_COPY_IN_RELEASE + return temp; +} +inline ::InfoMessage* MachineInfoMessage::unsafe_arena_release_info() { + // @@protoc_insertion_point(field_release:MachineInfoMessage.info) + + ::InfoMessage* temp = info_; + info_ = nullptr; + return temp; +} +inline ::InfoMessage* MachineInfoMessage::_internal_mutable_info() { + + if (info_ == nullptr) { + auto* p = CreateMaybeMessage<::InfoMessage>(GetArenaForAllocation()); + info_ = p; + } + return info_; +} +inline ::InfoMessage* MachineInfoMessage::mutable_info() { + ::InfoMessage* _msg = _internal_mutable_info(); + // @@protoc_insertion_point(field_mutable:MachineInfoMessage.info) + return _msg; +} +inline void MachineInfoMessage::set_allocated_info(::InfoMessage* info) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + if (message_arena == nullptr) { + delete info_; + } + if (info) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper<::InfoMessage>::GetOwningArena(info); + if (message_arena != submessage_arena) { + info = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, info, submessage_arena); + } + + } else { + + } + info_ = info; + // @@protoc_insertion_point(field_set_allocated:MachineInfoMessage.info) +} + +// uint32 type = 3; +inline void MachineInfoMessage::clear_type() { + type_ = 0u; +} +inline uint32_t MachineInfoMessage::_internal_type() const { + return type_; +} +inline uint32_t MachineInfoMessage::type() const { + // @@protoc_insertion_point(field_get:MachineInfoMessage.type) + return _internal_type(); +} +inline void MachineInfoMessage::_internal_set_type(uint32_t value) { + + type_ = value; +} +inline void MachineInfoMessage::set_type(uint32_t value) { + _internal_set_type(value); + // @@protoc_insertion_point(field_set:MachineInfoMessage.type) +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ +// ------------------------------------------------------------------- + + +// @@protoc_insertion_point(namespace_scope) + + +// @@protoc_insertion_point(global_scope) + +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_proto_2fmachine_2eproto diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/test_main b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/test_main new file mode 100755 index 0000000..1be3e9a Binary files /dev/null and b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/test_main differ diff --git a/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/test_main.cpp b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/test_main.cpp new file mode 100755 index 0000000..a6e5e82 --- /dev/null +++ b/example_code/pb_demo/protoc-gen/protoc-gen-pod/out/test_main.cpp @@ -0,0 +1,95 @@ +#include +#include +#include "demo.pb.h" +#include "demo.h" +#include "heartbeat.h" +#include "heartbeat.pb.h" +#include "machine.h" + +using namespace std; + +int main() +{ + { + UserMsg pb; + PODUserMsg pod; + pod.clear(); + pod.id = 1; + pod.age = 2; + + pod.pod2pb(&pb); + assert(pb.id() == pod.id); + assert(pb.age() == pod.age); + + pod.clear(); + pod.pb2pod(pb); + assert(pb.id() == pod.id); + assert(pb.age() == pod.age); + } + + { + PODHeartBeatReqMessage pod; + HeartBeatReqMessage pb; + pod.clear(); + pod.trace_id = 123; + pod.ip = 456; + pod.time = 789; + pod.type = HeartBeatReqMessage_MachineEnum::HeartBeatReqMessage_MachineEnum_E_IOS; + + pod.pod2pb(&pb); + assert(pb.trace_id() == pod.trace_id); + assert(pb.ip() == pod.ip); + assert(pb.time() == pod.time); + assert(pb.type() == pod.type); + + pod.clear(); + pod.pb2pod(pb); + assert(pb.trace_id() == pod.trace_id); + assert(pb.ip() == pod.ip); + assert(pb.time() == pod.time); + assert(pb.type() == pod.type); + } + + { + PODMachineInfoMessage pod; + MachineInfoMessage pb; + pod.clear(); + pod.trace_id = 123; + pod.info.ip = 456; + pod.info.time = 789; + pod.type = 1000; + + pod.pod2pb(&pb); + assert(pb.trace_id() == pod.trace_id); + assert(pb.info().ip() == pod.info.ip); + assert(pb.info().time() == pod.info.time); + assert(pb.type() == pod.type); + } + + { + PODFamilyMsg pod; + FamilyMsg pb; + pod.clear(); + pod.familys[0].id = 100; + pod.familys[0].age = 123; + pod.familys[1].id = 200; + pod.familys[2].age = 456; + + // rt to pb + pod.pod2pb(&pb); + assert(pb.familys(0).age() == pod.familys[0].age); + assert(pb.familys(0).id() == pod.familys[0].id); + assert(pb.familys(1).age() == pod.familys[1].age); + assert(pb.familys(1).id() == pod.familys[1].id); + + // pb to rt + pod.clear(); + pod.pb2pod(pb); + assert(pb.familys(0).age() == pod.familys[0].age); + assert(pb.familys(0).id() == pod.familys[0].id); + assert(pb.familys(1).age() == pod.familys[1].age); + assert(pb.familys(1).id() == pod.familys[1].id); + } + cout << "pass" < +#include +#include + +using namespace std; +using namespace heartbeat; + +void traceMsg(const HeartBeatMessage &msg) +{ + cout << msg.datetime() << endl; + cout << msg.hostname() << endl; + cout << msg.ip() << endl; + cout << msg.info() << endl; + cout << msg.info2() << endl; + cout << msg.info3() << endl; + + cout <<"========"<FindFieldByName(name); + assert(fdes != nullptr); + const google::protobuf::Reflection* ref = hb_msg.GetReflection(); + cout << ref->GetString(hb_msg, fdes) << endl; + return 0; +} + +int main(void) +{ + HeartBeatMessage msg; + + fstream input("./heartbeat.db",ios::in|ios::binary); + + if(!msg.ParseFromIstream(&input)) + { + cerr << "read data from file error." << endl; + return -1; + } + traceMsg(msg); + get_feature(msg, "hostName"); + return 0; +} \ No newline at end of file diff --git a/example_code/pb_demo/readme.md b/example_code/pb_demo/readme.md new file mode 100755 index 0000000..5475f9b --- /dev/null +++ b/example_code/pb_demo/readme.md @@ -0,0 +1,3 @@ +### protobuff 序列化、反序列化 + +https://www.jianshu.com/p/131f0bf218ef \ No newline at end of file diff --git a/example_code/pb_demo/reflect/demo1/Makefile b/example_code/pb_demo/reflect/demo1/Makefile new file mode 100755 index 0000000..047a939 --- /dev/null +++ b/example_code/pb_demo/reflect/demo1/Makefile @@ -0,0 +1,13 @@ +.PHONY: all proto clean run + +all: + g++ main.cpp ./out/person.pb.cc -o main -I./out -lprotobuf -lpthread -L/usr/local/lib -g + +proto: + protoc --cpp_out=./out *.proto + +run: + ./main + +clean: + rm main \ No newline at end of file diff --git a/example_code/pb_demo/reflect/demo1/build.sh b/example_code/pb_demo/reflect/demo1/build.sh new file mode 100755 index 0000000..4e848a0 --- /dev/null +++ b/example_code/pb_demo/reflect/demo1/build.sh @@ -0,0 +1 @@ +g++ main.cpp \ No newline at end of file diff --git a/example_code/pb_demo/reflect/demo1/main b/example_code/pb_demo/reflect/demo1/main new file mode 100755 index 0000000..53d9b49 Binary files /dev/null and b/example_code/pb_demo/reflect/demo1/main differ diff --git a/example_code/pb_demo/reflect/demo1/main.cpp b/example_code/pb_demo/reflect/demo1/main.cpp new file mode 100755 index 0000000..7cae0f1 --- /dev/null +++ b/example_code/pb_demo/reflect/demo1/main.cpp @@ -0,0 +1,393 @@ +#include +#include +#include +#include +#include "person.pb.h" + +using namespace std; + +int pb_fill_message(std::queue& args, google::protobuf::Message* msg); + +int print_pb_message(const google::protobuf::Message & message) +{ + const google::protobuf::Descriptor* pDescriptor = message.GetDescriptor(); + int count = pDescriptor->field_count(); + cout << "field count : " << count << " message : " + << pDescriptor->name() << " file desc" << pDescriptor->file()<< endl; + + for (int i = 0; i < count; i++) + { + const google::protobuf::FieldDescriptor * pFieldDesc = pDescriptor->field(i); + cout << "field index : " << i << ", field name :" << pFieldDesc->name() + << ", field type : " << pFieldDesc->cpp_type() << ", is repeated : " + << pFieldDesc->is_repeated() << ", number : " << pFieldDesc->number() << endl; + + // option + pFieldDesc->options(); + } + cout << message.DebugString() << endl; + return 0; +} + +// reflect +int fill_pb_message(google::protobuf::Message & message) +{ + const google::protobuf::Reflection* pReflection = message.GetReflection(); + + const google::protobuf::Descriptor* pDescriptor = message.GetDescriptor(); + int count = pDescriptor->field_count(); + + for (int i = 0; i < count; i++) + { + const google::protobuf::FieldDescriptor * field = pDescriptor->field(i); + bool has_field = pReflection->HasField(message, field); + if (has_field) + { + if (field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_UINT32) + { + cout << pReflection->GetUInt32(message, field) << endl; + + // 利用反射填充对象 + int field_value = 666; + pReflection->SetUInt32(&message, field, field_value); + } + } + } + return 0; +} + +int PbToMap(const google::protobuf::Message &message, + std::map &out) +{ + #define CASE_FIELD_TYPE(cpptype, method, valuetype) \ + case google::protobuf::FieldDescriptor::CPPTYPE_##cpptype: { \ + valuetype value = reflection->Get##method(message, field); \ + std::ostringstream oss; \ + oss << value; \ + out[field->name()] = oss.str(); \ + break; \ + } + + #define CASE_FIELD_TYPE_ENUM() \ + case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { \ + int value = reflection->GetEnum(message, field)->number(); \ + std::ostringstream oss; \ + oss << value; \ + out[field->name()] = oss.str(); \ + break; \ + } + + #define CASE_FIELD_TYPE_STRING() \ + case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { \ + std::string value = reflection->GetString(message, field); \ + out[field->name()] = value; \ + break; \ + } + + const google::protobuf::Descriptor *descriptor = message.GetDescriptor(); + const google::protobuf::Reflection *reflection = message.GetReflection(); + + for (int i = 0; i < descriptor->field_count(); i++) + { + const google::protobuf::FieldDescriptor *field = descriptor->field(i); + bool has_field = reflection->HasField(message, field); + + if (has_field) + { + if (field->is_repeated()) + { + return -1; // 不支持转换repeated字段 + } + + const std::string &field_name = field->name(); + switch (field->cpp_type()) + { + CASE_FIELD_TYPE(INT32, Int32, int); + CASE_FIELD_TYPE(UINT32, UInt32, uint32_t); + CASE_FIELD_TYPE(FLOAT, Float, float); + CASE_FIELD_TYPE(DOUBLE, Double, double); + CASE_FIELD_TYPE(BOOL, Bool, bool); + CASE_FIELD_TYPE(INT64, Int64, int64_t); + CASE_FIELD_TYPE(UINT64, UInt64, uint64_t); + CASE_FIELD_TYPE_ENUM(); + CASE_FIELD_TYPE_STRING(); + default: + return -1; // 其他异常类型 + } + } + } + return 0; +} + +int pb_fill_field(std::queue& args + , google::protobuf::Message* msg + , const google::protobuf::FieldDescriptor* field_des) +{ + if (args.empty()) + { + std::string err_ret = field_des->full_name() + "failed"; + args.push(err_ret); + return -1; + } + + const google::protobuf::Reflection* msg_ref = msg->GetReflection(); + assert(msg_ref != NULL); + + const char* cur_arg = args.front().c_str(); + switch (field_des->cpp_type()) + { + case google::protobuf::FieldDescriptor::CPPTYPE_STRING: + { + msg_ref->SetString(msg, field_des, cur_arg); + args.pop(); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_INT32: + { + int value = atoi(cur_arg); + msg_ref->SetInt32(msg, field_des, value); + args.pop(); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: + { + bool value = (bool)atoi(cur_arg); + msg_ref->SetBool(msg, field_des, value); + args.pop(); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: + { + float value = (float)atof(cur_arg); + msg_ref->SetFloat(msg, field_des, value); + args.pop(); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: + { + double value = atof(cur_arg); + msg_ref->SetDouble(msg, field_des, value); + args.pop(); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: + { + unsigned long int value = strtoull(cur_arg, NULL, 10);; + msg_ref->SetUInt64(msg, field_des, value); + args.pop(); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_INT64: + { + long int value = strtoll(cur_arg, NULL, 10); + msg_ref->SetInt64(msg, field_des, value); + args.pop(); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: + { + unsigned int value = (unsigned int)atoi(cur_arg);; + msg_ref->SetUInt32(msg, field_des, value); + args.pop(); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: + { + google::protobuf::Message* pMsg = msg_ref->MutableMessage(msg, field_des); + return pb_fill_message(args, pMsg); + } + default: + { + std::string err_ret = field_des->full_name() + " failed"; + args.push(err_ret); + return -1; + } + } + return 0; +} + +int pb_fill_repeated_field(std::queue& args + , google::protobuf::Message* msg + , const google::protobuf::FieldDescriptor* field_des + , int32_t nFieldIndex) +{ + if (args.empty()) + { + std::string err_ret = field_des->full_name() + "repeated failed"; + args.push(err_ret); + return -1; + } + + const google::protobuf::Reflection* msg_ref = msg->GetReflection(); + if (msg_ref == NULL) {return -1;} + + const char* cur_arg = args.front().c_str(); + switch (field_des->cpp_type()) + { + case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: + { + google::protobuf::Message* pSubMessage = msg_ref->AddMessage(msg, field_des); + assert(pSubMessage != NULL); + + return pb_fill_message(args, pSubMessage); + } + case google::protobuf::FieldDescriptor::CPPTYPE_STRING: + { + msg_ref->SetString(msg, field_des, cur_arg); + args.pop(); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_INT32: + { + int value = atoi(cur_arg); + msg_ref->AddInt32(msg, field_des, value); + args.pop(); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_INT64: + { + long int value = strtoll(cur_arg, NULL, 10); + msg_ref->AddInt64(msg, field_des, value); + args.pop(); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: + { + bool value = (bool)atoi(cur_arg); + msg_ref->AddBool(msg, field_des, value); + args.pop(); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: + { + float value = (float)atof(cur_arg); + msg_ref->AddFloat(msg, field_des, value); + args.pop(); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: + { + double value = atof(cur_arg); + msg_ref->AddDouble(msg, field_des, value); + args.pop(); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: + { + unsigned int value = (unsigned int)atoi(cur_arg);; + msg_ref->AddUInt32(msg, field_des, value); + args.pop(); + break; + } + case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: + { + unsigned long int value = strtoull(cur_arg, NULL, 10);; + msg_ref->AddUInt64(msg, field_des, value); + args.pop(); + break; + } + default: + { + std::string err_ret = field_des->full_name() + " repeared failed"; + args.push(err_ret); + return -1; + } + break; + } + return 0; +} + +int pb_fill_message(std::queue& args, google::protobuf::Message* msg) +{ + const google::protobuf::FieldDescriptor* field_des = NULL; + const google::protobuf::Descriptor* descriptor = msg->GetDescriptor(); + const google::protobuf::Reflection* msg_ref = msg->GetReflection(); + + int ret = 0; + for (int32_t i = 0; i < descriptor->field_count(); ++i) + { + field_des = descriptor->field(i); + if (args.empty()) + { + std::string err_ret = field_des->full_name() + " failed"; + args.push(err_ret); + return -1; + } + + const char* cur_arg = args.front().c_str(); + if (field_des->is_repeated()) + { + int32_t nArraySize = atoi(cur_arg); + args.pop(); + + for (int32_t i = 0; i < nArraySize; i++) + { + ret = pb_fill_repeated_field(args, msg, field_des, i); + if (ret != 0) return ret; + } + } + else + { + ret = pb_fill_field(args, msg, field_des); + if (ret != 0) return ret; + } + } + return 0; +} + +google::protobuf::Message* pb_create_by_name(const char *type_name) +{ + google::protobuf::Message* message = NULL; + + const google::protobuf::Descriptor* descriptor = + google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName(type_name); + if (descriptor) + { + google::protobuf::MessageFactory* factory = + google::protobuf::MessageFactory::generated_factory(); + assert(factory != NULL); + + const google::protobuf::Message* prototype = factory->GetPrototype(descriptor); + if (prototype) + { + message = prototype->New(); + } + } + return message; +} + +int string_to_pb() +{ + google::protobuf::Message* message = pb_create_by_name("PersonInfo"); + + std::queue args; + args.push("10001"); + args.push("18"); + args.push("123456"); + args.push("haha"); + + int ret = pb_fill_message(args, message); + if (ret != 0) { + cout << "fill failed" << endl; + return ret; + } + cout << "string_to_pb >>>> " << message->DebugString() << endl; + return 0; +} + +int main() +{ + PersonInfo info; + info.set_age(100); + cout <<"debug string : " << info.DebugString() << endl; + + print_pb_message(info); + fill_pb_message(info); + cout <<"debug string : " << info.DebugString() << endl; + + std::map pb_map; + PbToMap(info, pb_map); + + int ret = string_to_pb(); + return ret; +} diff --git a/example_code/pb_demo/reflect/demo1/out/person.pb.cc b/example_code/pb_demo/reflect/demo1/out/person.pb.cc new file mode 100755 index 0000000..d2ce455 --- /dev/null +++ b/example_code/pb_demo/reflect/demo1/out/person.pb.cc @@ -0,0 +1,370 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: person.proto + +#include "person.pb.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) +#include + +PROTOBUF_PRAGMA_INIT_SEG +constexpr PersonInfo::PersonInfo( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , id_(0u) + , age_(0u) + , passwd_(0u){} +struct PersonInfoDefaultTypeInternal { + constexpr PersonInfoDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~PersonInfoDefaultTypeInternal() {} + union { + PersonInfo _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PersonInfoDefaultTypeInternal _PersonInfo_default_instance_; +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_person_2eproto[1]; +static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_person_2eproto = nullptr; +static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_person_2eproto = nullptr; + +const uint32_t TableStruct_person_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PersonInfo, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PersonInfo, id_), + PROTOBUF_FIELD_OFFSET(::PersonInfo, age_), + PROTOBUF_FIELD_OFFSET(::PersonInfo, passwd_), + PROTOBUF_FIELD_OFFSET(::PersonInfo, name_), +}; +static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, -1, sizeof(::PersonInfo)}, +}; + +static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { + reinterpret_cast(&::_PersonInfo_default_instance_), +}; + +const char descriptor_table_protodef_person_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\014person.proto\"C\n\nPersonInfo\022\n\n\002id\030\001 \001(\r" + "\022\013\n\003age\030\002 \001(\r\022\016\n\006passwd\030\003 \001(\r\022\014\n\004name\030\004 " + "\001(\tb\006proto3" + ; +static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_person_2eproto_once; +const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_person_2eproto = { + false, false, 91, descriptor_table_protodef_person_2eproto, "person.proto", + &descriptor_table_person_2eproto_once, nullptr, 0, 1, + schemas, file_default_instances, TableStruct_person_2eproto::offsets, + file_level_metadata_person_2eproto, file_level_enum_descriptors_person_2eproto, file_level_service_descriptors_person_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_person_2eproto_getter() { + return &descriptor_table_person_2eproto; +} + +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_person_2eproto(&descriptor_table_person_2eproto); + +// =================================================================== + +class PersonInfo::_Internal { + public: +}; + +PersonInfo::PersonInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(); + if (!is_message_owned) { + RegisterArenaDtor(arena); + } + // @@protoc_insertion_point(arena_constructor:PersonInfo) +} +PersonInfo::PersonInfo(const PersonInfo& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_name().empty()) { + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), + GetArenaForAllocation()); + } + ::memcpy(&id_, &from.id_, + static_cast(reinterpret_cast(&passwd_) - + reinterpret_cast(&id_)) + sizeof(passwd_)); + // @@protoc_insertion_point(copy_constructor:PersonInfo) +} + +inline void PersonInfo::SharedCtor() { +name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation()); +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&id_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&passwd_) - + reinterpret_cast(&id_)) + sizeof(passwd_)); +} + +PersonInfo::~PersonInfo() { + // @@protoc_insertion_point(destructor:PersonInfo) + if (GetArenaForAllocation() != nullptr) return; + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +inline void PersonInfo::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void PersonInfo::ArenaDtor(void* object) { + PersonInfo* _this = reinterpret_cast< PersonInfo* >(object); + (void)_this; +} +void PersonInfo::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void PersonInfo::SetCachedSize(int size) const { + _cached_size_.Set(size); +} + +void PersonInfo::Clear() { +// @@protoc_insertion_point(message_clear_start:PersonInfo) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + name_.ClearToEmpty(); + ::memset(&id_, 0, static_cast( + reinterpret_cast(&passwd_) - + reinterpret_cast(&id_)) + sizeof(passwd_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* PersonInfo::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + switch (tag >> 3) { + // uint32 id = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 8)) { + id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // uint32 age = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 16)) { + age_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // uint32 passwd = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 24)) { + passwd_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // string name = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 34)) { + auto str = _internal_mutable_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "PersonInfo.name")); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* PersonInfo::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:PersonInfo) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // uint32 id = 1; + if (this->_internal_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(1, this->_internal_id(), target); + } + + // uint32 age = 2; + if (this->_internal_age() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(2, this->_internal_age(), target); + } + + // uint32 passwd = 3; + if (this->_internal_passwd() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(3, this->_internal_passwd(), target); + } + + // string name = 4; + if (!this->_internal_name().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_name().data(), static_cast(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "PersonInfo.name"); + target = stream->WriteStringMaybeAliased( + 4, this->_internal_name(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:PersonInfo) + return target; +} + +size_t PersonInfo::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:PersonInfo) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string name = 4; + if (!this->_internal_name().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // uint32 id = 1; + if (this->_internal_id() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_id()); + } + + // uint32 age = 2; + if (this->_internal_age() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_age()); + } + + // uint32 passwd = 3; + if (this->_internal_passwd() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_passwd()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData PersonInfo::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck, + PersonInfo::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*PersonInfo::GetClassData() const { return &_class_data_; } + +void PersonInfo::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, + const ::PROTOBUF_NAMESPACE_ID::Message& from) { + static_cast(to)->MergeFrom( + static_cast(from)); +} + + +void PersonInfo::MergeFrom(const PersonInfo& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:PersonInfo) + GOOGLE_DCHECK_NE(&from, this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_name().empty()) { + _internal_set_name(from._internal_name()); + } + if (from._internal_id() != 0) { + _internal_set_id(from._internal_id()); + } + if (from._internal_age() != 0) { + _internal_set_age(from._internal_age()); + } + if (from._internal_passwd() != 0) { + _internal_set_passwd(from._internal_passwd()); + } + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void PersonInfo::CopyFrom(const PersonInfo& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:PersonInfo) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool PersonInfo::IsInitialized() const { + return true; +} + +void PersonInfo::InternalSwap(PersonInfo* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + &name_, lhs_arena, + &other->name_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(PersonInfo, passwd_) + + sizeof(PersonInfo::passwd_) + - PROTOBUF_FIELD_OFFSET(PersonInfo, id_)>( + reinterpret_cast(&id_), + reinterpret_cast(&other->id_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata PersonInfo::GetMetadata() const { + return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors( + &descriptor_table_person_2eproto_getter, &descriptor_table_person_2eproto_once, + file_level_metadata_person_2eproto[0]); +} + +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::PersonInfo* Arena::CreateMaybeMessage< ::PersonInfo >(Arena* arena) { + return Arena::CreateMessageInternal< ::PersonInfo >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include diff --git a/example_code/pb_demo/reflect/demo1/out/person.pb.h b/example_code/pb_demo/reflect/demo1/out/person.pb.h new file mode 100755 index 0000000..9cd5bda --- /dev/null +++ b/example_code/pb_demo/reflect/demo1/out/person.pb.h @@ -0,0 +1,379 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: person.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_person_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_person_2eproto + +#include +#include + +#include +#if PROTOBUF_VERSION < 3019000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 3019001 < PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // IWYU pragma: export +#include // IWYU pragma: export +#include +// @@protoc_insertion_point(includes) +#include +#define PROTOBUF_INTERNAL_EXPORT_person_2eproto +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct TableStruct_person_2eproto { + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[1] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; + static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; + static const uint32_t offsets[]; +}; +extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_person_2eproto; +class PersonInfo; +struct PersonInfoDefaultTypeInternal; +extern PersonInfoDefaultTypeInternal _PersonInfo_default_instance_; +PROTOBUF_NAMESPACE_OPEN +template<> ::PersonInfo* Arena::CreateMaybeMessage<::PersonInfo>(Arena*); +PROTOBUF_NAMESPACE_CLOSE + +// =================================================================== + +class PersonInfo final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:PersonInfo) */ { + public: + inline PersonInfo() : PersonInfo(nullptr) {} + ~PersonInfo() override; + explicit constexpr PersonInfo(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + PersonInfo(const PersonInfo& from); + PersonInfo(PersonInfo&& from) noexcept + : PersonInfo() { + *this = ::std::move(from); + } + + inline PersonInfo& operator=(const PersonInfo& from) { + CopyFrom(from); + return *this; + } + inline PersonInfo& operator=(PersonInfo&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const PersonInfo& default_instance() { + return *internal_default_instance(); + } + static inline const PersonInfo* internal_default_instance() { + return reinterpret_cast( + &_PersonInfo_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(PersonInfo& a, PersonInfo& b) { + a.Swap(&b); + } + inline void Swap(PersonInfo* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(PersonInfo* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + PersonInfo* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const PersonInfo& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom(const PersonInfo& from); + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(PersonInfo* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "PersonInfo"; + } + protected: + explicit PersonInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kNameFieldNumber = 4, + kIdFieldNumber = 1, + kAgeFieldNumber = 2, + kPasswdFieldNumber = 3, + }; + // string name = 4; + void clear_name(); + const std::string& name() const; + template + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // uint32 id = 1; + void clear_id(); + uint32_t id() const; + void set_id(uint32_t value); + private: + uint32_t _internal_id() const; + void _internal_set_id(uint32_t value); + public: + + // uint32 age = 2; + void clear_age(); + uint32_t age() const; + void set_age(uint32_t value); + private: + uint32_t _internal_age() const; + void _internal_set_age(uint32_t value); + public: + + // uint32 passwd = 3; + void clear_passwd(); + uint32_t passwd() const; + void set_passwd(uint32_t value); + private: + uint32_t _internal_passwd() const; + void _internal_set_passwd(uint32_t value); + public: + + // @@protoc_insertion_point(class_scope:PersonInfo) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + uint32_t id_; + uint32_t age_; + uint32_t passwd_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_person_2eproto; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// PersonInfo + +// uint32 id = 1; +inline void PersonInfo::clear_id() { + id_ = 0u; +} +inline uint32_t PersonInfo::_internal_id() const { + return id_; +} +inline uint32_t PersonInfo::id() const { + // @@protoc_insertion_point(field_get:PersonInfo.id) + return _internal_id(); +} +inline void PersonInfo::_internal_set_id(uint32_t value) { + + id_ = value; +} +inline void PersonInfo::set_id(uint32_t value) { + _internal_set_id(value); + // @@protoc_insertion_point(field_set:PersonInfo.id) +} + +// uint32 age = 2; +inline void PersonInfo::clear_age() { + age_ = 0u; +} +inline uint32_t PersonInfo::_internal_age() const { + return age_; +} +inline uint32_t PersonInfo::age() const { + // @@protoc_insertion_point(field_get:PersonInfo.age) + return _internal_age(); +} +inline void PersonInfo::_internal_set_age(uint32_t value) { + + age_ = value; +} +inline void PersonInfo::set_age(uint32_t value) { + _internal_set_age(value); + // @@protoc_insertion_point(field_set:PersonInfo.age) +} + +// uint32 passwd = 3; +inline void PersonInfo::clear_passwd() { + passwd_ = 0u; +} +inline uint32_t PersonInfo::_internal_passwd() const { + return passwd_; +} +inline uint32_t PersonInfo::passwd() const { + // @@protoc_insertion_point(field_get:PersonInfo.passwd) + return _internal_passwd(); +} +inline void PersonInfo::_internal_set_passwd(uint32_t value) { + + passwd_ = value; +} +inline void PersonInfo::set_passwd(uint32_t value) { + _internal_set_passwd(value); + // @@protoc_insertion_point(field_set:PersonInfo.passwd) +} + +// string name = 4; +inline void PersonInfo::clear_name() { + name_.ClearToEmpty(); +} +inline const std::string& PersonInfo::name() const { + // @@protoc_insertion_point(field_get:PersonInfo.name) + return _internal_name(); +} +template +inline PROTOBUF_ALWAYS_INLINE +void PersonInfo::set_name(ArgT0&& arg0, ArgT... args) { + + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:PersonInfo.name) +} +inline std::string* PersonInfo::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:PersonInfo.name) + return _s; +} +inline const std::string& PersonInfo::_internal_name() const { + return name_.Get(); +} +inline void PersonInfo::_internal_set_name(const std::string& value) { + + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation()); +} +inline std::string* PersonInfo::_internal_mutable_name() { + + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation()); +} +inline std::string* PersonInfo::release_name() { + // @@protoc_insertion_point(field_release:PersonInfo.name) + return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation()); +} +inline void PersonInfo::set_allocated_name(std::string* name) { + if (name != nullptr) { + + } else { + + } + name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name, + GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (name_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) { + name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:PersonInfo.name) +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) + + +// @@protoc_insertion_point(global_scope) + +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_person_2eproto diff --git a/example_code/pb_demo/reflect/demo1/person.proto b/example_code/pb_demo/reflect/demo1/person.proto new file mode 100755 index 0000000..d97c812 --- /dev/null +++ b/example_code/pb_demo/reflect/demo1/person.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; +message PersonInfo +{ + uint32 id = 1; + uint32 age = 2; + uint32 passwd = 3; + string name = 4; +} \ No newline at end of file diff --git a/example_code/pb_demo/reflect/demo2/Makefile b/example_code/pb_demo/reflect/demo2/Makefile new file mode 100755 index 0000000..c8ee1ad --- /dev/null +++ b/example_code/pb_demo/reflect/demo2/Makefile @@ -0,0 +1,13 @@ +.PHONY: all proto clean run + +all: + g++ main.cpp ./out/person.pb.cc -o main -I./out -lprotobuf -lpthread -L/usr/local/lib -g + +proto: + protoc --cpp_out=./out *.proto + +run: + ./main + +clean: + rm main \ No newline at end of file diff --git a/example_code/pb_demo/reflect/demo2/main b/example_code/pb_demo/reflect/demo2/main new file mode 100755 index 0000000..0931718 Binary files /dev/null and b/example_code/pb_demo/reflect/demo2/main differ diff --git a/example_code/pb_demo/reflect/demo2/main.cpp b/example_code/pb_demo/reflect/demo2/main.cpp new file mode 100755 index 0000000..883ec8e --- /dev/null +++ b/example_code/pb_demo/reflect/demo2/main.cpp @@ -0,0 +1,50 @@ +#include +#include "person.pb.h" +#include +#include + +using namespace std; +using namespace google::protobuf; + +bool minLengthCheck(const std::string &strValue, const uint32_t &dwLenthMin) { + return strValue.size() < dwLenthMin; +} + +int allCheck(const google::protobuf::Message &oMessage){ + const auto *poReflect = oMessage.GetReflection(); + + vector vecFD; + poReflect->ListFields(oMessage, &vecFD); + + for (const auto &poFiled : vecFD) { + const auto &oFieldRule = poFiled->options().GetExtension(field_rule); + if (poFiled->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_STRING && !poFiled->is_repeated()) { + // ������string����ѡ����ظ��IJŻ�У���ֶγ������� + const std::string strValue = poReflect->GetString(oMessage, poFiled); + const std::string strName = poFiled->name(); + + if (oFieldRule.length_min()) { + // �вŽ���У�飬û���򲻽���У�� + if (minLengthCheck(strValue, oFieldRule.length_min())) { + cout << "the length of " << strName << " is lower than " << oFieldRule.length_min()< + +#include +#include +#include +#include +#include +#include +#include +// @@protoc_insertion_point(includes) +#include + +PROTOBUF_PRAGMA_INIT_SEG +constexpr PersonInfo::PersonInfo( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , id_(0u) + , age_(0u) + , passwd_(0u){} +struct PersonInfoDefaultTypeInternal { + constexpr PersonInfoDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~PersonInfoDefaultTypeInternal() {} + union { + PersonInfo _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PersonInfoDefaultTypeInternal _PersonInfo_default_instance_; +constexpr FieldRule::FieldRule( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : length_min_(0u) + , id_(0u){} +struct FieldRuleDefaultTypeInternal { + constexpr FieldRuleDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~FieldRuleDefaultTypeInternal() {} + union { + FieldRule _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT FieldRuleDefaultTypeInternal _FieldRule_default_instance_; +constexpr Student::Student( + ::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized) + : name_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string) + , email_(&::PROTOBUF_NAMESPACE_ID::internal::fixed_address_empty_string){} +struct StudentDefaultTypeInternal { + constexpr StudentDefaultTypeInternal() + : _instance(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized{}) {} + ~StudentDefaultTypeInternal() {} + union { + Student _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT StudentDefaultTypeInternal _Student_default_instance_; +static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_person_2eproto[3]; +static constexpr ::PROTOBUF_NAMESPACE_ID::EnumDescriptor const** file_level_enum_descriptors_person_2eproto = nullptr; +static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_person_2eproto = nullptr; + +const uint32_t TableStruct_person_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::PersonInfo, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::PersonInfo, id_), + PROTOBUF_FIELD_OFFSET(::PersonInfo, age_), + PROTOBUF_FIELD_OFFSET(::PersonInfo, passwd_), + PROTOBUF_FIELD_OFFSET(::PersonInfo, name_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::FieldRule, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::FieldRule, length_min_), + PROTOBUF_FIELD_OFFSET(::FieldRule, id_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::Student, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::Student, name_), + PROTOBUF_FIELD_OFFSET(::Student, email_), +}; +static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, -1, sizeof(::PersonInfo)}, + { 10, -1, -1, sizeof(::FieldRule)}, + { 18, -1, -1, sizeof(::Student)}, +}; + +static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = { + reinterpret_cast(&::_PersonInfo_default_instance_), + reinterpret_cast(&::_FieldRule_default_instance_), + reinterpret_cast(&::_Student_default_instance_), +}; + +const char descriptor_table_protodef_person_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = + "\n\014person.proto\032 google/protobuf/descript" + "or.proto\"C\n\nPersonInfo\022\n\n\002id\030\001 \001(\r\022\013\n\003ag" + "e\030\002 \001(\r\022\016\n\006passwd\030\003 \001(\r\022\014\n\004name\030\004 \001(\t\"+\n" + "\tFieldRule\022\022\n\nlength_min\030\001 \001(\r\022\n\n\002id\030\002 \001" + "(\r\"B\n\007Student\022\032\n\004name\030\001 \001(\tB\014\202\265\030\002\010\005\202\265\030\002\020" + "\001\022\033\n\005email\030\002 \001(\tB\014\202\265\030\002\010\n\202\265\030\002\020\002:\?\n\nfield_" + "rule\022\035.google.protobuf.FieldOptions\030\320\206\003 " + "\001(\0132\n.FieldRuleb\006proto3" + ; +static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_person_2eproto_deps[1] = { + &::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, +}; +static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_person_2eproto_once; +const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_person_2eproto = { + false, false, 303, descriptor_table_protodef_person_2eproto, "person.proto", + &descriptor_table_person_2eproto_once, descriptor_table_person_2eproto_deps, 1, 3, + schemas, file_default_instances, TableStruct_person_2eproto::offsets, + file_level_metadata_person_2eproto, file_level_enum_descriptors_person_2eproto, file_level_service_descriptors_person_2eproto, +}; +PROTOBUF_ATTRIBUTE_WEAK const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable* descriptor_table_person_2eproto_getter() { + return &descriptor_table_person_2eproto; +} + +// Force running AddDescriptors() at dynamic initialization time. +PROTOBUF_ATTRIBUTE_INIT_PRIORITY static ::PROTOBUF_NAMESPACE_ID::internal::AddDescriptorsRunner dynamic_init_dummy_person_2eproto(&descriptor_table_person_2eproto); + +// =================================================================== + +class PersonInfo::_Internal { + public: +}; + +PersonInfo::PersonInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(); + if (!is_message_owned) { + RegisterArenaDtor(arena); + } + // @@protoc_insertion_point(arena_constructor:PersonInfo) +} +PersonInfo::PersonInfo(const PersonInfo& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_name().empty()) { + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), + GetArenaForAllocation()); + } + ::memcpy(&id_, &from.id_, + static_cast(reinterpret_cast(&passwd_) - + reinterpret_cast(&id_)) + sizeof(passwd_)); + // @@protoc_insertion_point(copy_constructor:PersonInfo) +} + +inline void PersonInfo::SharedCtor() { +name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation()); +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&id_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&passwd_) - + reinterpret_cast(&id_)) + sizeof(passwd_)); +} + +PersonInfo::~PersonInfo() { + // @@protoc_insertion_point(destructor:PersonInfo) + if (GetArenaForAllocation() != nullptr) return; + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +inline void PersonInfo::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void PersonInfo::ArenaDtor(void* object) { + PersonInfo* _this = reinterpret_cast< PersonInfo* >(object); + (void)_this; +} +void PersonInfo::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void PersonInfo::SetCachedSize(int size) const { + _cached_size_.Set(size); +} + +void PersonInfo::Clear() { +// @@protoc_insertion_point(message_clear_start:PersonInfo) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + name_.ClearToEmpty(); + ::memset(&id_, 0, static_cast( + reinterpret_cast(&passwd_) - + reinterpret_cast(&id_)) + sizeof(passwd_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* PersonInfo::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + switch (tag >> 3) { + // uint32 id = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 8)) { + id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // uint32 age = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 16)) { + age_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // uint32 passwd = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 24)) { + passwd_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // string name = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 34)) { + auto str = _internal_mutable_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "PersonInfo.name")); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* PersonInfo::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:PersonInfo) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // uint32 id = 1; + if (this->_internal_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(1, this->_internal_id(), target); + } + + // uint32 age = 2; + if (this->_internal_age() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(2, this->_internal_age(), target); + } + + // uint32 passwd = 3; + if (this->_internal_passwd() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(3, this->_internal_passwd(), target); + } + + // string name = 4; + if (!this->_internal_name().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_name().data(), static_cast(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "PersonInfo.name"); + target = stream->WriteStringMaybeAliased( + 4, this->_internal_name(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:PersonInfo) + return target; +} + +size_t PersonInfo::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:PersonInfo) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string name = 4; + if (!this->_internal_name().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // uint32 id = 1; + if (this->_internal_id() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_id()); + } + + // uint32 age = 2; + if (this->_internal_age() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_age()); + } + + // uint32 passwd = 3; + if (this->_internal_passwd() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_passwd()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData PersonInfo::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck, + PersonInfo::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*PersonInfo::GetClassData() const { return &_class_data_; } + +void PersonInfo::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, + const ::PROTOBUF_NAMESPACE_ID::Message& from) { + static_cast(to)->MergeFrom( + static_cast(from)); +} + + +void PersonInfo::MergeFrom(const PersonInfo& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:PersonInfo) + GOOGLE_DCHECK_NE(&from, this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_name().empty()) { + _internal_set_name(from._internal_name()); + } + if (from._internal_id() != 0) { + _internal_set_id(from._internal_id()); + } + if (from._internal_age() != 0) { + _internal_set_age(from._internal_age()); + } + if (from._internal_passwd() != 0) { + _internal_set_passwd(from._internal_passwd()); + } + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void PersonInfo::CopyFrom(const PersonInfo& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:PersonInfo) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool PersonInfo::IsInitialized() const { + return true; +} + +void PersonInfo::InternalSwap(PersonInfo* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + &name_, lhs_arena, + &other->name_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(PersonInfo, passwd_) + + sizeof(PersonInfo::passwd_) + - PROTOBUF_FIELD_OFFSET(PersonInfo, id_)>( + reinterpret_cast(&id_), + reinterpret_cast(&other->id_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata PersonInfo::GetMetadata() const { + return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors( + &descriptor_table_person_2eproto_getter, &descriptor_table_person_2eproto_once, + file_level_metadata_person_2eproto[0]); +} + +// =================================================================== + +class FieldRule::_Internal { + public: +}; + +FieldRule::FieldRule(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(); + if (!is_message_owned) { + RegisterArenaDtor(arena); + } + // @@protoc_insertion_point(arena_constructor:FieldRule) +} +FieldRule::FieldRule(const FieldRule& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + ::memcpy(&length_min_, &from.length_min_, + static_cast(reinterpret_cast(&id_) - + reinterpret_cast(&length_min_)) + sizeof(id_)); + // @@protoc_insertion_point(copy_constructor:FieldRule) +} + +inline void FieldRule::SharedCtor() { +::memset(reinterpret_cast(this) + static_cast( + reinterpret_cast(&length_min_) - reinterpret_cast(this)), + 0, static_cast(reinterpret_cast(&id_) - + reinterpret_cast(&length_min_)) + sizeof(id_)); +} + +FieldRule::~FieldRule() { + // @@protoc_insertion_point(destructor:FieldRule) + if (GetArenaForAllocation() != nullptr) return; + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +inline void FieldRule::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); +} + +void FieldRule::ArenaDtor(void* object) { + FieldRule* _this = reinterpret_cast< FieldRule* >(object); + (void)_this; +} +void FieldRule::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void FieldRule::SetCachedSize(int size) const { + _cached_size_.Set(size); +} + +void FieldRule::Clear() { +// @@protoc_insertion_point(message_clear_start:FieldRule) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + ::memset(&length_min_, 0, static_cast( + reinterpret_cast(&id_) - + reinterpret_cast(&length_min_)) + sizeof(id_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* FieldRule::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + switch (tag >> 3) { + // uint32 length_min = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 8)) { + length_min_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // uint32 id = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 16)) { + id_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* FieldRule::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:FieldRule) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // uint32 length_min = 1; + if (this->_internal_length_min() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(1, this->_internal_length_min(), target); + } + + // uint32 id = 2; + if (this->_internal_id() != 0) { + target = stream->EnsureSpace(target); + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt32ToArray(2, this->_internal_id(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:FieldRule) + return target; +} + +size_t FieldRule::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:FieldRule) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // uint32 length_min = 1; + if (this->_internal_length_min() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_length_min()); + } + + // uint32 id = 2; + if (this->_internal_id() != 0) { + total_size += ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt32SizePlusOne(this->_internal_id()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData FieldRule::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck, + FieldRule::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*FieldRule::GetClassData() const { return &_class_data_; } + +void FieldRule::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, + const ::PROTOBUF_NAMESPACE_ID::Message& from) { + static_cast(to)->MergeFrom( + static_cast(from)); +} + + +void FieldRule::MergeFrom(const FieldRule& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:FieldRule) + GOOGLE_DCHECK_NE(&from, this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (from._internal_length_min() != 0) { + _internal_set_length_min(from._internal_length_min()); + } + if (from._internal_id() != 0) { + _internal_set_id(from._internal_id()); + } + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void FieldRule::CopyFrom(const FieldRule& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:FieldRule) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool FieldRule::IsInitialized() const { + return true; +} + +void FieldRule::InternalSwap(FieldRule* other) { + using std::swap; + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(FieldRule, id_) + + sizeof(FieldRule::id_) + - PROTOBUF_FIELD_OFFSET(FieldRule, length_min_)>( + reinterpret_cast(&length_min_), + reinterpret_cast(&other->length_min_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata FieldRule::GetMetadata() const { + return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors( + &descriptor_table_person_2eproto_getter, &descriptor_table_person_2eproto_once, + file_level_metadata_person_2eproto[1]); +} + +// =================================================================== + +class Student::_Internal { + public: +}; + +Student::Student(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(); + if (!is_message_owned) { + RegisterArenaDtor(arena); + } + // @@protoc_insertion_point(arena_constructor:Student) +} +Student::Student(const Student& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_name().empty()) { + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_name(), + GetArenaForAllocation()); + } + email_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + email_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_email().empty()) { + email_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_email(), + GetArenaForAllocation()); + } + // @@protoc_insertion_point(copy_constructor:Student) +} + +inline void Student::SharedCtor() { +name_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation()); +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +email_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + email_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation()); +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +Student::~Student() { + // @@protoc_insertion_point(destructor:Student) + if (GetArenaForAllocation() != nullptr) return; + SharedDtor(); + _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +inline void Student::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + name_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); + email_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited()); +} + +void Student::ArenaDtor(void* object) { + Student* _this = reinterpret_cast< Student* >(object); + (void)_this; +} +void Student::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) { +} +void Student::SetCachedSize(int size) const { + _cached_size_.Set(size); +} + +void Student::Clear() { +// @@protoc_insertion_point(message_clear_start:Student) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + name_.ClearToEmpty(); + email_.ClearToEmpty(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* Student::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag); + switch (tag >> 3) { + // string name = 1 [(.field_rule) = { + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 10)) { + auto str = _internal_mutable_name(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "Student.name")); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // string email = 2 [(.field_rule) = { + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 18)) { + auto str = _internal_mutable_email(); + ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx); + CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "Student.email")); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* Student::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:Student) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // string name = 1 [(.field_rule) = { + if (!this->_internal_name().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_name().data(), static_cast(this->_internal_name().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "Student.name"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_name(), target); + } + + // string email = 2 [(.field_rule) = { + if (!this->_internal_email().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_email().data(), static_cast(this->_internal_email().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "Student.email"); + target = stream->WriteStringMaybeAliased( + 2, this->_internal_email(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:Student) + return target; +} + +size_t Student::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:Student) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string name = 1 [(.field_rule) = { + if (!this->_internal_name().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_name()); + } + + // string email = 2 [(.field_rule) = { + if (!this->_internal_email().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_email()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData Student::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSizeCheck, + Student::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*Student::GetClassData() const { return &_class_data_; } + +void Student::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, + const ::PROTOBUF_NAMESPACE_ID::Message& from) { + static_cast(to)->MergeFrom( + static_cast(from)); +} + + +void Student::MergeFrom(const Student& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:Student) + GOOGLE_DCHECK_NE(&from, this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_name().empty()) { + _internal_set_name(from._internal_name()); + } + if (!from._internal_email().empty()) { + _internal_set_email(from._internal_email()); + } + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void Student::CopyFrom(const Student& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:Student) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Student::IsInitialized() const { + return true; +} + +void Student::InternalSwap(Student* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + &name_, lhs_arena, + &other->name_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), + &email_, lhs_arena, + &other->email_, rhs_arena + ); +} + +::PROTOBUF_NAMESPACE_ID::Metadata Student::GetMetadata() const { + return ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors( + &descriptor_table_person_2eproto_getter, &descriptor_table_person_2eproto_once, + file_level_metadata_person_2eproto[2]); +} +PROTOBUF_ATTRIBUTE_INIT_PRIORITY ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< ::PROTOBUF_NAMESPACE_ID::FieldOptions, + ::PROTOBUF_NAMESPACE_ID::internal::MessageTypeTraits< ::FieldRule >, 11, false > + field_rule(kFieldRuleFieldNumber, ::FieldRule::default_instance()); + +// @@protoc_insertion_point(namespace_scope) +PROTOBUF_NAMESPACE_OPEN +template<> PROTOBUF_NOINLINE ::PersonInfo* Arena::CreateMaybeMessage< ::PersonInfo >(Arena* arena) { + return Arena::CreateMessageInternal< ::PersonInfo >(arena); +} +template<> PROTOBUF_NOINLINE ::FieldRule* Arena::CreateMaybeMessage< ::FieldRule >(Arena* arena) { + return Arena::CreateMessageInternal< ::FieldRule >(arena); +} +template<> PROTOBUF_NOINLINE ::Student* Arena::CreateMaybeMessage< ::Student >(Arena* arena) { + return Arena::CreateMessageInternal< ::Student >(arena); +} +PROTOBUF_NAMESPACE_CLOSE + +// @@protoc_insertion_point(global_scope) +#include diff --git a/example_code/pb_demo/reflect/demo2/out/person.pb.h b/example_code/pb_demo/reflect/demo2/out/person.pb.h new file mode 100755 index 0000000..3e4dec7 --- /dev/null +++ b/example_code/pb_demo/reflect/demo2/out/person.pb.h @@ -0,0 +1,870 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: person.proto + +#ifndef GOOGLE_PROTOBUF_INCLUDED_person_2eproto +#define GOOGLE_PROTOBUF_INCLUDED_person_2eproto + +#include +#include + +#include +#if PROTOBUF_VERSION < 3019000 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 3019001 < PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // IWYU pragma: export +#include // IWYU pragma: export +#include +#include +// @@protoc_insertion_point(includes) +#include +#define PROTOBUF_INTERNAL_EXPORT_person_2eproto +PROTOBUF_NAMESPACE_OPEN +namespace internal { +class AnyMetadata; +} // namespace internal +PROTOBUF_NAMESPACE_CLOSE + +// Internal implementation detail -- do not use these members. +struct TableStruct_person_2eproto { + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[3] + PROTOBUF_SECTION_VARIABLE(protodesc_cold); + static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[]; + static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[]; + static const uint32_t offsets[]; +}; +extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_person_2eproto; +class FieldRule; +struct FieldRuleDefaultTypeInternal; +extern FieldRuleDefaultTypeInternal _FieldRule_default_instance_; +class PersonInfo; +struct PersonInfoDefaultTypeInternal; +extern PersonInfoDefaultTypeInternal _PersonInfo_default_instance_; +class Student; +struct StudentDefaultTypeInternal; +extern StudentDefaultTypeInternal _Student_default_instance_; +PROTOBUF_NAMESPACE_OPEN +template<> ::FieldRule* Arena::CreateMaybeMessage<::FieldRule>(Arena*); +template<> ::PersonInfo* Arena::CreateMaybeMessage<::PersonInfo>(Arena*); +template<> ::Student* Arena::CreateMaybeMessage<::Student>(Arena*); +PROTOBUF_NAMESPACE_CLOSE + +// =================================================================== + +class PersonInfo final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:PersonInfo) */ { + public: + inline PersonInfo() : PersonInfo(nullptr) {} + ~PersonInfo() override; + explicit constexpr PersonInfo(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + PersonInfo(const PersonInfo& from); + PersonInfo(PersonInfo&& from) noexcept + : PersonInfo() { + *this = ::std::move(from); + } + + inline PersonInfo& operator=(const PersonInfo& from) { + CopyFrom(from); + return *this; + } + inline PersonInfo& operator=(PersonInfo&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const PersonInfo& default_instance() { + return *internal_default_instance(); + } + static inline const PersonInfo* internal_default_instance() { + return reinterpret_cast( + &_PersonInfo_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + friend void swap(PersonInfo& a, PersonInfo& b) { + a.Swap(&b); + } + inline void Swap(PersonInfo* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(PersonInfo* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + PersonInfo* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const PersonInfo& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom(const PersonInfo& from); + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(PersonInfo* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "PersonInfo"; + } + protected: + explicit PersonInfo(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kNameFieldNumber = 4, + kIdFieldNumber = 1, + kAgeFieldNumber = 2, + kPasswdFieldNumber = 3, + }; + // string name = 4; + void clear_name(); + const std::string& name() const; + template + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // uint32 id = 1; + void clear_id(); + uint32_t id() const; + void set_id(uint32_t value); + private: + uint32_t _internal_id() const; + void _internal_set_id(uint32_t value); + public: + + // uint32 age = 2; + void clear_age(); + uint32_t age() const; + void set_age(uint32_t value); + private: + uint32_t _internal_age() const; + void _internal_set_age(uint32_t value); + public: + + // uint32 passwd = 3; + void clear_passwd(); + uint32_t passwd() const; + void set_passwd(uint32_t value); + private: + uint32_t _internal_passwd() const; + void _internal_set_passwd(uint32_t value); + public: + + // @@protoc_insertion_point(class_scope:PersonInfo) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + uint32_t id_; + uint32_t age_; + uint32_t passwd_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_person_2eproto; +}; +// ------------------------------------------------------------------- + +class FieldRule final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:FieldRule) */ { + public: + inline FieldRule() : FieldRule(nullptr) {} + ~FieldRule() override; + explicit constexpr FieldRule(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + FieldRule(const FieldRule& from); + FieldRule(FieldRule&& from) noexcept + : FieldRule() { + *this = ::std::move(from); + } + + inline FieldRule& operator=(const FieldRule& from) { + CopyFrom(from); + return *this; + } + inline FieldRule& operator=(FieldRule&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const FieldRule& default_instance() { + return *internal_default_instance(); + } + static inline const FieldRule* internal_default_instance() { + return reinterpret_cast( + &_FieldRule_default_instance_); + } + static constexpr int kIndexInFileMessages = + 1; + + friend void swap(FieldRule& a, FieldRule& b) { + a.Swap(&b); + } + inline void Swap(FieldRule* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(FieldRule* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + FieldRule* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const FieldRule& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom(const FieldRule& from); + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(FieldRule* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "FieldRule"; + } + protected: + explicit FieldRule(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kLengthMinFieldNumber = 1, + kIdFieldNumber = 2, + }; + // uint32 length_min = 1; + void clear_length_min(); + uint32_t length_min() const; + void set_length_min(uint32_t value); + private: + uint32_t _internal_length_min() const; + void _internal_set_length_min(uint32_t value); + public: + + // uint32 id = 2; + void clear_id(); + uint32_t id() const; + void set_id(uint32_t value); + private: + uint32_t _internal_id() const; + void _internal_set_id(uint32_t value); + public: + + // @@protoc_insertion_point(class_scope:FieldRule) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + uint32_t length_min_; + uint32_t id_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_person_2eproto; +}; +// ------------------------------------------------------------------- + +class Student final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:Student) */ { + public: + inline Student() : Student(nullptr) {} + ~Student() override; + explicit constexpr Student(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + Student(const Student& from); + Student(Student&& from) noexcept + : Student() { + *this = ::std::move(from); + } + + inline Student& operator=(const Student& from) { + CopyFrom(from); + return *this; + } + inline Student& operator=(Student&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const Student& default_instance() { + return *internal_default_instance(); + } + static inline const Student* internal_default_instance() { + return reinterpret_cast( + &_Student_default_instance_); + } + static constexpr int kIndexInFileMessages = + 2; + + friend void swap(Student& a, Student& b) { + a.Swap(&b); + } + inline void Swap(Student* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(Student* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + Student* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const Student& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom(const Student& from); + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message* to, const ::PROTOBUF_NAMESPACE_ID::Message& from); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Student* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "Student"; + } + protected: + explicit Student(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kNameFieldNumber = 1, + kEmailFieldNumber = 2, + }; + // string name = 1 [(.field_rule) = { + void clear_name(); + const std::string& name() const; + template + void set_name(ArgT0&& arg0, ArgT... args); + std::string* mutable_name(); + PROTOBUF_NODISCARD std::string* release_name(); + void set_allocated_name(std::string* name); + private: + const std::string& _internal_name() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_name(const std::string& value); + std::string* _internal_mutable_name(); + public: + + // string email = 2 [(.field_rule) = { + void clear_email(); + const std::string& email() const; + template + void set_email(ArgT0&& arg0, ArgT... args); + std::string* mutable_email(); + PROTOBUF_NODISCARD std::string* release_email(); + void set_allocated_email(std::string* email); + private: + const std::string& _internal_email() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_email(const std::string& value); + std::string* _internal_mutable_email(); + public: + + // @@protoc_insertion_point(class_scope:Student) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_; + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr email_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + friend struct ::TableStruct_person_2eproto; +}; +// =================================================================== + +static const int kFieldRuleFieldNumber = 50000; +extern ::PROTOBUF_NAMESPACE_ID::internal::ExtensionIdentifier< ::PROTOBUF_NAMESPACE_ID::FieldOptions, + ::PROTOBUF_NAMESPACE_ID::internal::MessageTypeTraits< ::FieldRule >, 11, false > + field_rule; + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// PersonInfo + +// uint32 id = 1; +inline void PersonInfo::clear_id() { + id_ = 0u; +} +inline uint32_t PersonInfo::_internal_id() const { + return id_; +} +inline uint32_t PersonInfo::id() const { + // @@protoc_insertion_point(field_get:PersonInfo.id) + return _internal_id(); +} +inline void PersonInfo::_internal_set_id(uint32_t value) { + + id_ = value; +} +inline void PersonInfo::set_id(uint32_t value) { + _internal_set_id(value); + // @@protoc_insertion_point(field_set:PersonInfo.id) +} + +// uint32 age = 2; +inline void PersonInfo::clear_age() { + age_ = 0u; +} +inline uint32_t PersonInfo::_internal_age() const { + return age_; +} +inline uint32_t PersonInfo::age() const { + // @@protoc_insertion_point(field_get:PersonInfo.age) + return _internal_age(); +} +inline void PersonInfo::_internal_set_age(uint32_t value) { + + age_ = value; +} +inline void PersonInfo::set_age(uint32_t value) { + _internal_set_age(value); + // @@protoc_insertion_point(field_set:PersonInfo.age) +} + +// uint32 passwd = 3; +inline void PersonInfo::clear_passwd() { + passwd_ = 0u; +} +inline uint32_t PersonInfo::_internal_passwd() const { + return passwd_; +} +inline uint32_t PersonInfo::passwd() const { + // @@protoc_insertion_point(field_get:PersonInfo.passwd) + return _internal_passwd(); +} +inline void PersonInfo::_internal_set_passwd(uint32_t value) { + + passwd_ = value; +} +inline void PersonInfo::set_passwd(uint32_t value) { + _internal_set_passwd(value); + // @@protoc_insertion_point(field_set:PersonInfo.passwd) +} + +// string name = 4; +inline void PersonInfo::clear_name() { + name_.ClearToEmpty(); +} +inline const std::string& PersonInfo::name() const { + // @@protoc_insertion_point(field_get:PersonInfo.name) + return _internal_name(); +} +template +inline PROTOBUF_ALWAYS_INLINE +void PersonInfo::set_name(ArgT0&& arg0, ArgT... args) { + + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:PersonInfo.name) +} +inline std::string* PersonInfo::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:PersonInfo.name) + return _s; +} +inline const std::string& PersonInfo::_internal_name() const { + return name_.Get(); +} +inline void PersonInfo::_internal_set_name(const std::string& value) { + + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation()); +} +inline std::string* PersonInfo::_internal_mutable_name() { + + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation()); +} +inline std::string* PersonInfo::release_name() { + // @@protoc_insertion_point(field_release:PersonInfo.name) + return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation()); +} +inline void PersonInfo::set_allocated_name(std::string* name) { + if (name != nullptr) { + + } else { + + } + name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name, + GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (name_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) { + name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:PersonInfo.name) +} + +// ------------------------------------------------------------------- + +// FieldRule + +// uint32 length_min = 1; +inline void FieldRule::clear_length_min() { + length_min_ = 0u; +} +inline uint32_t FieldRule::_internal_length_min() const { + return length_min_; +} +inline uint32_t FieldRule::length_min() const { + // @@protoc_insertion_point(field_get:FieldRule.length_min) + return _internal_length_min(); +} +inline void FieldRule::_internal_set_length_min(uint32_t value) { + + length_min_ = value; +} +inline void FieldRule::set_length_min(uint32_t value) { + _internal_set_length_min(value); + // @@protoc_insertion_point(field_set:FieldRule.length_min) +} + +// uint32 id = 2; +inline void FieldRule::clear_id() { + id_ = 0u; +} +inline uint32_t FieldRule::_internal_id() const { + return id_; +} +inline uint32_t FieldRule::id() const { + // @@protoc_insertion_point(field_get:FieldRule.id) + return _internal_id(); +} +inline void FieldRule::_internal_set_id(uint32_t value) { + + id_ = value; +} +inline void FieldRule::set_id(uint32_t value) { + _internal_set_id(value); + // @@protoc_insertion_point(field_set:FieldRule.id) +} + +// ------------------------------------------------------------------- + +// Student + +// string name = 1 [(.field_rule) = { +inline void Student::clear_name() { + name_.ClearToEmpty(); +} +inline const std::string& Student::name() const { + // @@protoc_insertion_point(field_get:Student.name) + return _internal_name(); +} +template +inline PROTOBUF_ALWAYS_INLINE +void Student::set_name(ArgT0&& arg0, ArgT... args) { + + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:Student.name) +} +inline std::string* Student::mutable_name() { + std::string* _s = _internal_mutable_name(); + // @@protoc_insertion_point(field_mutable:Student.name) + return _s; +} +inline const std::string& Student::_internal_name() const { + return name_.Get(); +} +inline void Student::_internal_set_name(const std::string& value) { + + name_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation()); +} +inline std::string* Student::_internal_mutable_name() { + + return name_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation()); +} +inline std::string* Student::release_name() { + // @@protoc_insertion_point(field_release:Student.name) + return name_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation()); +} +inline void Student::set_allocated_name(std::string* name) { + if (name != nullptr) { + + } else { + + } + name_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), name, + GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (name_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) { + name_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:Student.name) +} + +// string email = 2 [(.field_rule) = { +inline void Student::clear_email() { + email_.ClearToEmpty(); +} +inline const std::string& Student::email() const { + // @@protoc_insertion_point(field_get:Student.email) + return _internal_email(); +} +template +inline PROTOBUF_ALWAYS_INLINE +void Student::set_email(ArgT0&& arg0, ArgT... args) { + + email_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, static_cast(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:Student.email) +} +inline std::string* Student::mutable_email() { + std::string* _s = _internal_mutable_email(); + // @@protoc_insertion_point(field_mutable:Student.email) + return _s; +} +inline const std::string& Student::_internal_email() const { + return email_.Get(); +} +inline void Student::_internal_set_email(const std::string& value) { + + email_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArenaForAllocation()); +} +inline std::string* Student::_internal_mutable_email() { + + return email_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArenaForAllocation()); +} +inline std::string* Student::release_email() { + // @@protoc_insertion_point(field_release:Student.email) + return email_.Release(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArenaForAllocation()); +} +inline void Student::set_allocated_email(std::string* email) { + if (email != nullptr) { + + } else { + + } + email_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), email, + GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (email_.IsDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited())) { + email_.Set(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), "", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:Student.email) +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + + +// @@protoc_insertion_point(namespace_scope) + + +// @@protoc_insertion_point(global_scope) + +#include +#endif // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_person_2eproto diff --git a/example_code/pb_demo/reflect/demo2/person.proto b/example_code/pb_demo/reflect/demo2/person.proto new file mode 100755 index 0000000..e16713d --- /dev/null +++ b/example_code/pb_demo/reflect/demo2/person.proto @@ -0,0 +1,25 @@ +syntax = "proto3"; + +import "google/protobuf/descriptor.proto"; + +message PersonInfo +{ + uint32 id = 1; + uint32 age = 2; + uint32 passwd = 3; + string name = 4; +} + +message FieldRule{ + uint32 length_min = 1; // 字段最小长度 + uint32 id = 2; // 字段映射id +} + +extend google.protobuf.FieldOptions{ + FieldRule field_rule = 50000; +} + +message Student{ + string name =1 [(field_rule).length_min = 5, (field_rule).id = 1]; + string email = 2 [(field_rule).length_min = 10, (field_rule).id = 2]; +} \ No newline at end of file diff --git a/example_code/pb_demo/writter b/example_code/pb_demo/writter new file mode 100755 index 0000000..037a9aa Binary files /dev/null and b/example_code/pb_demo/writter differ diff --git a/example_code/pb_demo/writter.cc b/example_code/pb_demo/writter.cc new file mode 100755 index 0000000..a3e077c --- /dev/null +++ b/example_code/pb_demo/writter.cc @@ -0,0 +1,31 @@ +#include "heartbeat.pb.h" +#include +#include +#include + +using namespace std; +using namespace heartbeat; + +int main(void){ + HeartBeatMessage msg; + + const long dateTime = 100100; + std::cout << dateTime << std::endl; + + msg.set_datetime(dateTime); + msg.set_hostname("dataNode-1000"); + msg.set_ip("192.168.0.128"); + msg.set_info("Everything is normal, I'm healthy"); + + fstream output("./heartbeat.db",ios::out|ios::trunc|ios::binary); + if (!msg.SerializeToOstream(&output)) + { + cerr << "save data error." << endl; + return -1; + } + return 0; +} + +// protoc --cpp_out=. heartbeat.proto +// export LD_LIBRARY_PATH=/usr/local/lib +// g++ writter.cc heartbeat.pb.cc -lprotobuf -std=c++11 -g -lpthread \ No newline at end of file diff --git "a/example_code/pdf/C++11\347\232\204\345\206\205\345\255\230\346\225\260\346\215\2561.pdf" "b/example_code/pdf/C++11\347\232\204\345\206\205\345\255\230\346\225\260\346\215\2561.pdf" new file mode 100755 index 0000000..108795b Binary files /dev/null and "b/example_code/pdf/C++11\347\232\204\345\206\205\345\255\230\346\225\260\346\215\2561.pdf" differ diff --git "a/example_code/pdf/C++11\347\232\204\345\206\205\345\255\230\346\225\260\346\215\2562.pdf" "b/example_code/pdf/C++11\347\232\204\345\206\205\345\255\230\346\225\260\346\215\2562.pdf" new file mode 100755 index 0000000..2782bc8 Binary files /dev/null and "b/example_code/pdf/C++11\347\232\204\345\206\205\345\255\230\346\225\260\346\215\2562.pdf" differ diff --git a/example_code/perd_record/perf_collector.h b/example_code/perd_record/perf_collector.h new file mode 100755 index 0000000..7835e86 --- /dev/null +++ b/example_code/perd_record/perf_collector.h @@ -0,0 +1,37 @@ +#ifndef __PERF_COLLECT_H__ +#define __PERF_COLLECT_H__ + +#include "perf_stat.h" +#include "perf_stat_str_def.h" + +/* +��Ƶ��1MHZ�Ļ�����ôTSC�ͻ���1��������1000000; + +$ cat /proc/cpuinfo | grep MHz | uniq +cpu MHz : 2494.140 + +1����������tsc = 2494412210 +*/ + +class CYCLE_PROFILER +{ +public: + CYCLE_PROFILER(int id) : _id(id) + { + rdtscll(_tsc_begin); + } + + ~CYCLE_PROFILER() + { + rdtscll(_tsc_end); + unsigned long int time = _tsc_end - _tsc_begin; + printf("func id : %s, begin %lu, end %lu, use cpu tsc %lu \n", stat_type_str[_id], _tsc_begin, _tsc_end, time); + } + +private: + int _id; + unsigned long int _tsc_begin; + unsigned long int _tsc_end; +}; + +#endif \ No newline at end of file diff --git a/example_code/perd_record/perf_stat.h b/example_code/perd_record/perf_stat.h new file mode 100755 index 0000000..3f6c522 --- /dev/null +++ b/example_code/perd_record/perf_stat.h @@ -0,0 +1,74 @@ +#ifndef __PERF_STAT_H__ +#define __PERF_STAT_H__ + +#include +#include +#include +#include + +#ifdef __x86_64__ +#define rdtscll(val) do {\ + unsigned int __a,__d; \ + asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \ + (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32); \ + }while(0); +#else // __x86_64__ + #define rdtscll(val) \ + __asm__ __volatile__("rdtsc" : "=A" (val)) +#endif // __x86_64__ + +#ifndef _WIN32 + #include +#else // _WIN32 + #pragma warning(disable:4996) + #pragma comment(lib, "winmm.lib") + #include + #define usleep Sleep + + inline void gettimeofday(struct timeval *tv, void *) { + unsigned int tt = timeGetTime(); + tv->tv_sec = tt/1000; // ? + tv->tv_usec = tt%1000 * 1000; // ? + } +#endif // _WIN32 + +#define __MEASURE_IN_TICKS__ // �˺�ᵼ��һ������»�ʹ��tick������cpu��֧��ʱ��ʹ��gettimeofday���� + +#ifdef __MEASURE_IN_TICKS__ + #ifndef _WIN32 + #include + #include + #include + #define CPUINFO "/proc/cpuinfo" + #define CONSTANT_TSC "constant_tsc" + #endif // _WIN32 + + inline int mx_stat_init() + { + int ret = -1; + + #ifndef _WIN32 + const size_t BUFFSIZE = 4096; + int fd = open(CPUINFO, O_RDONLY); // cat cpu info + if(0 > fd) return -1; + do { + char buff[BUFFSIZE]; + memset(buff, 0, BUFFSIZE); + ssize_t read_size = read(fd, buff, BUFFSIZE - 1); // read it + if (0 > read_size) break; + + char *found_str = strstr(buff, CONSTANT_TSC); + if (NULL != found_str) { // found it, TSC supported! + ret = 0; + break; + } + } while(0); + close(fd); + #endif // _WIN32 + + return ret; + } +#endif // __MEASURE_IN_TICKS__ + + +#endif //__PERF_STAT_H__ diff --git a/example_code/perd_record/perf_stat_def.h b/example_code/perd_record/perf_stat_def.h new file mode 100755 index 0000000..39f7f80 --- /dev/null +++ b/example_code/perd_record/perf_stat_def.h @@ -0,0 +1,16 @@ +#ifndef __PERF_STAT_DEF_H__ +#define __PERF_STAT_DEF_H__ + +#ifdef PERF_DECLARE_STAT_TYPE +#undef PERF_DECLARE_STAT_TYPE +#endif + +#define PERF_DECLARE_STAT_TYPE(x) x, + +enum stat_type_t +{ +#include "perf_stat_type_def.h" + _type_max, +}; + +#endif \ No newline at end of file diff --git a/example_code/perd_record/perf_stat_str_def.h b/example_code/perd_record/perf_stat_str_def.h new file mode 100755 index 0000000..1c22474 --- /dev/null +++ b/example_code/perd_record/perf_stat_str_def.h @@ -0,0 +1,16 @@ +#ifndef __PERF_STAT_STR_DEF_H__ +#define __PERF_STAT_STR_DEF_H__ + +#ifdef PERF_DECLARE_STAT_TYPE +#undef PERF_DECLARE_STAT_TYPE +#endif + +#define PERF_DECLARE_STAT_TYPE(x) #x, + +const char * stat_type_str[] = +{ + #include "perf_stat_type_def.h" + "_type_max", +}; + +#endif diff --git a/example_code/perd_record/perf_stat_type_def.h b/example_code/perd_record/perf_stat_type_def.h new file mode 100755 index 0000000..fb44efb --- /dev/null +++ b/example_code/perd_record/perf_stat_type_def.h @@ -0,0 +1 @@ +PERF_DECLARE_STAT_TYPE(_type_test_func) \ No newline at end of file diff --git a/example_code/perd_record/readme.md b/example_code/perd_record/readme.md new file mode 100755 index 0000000..3881486 --- /dev/null +++ b/example_code/perd_record/readme.md @@ -0,0 +1,5 @@ +#### 统计函数执行时间 + +``` +g++ test_main.c -o test_main +``` \ No newline at end of file diff --git a/example_code/perd_record/test_main.c b/example_code/perd_record/test_main.c new file mode 100755 index 0000000..22d4a2b --- /dev/null +++ b/example_code/perd_record/test_main.c @@ -0,0 +1,22 @@ +#include +#include +#include "perf_stat_def.h" +#include "perf_collector.h" + +int test_func() +{ + CYCLE_PROFILER((int)_type_test_func); + + int times = 1000000; + while (times > 0) + { + int value = times * times; + times--; + }; +} + +int main() +{ + test_func(); + return 0; +} \ No newline at end of file diff --git a/example_code/readme.md b/example_code/readme.md old mode 100644 new mode 100755 diff --git a/example_code/redis_conf/redis_7000.conf b/example_code/redis_conf/redis_7000.conf new file mode 100755 index 0000000..82b08c9 --- /dev/null +++ b/example_code/redis_conf/redis_7000.conf @@ -0,0 +1,1322 @@ +# Redis configuration file example. +# +# Note that in order to read the configuration file, Redis must be +# started with the file path as first argument: +# +# ./redis-server /path/to/redis.conf + +# Note on units: when memory size is needed, it is possible to specify +# it in the usual form of 1k 5GB 4M and so forth: +# +# 1k => 1000 bytes +# 1kb => 1024 bytes +# 1m => 1000000 bytes +# 1mb => 1024*1024 bytes +# 1g => 1000000000 bytes +# 1gb => 1024*1024*1024 bytes +# +# units are case insensitive so 1GB 1Gb 1gB are all the same. + +################################## INCLUDES ################################### + +# Include one or more other config files here. This is useful if you +# have a standard template that goes to all Redis servers but also need +# to customize a few per-server settings. Include files can include +# other files, so use this wisely. +# +# Notice option "include" won't be rewritten by command "CONFIG REWRITE" +# from admin or Redis Sentinel. Since Redis always uses the last processed +# line as value of a configuration directive, you'd better put includes +# at the beginning of this file to avoid overwriting config change at runtime. +# +# If instead you are interested in using includes to override configuration +# options, it is better to use include as the last line. +# +# include /path/to/local.conf +# include /path/to/other.conf + +################################## MODULES ##################################### + +# Load modules at startup. If the server is not able to load modules +# it will abort. It is possible to use multiple loadmodule directives. +# +# loadmodule /path/to/my_module.so +# loadmodule /path/to/other_module.so + +################################## NETWORK ##################################### + +# By default, if no "bind" configuration directive is specified, Redis listens +# for connections from all the network interfaces available on the server. +# It is possible to listen to just one or multiple selected interfaces using +# the "bind" configuration directive, followed by one or more IP addresses. +# +# Examples: +# +# bind 192.168.1.100 10.0.0.1 +# bind 127.0.0.1 ::1 +# +# ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the +# internet, binding to all the interfaces is dangerous and will expose the +# instance to everybody on the internet. So by default we uncomment the +# following bind directive, that will force Redis to listen only into +# the IPv4 lookback interface address (this means Redis will be able to +# accept connections only from clients running into the same computer it +# is running). +# +# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES +# JUST COMMENT THE FOLLOWING LINE. +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +bind 127.0.0.1 ::1 + +# Protected mode is a layer of security protection, in order to avoid that +# Redis instances left open on the internet are accessed and exploited. +# +# When protected mode is on and if: +# +# 1) The server is not binding explicitly to a set of addresses using the +# "bind" directive. +# 2) No password is configured. +# +# The server only accepts connections from clients connecting from the +# IPv4 and IPv6 loopback addresses 127.0.0.1 and ::1, and from Unix domain +# sockets. +# +# By default protected mode is enabled. You should disable it only if +# you are sure you want clients from other hosts to connect to Redis +# even if no authentication is configured, nor a specific set of interfaces +# are explicitly listed using the "bind" directive. +protected-mode yes + +# Accept connections on the specified port, default is 6379 (IANA #815344). +# If port 0 is specified Redis will not listen on a TCP socket. +port 7000 +#deamonize yes #后台启动 +cluster-enabled yes +cluster-config-file nodes_7000.conf +cluster-node-timeout 5000 +appendonly yes + +# TCP listen() backlog. +# +# In high requests-per-second environments you need an high backlog in order +# to avoid slow clients connections issues. Note that the Linux kernel +# will silently truncate it to the value of /proc/sys/net/core/somaxconn so +# make sure to raise both the value of somaxconn and tcp_max_syn_backlog +# in order to get the desired effect. +tcp-backlog 511 + +# Unix socket. +# +# Specify the path for the Unix socket that will be used to listen for +# incoming connections. There is no default, so Redis will not listen +# on a unix socket when not specified. +# +# unixsocket /var/run/redis/redis-server.sock +# unixsocketperm 700 + +# Close the connection after a client is idle for N seconds (0 to disable) +timeout 0 + +# TCP keepalive. +# +# If non-zero, use SO_KEEPALIVE to send TCP ACKs to clients in absence +# of communication. This is useful for two reasons: +# +# 1) Detect dead peers. +# 2) Take the connection alive from the point of view of network +# equipment in the middle. +# +# On Linux, the specified value (in seconds) is the period used to send ACKs. +# Note that to close the connection the double of the time is needed. +# On other kernels the period depends on the kernel configuration. +# +# A reasonable value for this option is 300 seconds, which is the new +# Redis default starting with Redis 3.2.1. +tcp-keepalive 300 + +################################# GENERAL ##################################### + +# By default Redis does not run as a daemon. Use 'yes' if you need it. +# Note that Redis will write a pid file in /var/run/redis.pid when daemonized. +daemonize yes + +# If you run Redis from upstart or systemd, Redis can interact with your +# supervision tree. Options: +# supervised no - no supervision interaction +# supervised upstart - signal upstart by putting Redis into SIGSTOP mode +# supervised systemd - signal systemd by writing READY=1 to $NOTIFY_SOCKET +# supervised auto - detect upstart or systemd method based on +# UPSTART_JOB or NOTIFY_SOCKET environment variables +# Note: these supervision methods only signal "process is ready." +# They do not enable continuous liveness pings back to your supervisor. +supervised no + +# If a pid file is specified, Redis writes it where specified at startup +# and removes it at exit. +# +# When the server runs non daemonized, no pid file is created if none is +# specified in the configuration. When the server is daemonized, the pid file +# is used even if not specified, defaulting to "/var/run/redis.pid". +# +# Creating a pid file is best effort: if Redis is not able to create it +# nothing bad happens, the server will start and run normally. +pidfile /var/run/redis/redis-server.pid + +# Specify the server verbosity level. +# This can be one of: +# debug (a lot of information, useful for development/testing) +# verbose (many rarely useful info, but not a mess like the debug level) +# notice (moderately verbose, what you want in production probably) +# warning (only very important / critical messages are logged) +loglevel notice + +# Specify the log file name. Also the empty string can be used to force +# Redis to log on the standard output. Note that if you use standard +# output for logging but daemonize, logs will be sent to /dev/null +logfile /var/log/redis/redis-server.log + +# To enable logging to the system logger, just set 'syslog-enabled' to yes, +# and optionally update the other syslog parameters to suit your needs. +# syslog-enabled no + +# Specify the syslog identity. +# syslog-ident redis + +# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7. +# syslog-facility local0 + +# Set the number of databases. The default database is DB 0, you can select +# a different one on a per-connection basis using SELECT where +# dbid is a number between 0 and 'databases'-1 +databases 16 + +# By default Redis shows an ASCII art logo only when started to log to the +# standard output and if the standard output is a TTY. Basically this means +# that normally a logo is displayed only in interactive sessions. +# +# However it is possible to force the pre-4.0 behavior and always show a +# ASCII art logo in startup logs by setting the following option to yes. +always-show-logo yes + +################################ SNAPSHOTTING ################################ +# +# Save the DB on disk: +# +# save +# +# Will save the DB if both the given number of seconds and the given +# number of write operations against the DB occurred. +# +# In the example below the behaviour will be to save: +# after 900 sec (15 min) if at least 1 key changed +# after 300 sec (5 min) if at least 10 keys changed +# after 60 sec if at least 10000 keys changed +# +# Note: you can disable saving completely by commenting out all "save" lines. +# +# It is also possible to remove all the previously configured save +# points by adding a save directive with a single empty string argument +# like in the following example: +# +# save "" + +save 900 1 +save 300 10 +save 60 10000 + +# By default Redis will stop accepting writes if RDB snapshots are enabled +# (at least one save point) and the latest background save failed. +# This will make the user aware (in a hard way) that data is not persisting +# on disk properly, otherwise chances are that no one will notice and some +# disaster will happen. +# +# If the background saving process will start working again Redis will +# automatically allow writes again. +# +# However if you have setup your proper monitoring of the Redis server +# and persistence, you may want to disable this feature so that Redis will +# continue to work as usual even if there are problems with disk, +# permissions, and so forth. +stop-writes-on-bgsave-error yes + +# Compress string objects using LZF when dump .rdb databases? +# For default that's set to 'yes' as it's almost always a win. +# If you want to save some CPU in the saving child set it to 'no' but +# the dataset will likely be bigger if you have compressible values or keys. +rdbcompression yes + +# Since version 5 of RDB a CRC64 checksum is placed at the end of the file. +# This makes the format more resistant to corruption but there is a performance +# hit to pay (around 10%) when saving and loading RDB files, so you can disable it +# for maximum performances. +# +# RDB files created with checksum disabled have a checksum of zero that will +# tell the loading code to skip the check. +rdbchecksum yes + +# The filename where to dump the DB +dbfilename dump.rdb + +# The working directory. +# +# The DB will be written inside this directory, with the filename specified +# above using the 'dbfilename' configuration directive. +# +# The Append Only File will also be created inside this directory. +# +# Note that you must specify a directory here, not a file name. +dir /var/lib/redis + +################################# REPLICATION ################################# + +# Master-Slave replication. Use slaveof to make a Redis instance a copy of +# another Redis server. A few things to understand ASAP about Redis replication. +# +# 1) Redis replication is asynchronous, but you can configure a master to +# stop accepting writes if it appears to be not connected with at least +# a given number of slaves. +# 2) Redis slaves are able to perform a partial resynchronization with the +# master if the replication link is lost for a relatively small amount of +# time. You may want to configure the replication backlog size (see the next +# sections of this file) with a sensible value depending on your needs. +# 3) Replication is automatic and does not need user intervention. After a +# network partition slaves automatically try to reconnect to masters +# and resynchronize with them. +# +# slaveof + +# If the master is password protected (using the "requirepass" configuration +# directive below) it is possible to tell the slave to authenticate before +# starting the replication synchronization process, otherwise the master will +# refuse the slave request. +# +# masterauth + +# When a slave loses its connection with the master, or when the replication +# is still in progress, the slave can act in two different ways: +# +# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will +# still reply to client requests, possibly with out of date data, or the +# data set may just be empty if this is the first synchronization. +# +# 2) if slave-serve-stale-data is set to 'no' the slave will reply with +# an error "SYNC with master in progress" to all the kind of commands +# but to INFO and SLAVEOF. +# +slave-serve-stale-data yes + +# You can configure a slave instance to accept writes or not. Writing against +# a slave instance may be useful to store some ephemeral data (because data +# written on a slave will be easily deleted after resync with the master) but +# may also cause problems if clients are writing to it because of a +# misconfiguration. +# +# Since Redis 2.6 by default slaves are read-only. +# +# Note: read only slaves are not designed to be exposed to untrusted clients +# on the internet. It's just a protection layer against misuse of the instance. +# Still a read only slave exports by default all the administrative commands +# such as CONFIG, DEBUG, and so forth. To a limited extent you can improve +# security of read only slaves using 'rename-command' to shadow all the +# administrative / dangerous commands. +slave-read-only yes + +# Replication SYNC strategy: disk or socket. +# +# ------------------------------------------------------- +# WARNING: DISKLESS REPLICATION IS EXPERIMENTAL CURRENTLY +# ------------------------------------------------------- +# +# New slaves and reconnecting slaves that are not able to continue the replication +# process just receiving differences, need to do what is called a "full +# synchronization". An RDB file is transmitted from the master to the slaves. +# The transmission can happen in two different ways: +# +# 1) Disk-backed: The Redis master creates a new process that writes the RDB +# file on disk. Later the file is transferred by the parent +# process to the slaves incrementally. +# 2) Diskless: The Redis master creates a new process that directly writes the +# RDB file to slave sockets, without touching the disk at all. +# +# With disk-backed replication, while the RDB file is generated, more slaves +# can be queued and served with the RDB file as soon as the current child producing +# the RDB file finishes its work. With diskless replication instead once +# the transfer starts, new slaves arriving will be queued and a new transfer +# will start when the current one terminates. +# +# When diskless replication is used, the master waits a configurable amount of +# time (in seconds) before starting the transfer in the hope that multiple slaves +# will arrive and the transfer can be parallelized. +# +# With slow disks and fast (large bandwidth) networks, diskless replication +# works better. +repl-diskless-sync no + +# When diskless replication is enabled, it is possible to configure the delay +# the server waits in order to spawn the child that transfers the RDB via socket +# to the slaves. +# +# This is important since once the transfer starts, it is not possible to serve +# new slaves arriving, that will be queued for the next RDB transfer, so the server +# waits a delay in order to let more slaves arrive. +# +# The delay is specified in seconds, and by default is 5 seconds. To disable +# it entirely just set it to 0 seconds and the transfer will start ASAP. +repl-diskless-sync-delay 5 + +# Slaves send PINGs to server in a predefined interval. It's possible to change +# this interval with the repl_ping_slave_period option. The default value is 10 +# seconds. +# +# repl-ping-slave-period 10 + +# The following option sets the replication timeout for: +# +# 1) Bulk transfer I/O during SYNC, from the point of view of slave. +# 2) Master timeout from the point of view of slaves (data, pings). +# 3) Slave timeout from the point of view of masters (REPLCONF ACK pings). +# +# It is important to make sure that this value is greater than the value +# specified for repl-ping-slave-period otherwise a timeout will be detected +# every time there is low traffic between the master and the slave. +# +# repl-timeout 60 + +# Disable TCP_NODELAY on the slave socket after SYNC? +# +# If you select "yes" Redis will use a smaller number of TCP packets and +# less bandwidth to send data to slaves. But this can add a delay for +# the data to appear on the slave side, up to 40 milliseconds with +# Linux kernels using a default configuration. +# +# If you select "no" the delay for data to appear on the slave side will +# be reduced but more bandwidth will be used for replication. +# +# By default we optimize for low latency, but in very high traffic conditions +# or when the master and slaves are many hops away, turning this to "yes" may +# be a good idea. +repl-disable-tcp-nodelay no + +# Set the replication backlog size. The backlog is a buffer that accumulates +# slave data when slaves are disconnected for some time, so that when a slave +# wants to reconnect again, often a full resync is not needed, but a partial +# resync is enough, just passing the portion of data the slave missed while +# disconnected. +# +# The bigger the replication backlog, the longer the time the slave can be +# disconnected and later be able to perform a partial resynchronization. +# +# The backlog is only allocated once there is at least a slave connected. +# +# repl-backlog-size 1mb + +# After a master has no longer connected slaves for some time, the backlog +# will be freed. The following option configures the amount of seconds that +# need to elapse, starting from the time the last slave disconnected, for +# the backlog buffer to be freed. +# +# Note that slaves never free the backlog for timeout, since they may be +# promoted to masters later, and should be able to correctly "partially +# resynchronize" with the slaves: hence they should always accumulate backlog. +# +# A value of 0 means to never release the backlog. +# +# repl-backlog-ttl 3600 + +# The slave priority is an integer number published by Redis in the INFO output. +# It is used by Redis Sentinel in order to select a slave to promote into a +# master if the master is no longer working correctly. +# +# A slave with a low priority number is considered better for promotion, so +# for instance if there are three slaves with priority 10, 100, 25 Sentinel will +# pick the one with priority 10, that is the lowest. +# +# However a special priority of 0 marks the slave as not able to perform the +# role of master, so a slave with priority of 0 will never be selected by +# Redis Sentinel for promotion. +# +# By default the priority is 100. +slave-priority 100 + +# It is possible for a master to stop accepting writes if there are less than +# N slaves connected, having a lag less or equal than M seconds. +# +# The N slaves need to be in "online" state. +# +# The lag in seconds, that must be <= the specified value, is calculated from +# the last ping received from the slave, that is usually sent every second. +# +# This option does not GUARANTEE that N replicas will accept the write, but +# will limit the window of exposure for lost writes in case not enough slaves +# are available, to the specified number of seconds. +# +# For example to require at least 3 slaves with a lag <= 10 seconds use: +# +# min-slaves-to-write 3 +# min-slaves-max-lag 10 +# +# Setting one or the other to 0 disables the feature. +# +# By default min-slaves-to-write is set to 0 (feature disabled) and +# min-slaves-max-lag is set to 10. + +# A Redis master is able to list the address and port of the attached +# slaves in different ways. For example the "INFO replication" section +# offers this information, which is used, among other tools, by +# Redis Sentinel in order to discover slave instances. +# Another place where this info is available is in the output of the +# "ROLE" command of a master. +# +# The listed IP and address normally reported by a slave is obtained +# in the following way: +# +# IP: The address is auto detected by checking the peer address +# of the socket used by the slave to connect with the master. +# +# Port: The port is communicated by the slave during the replication +# handshake, and is normally the port that the slave is using to +# list for connections. +# +# However when port forwarding or Network Address Translation (NAT) is +# used, the slave may be actually reachable via different IP and port +# pairs. The following two options can be used by a slave in order to +# report to its master a specific set of IP and port, so that both INFO +# and ROLE will report those values. +# +# There is no need to use both the options if you need to override just +# the port or the IP address. +# +# slave-announce-ip 5.5.5.5 +# slave-announce-port 1234 + +################################## SECURITY ################################### + +# Require clients to issue AUTH before processing any other +# commands. This might be useful in environments in which you do not trust +# others with access to the host running redis-server. +# +# This should stay commented out for backward compatibility and because most +# people do not need auth (e.g. they run their own servers). +# +# Warning: since Redis is pretty fast an outside user can try up to +# 150k passwords per second against a good box. This means that you should +# use a very strong password otherwise it will be very easy to break. +# +# requirepass foobared + +# Command renaming. +# +# It is possible to change the name of dangerous commands in a shared +# environment. For instance the CONFIG command may be renamed into something +# hard to guess so that it will still be available for internal-use tools +# but not available for general clients. +# +# Example: +# +# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52 +# +# It is also possible to completely kill a command by renaming it into +# an empty string: +# +# rename-command CONFIG "" +# +# Please note that changing the name of commands that are logged into the +# AOF file or transmitted to slaves may cause problems. + +################################### CLIENTS #################################### + +# Set the max number of connected clients at the same time. By default +# this limit is set to 10000 clients, however if the Redis server is not +# able to configure the process file limit to allow for the specified limit +# the max number of allowed clients is set to the current file limit +# minus 32 (as Redis reserves a few file descriptors for internal uses). +# +# Once the limit is reached Redis will close all the new connections sending +# an error 'max number of clients reached'. +# +# maxclients 10000 + +############################## MEMORY MANAGEMENT ################################ + +# Set a memory usage limit to the specified amount of bytes. +# When the memory limit is reached Redis will try to remove keys +# according to the eviction policy selected (see maxmemory-policy). +# +# If Redis can't remove keys according to the policy, or if the policy is +# set to 'noeviction', Redis will start to reply with errors to commands +# that would use more memory, like SET, LPUSH, and so on, and will continue +# to reply to read-only commands like GET. +# +# This option is usually useful when using Redis as an LRU or LFU cache, or to +# set a hard memory limit for an instance (using the 'noeviction' policy). +# +# WARNING: If you have slaves attached to an instance with maxmemory on, +# the size of the output buffers needed to feed the slaves are subtracted +# from the used memory count, so that network problems / resyncs will +# not trigger a loop where keys are evicted, and in turn the output +# buffer of slaves is full with DELs of keys evicted triggering the deletion +# of more keys, and so forth until the database is completely emptied. +# +# In short... if you have slaves attached it is suggested that you set a lower +# limit for maxmemory so that there is some free RAM on the system for slave +# output buffers (but this is not needed if the policy is 'noeviction'). +# +# maxmemory + +# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory +# is reached. You can select among five behaviors: +# +# volatile-lru -> Evict using approximated LRU among the keys with an expire set. +# allkeys-lru -> Evict any key using approximated LRU. +# volatile-lfu -> Evict using approximated LFU among the keys with an expire set. +# allkeys-lfu -> Evict any key using approximated LFU. +# volatile-random -> Remove a random key among the ones with an expire set. +# allkeys-random -> Remove a random key, any key. +# volatile-ttl -> Remove the key with the nearest expire time (minor TTL) +# noeviction -> Don't evict anything, just return an error on write operations. +# +# LRU means Least Recently Used +# LFU means Least Frequently Used +# +# Both LRU, LFU and volatile-ttl are implemented using approximated +# randomized algorithms. +# +# Note: with any of the above policies, Redis will return an error on write +# operations, when there are no suitable keys for eviction. +# +# At the date of writing these commands are: set setnx setex append +# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd +# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby +# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby +# getset mset msetnx exec sort +# +# The default is: +# +# maxmemory-policy noeviction + +# LRU, LFU and minimal TTL algorithms are not precise algorithms but approximated +# algorithms (in order to save memory), so you can tune it for speed or +# accuracy. For default Redis will check five keys and pick the one that was +# used less recently, you can change the sample size using the following +# configuration directive. +# +# The default of 5 produces good enough results. 10 Approximates very closely +# true LRU but costs more CPU. 3 is faster but not very accurate. +# +# maxmemory-samples 5 + +############################# LAZY FREEING #################################### + +# Redis has two primitives to delete keys. One is called DEL and is a blocking +# deletion of the object. It means that the server stops processing new commands +# in order to reclaim all the memory associated with an object in a synchronous +# way. If the key deleted is associated with a small object, the time needed +# in order to execute the DEL command is very small and comparable to most other +# O(1) or O(log_N) commands in Redis. However if the key is associated with an +# aggregated value containing millions of elements, the server can block for +# a long time (even seconds) in order to complete the operation. +# +# For the above reasons Redis also offers non blocking deletion primitives +# such as UNLINK (non blocking DEL) and the ASYNC option of FLUSHALL and +# FLUSHDB commands, in order to reclaim memory in background. Those commands +# are executed in constant time. Another thread will incrementally free the +# object in the background as fast as possible. +# +# DEL, UNLINK and ASYNC option of FLUSHALL and FLUSHDB are user-controlled. +# It's up to the design of the application to understand when it is a good +# idea to use one or the other. However the Redis server sometimes has to +# delete keys or flush the whole database as a side effect of other operations. +# Specifically Redis deletes objects independently of a user call in the +# following scenarios: +# +# 1) On eviction, because of the maxmemory and maxmemory policy configurations, +# in order to make room for new data, without going over the specified +# memory limit. +# 2) Because of expire: when a key with an associated time to live (see the +# EXPIRE command) must be deleted from memory. +# 3) Because of a side effect of a command that stores data on a key that may +# already exist. For example the RENAME command may delete the old key +# content when it is replaced with another one. Similarly SUNIONSTORE +# or SORT with STORE option may delete existing keys. The SET command +# itself removes any old content of the specified key in order to replace +# it with the specified string. +# 4) During replication, when a slave performs a full resynchronization with +# its master, the content of the whole database is removed in order to +# load the RDB file just transfered. +# +# In all the above cases the default is to delete objects in a blocking way, +# like if DEL was called. However you can configure each case specifically +# in order to instead release memory in a non-blocking way like if UNLINK +# was called, using the following configuration directives: + +lazyfree-lazy-eviction no +lazyfree-lazy-expire no +lazyfree-lazy-server-del no +slave-lazy-flush no + +############################## APPEND ONLY MODE ############################### + +# By default Redis asynchronously dumps the dataset on disk. This mode is +# good enough in many applications, but an issue with the Redis process or +# a power outage may result into a few minutes of writes lost (depending on +# the configured save points). +# +# The Append Only File is an alternative persistence mode that provides +# much better durability. For instance using the default data fsync policy +# (see later in the config file) Redis can lose just one second of writes in a +# dramatic event like a server power outage, or a single write if something +# wrong with the Redis process itself happens, but the operating system is +# still running correctly. +# +# AOF and RDB persistence can be enabled at the same time without problems. +# If the AOF is enabled on startup Redis will load the AOF, that is the file +# with the better durability guarantees. +# +# Please check http://redis.io/topics/persistence for more information. + +appendonly no + +# The name of the append only file (default: "appendonly.aof") + +appendfilename "appendonly.aof" + +# The fsync() call tells the Operating System to actually write data on disk +# instead of waiting for more data in the output buffer. Some OS will really flush +# data on disk, some other OS will just try to do it ASAP. +# +# Redis supports three different modes: +# +# no: don't fsync, just let the OS flush the data when it wants. Faster. +# always: fsync after every write to the append only log. Slow, Safest. +# everysec: fsync only one time every second. Compromise. +# +# The default is "everysec", as that's usually the right compromise between +# speed and data safety. It's up to you to understand if you can relax this to +# "no" that will let the operating system flush the output buffer when +# it wants, for better performances (but if you can live with the idea of +# some data loss consider the default persistence mode that's snapshotting), +# or on the contrary, use "always" that's very slow but a bit safer than +# everysec. +# +# More details please check the following article: +# http://antirez.com/post/redis-persistence-demystified.html +# +# If unsure, use "everysec". + +# appendfsync always +appendfsync everysec +# appendfsync no + +# When the AOF fsync policy is set to always or everysec, and a background +# saving process (a background save or AOF log background rewriting) is +# performing a lot of I/O against the disk, in some Linux configurations +# Redis may block too long on the fsync() call. Note that there is no fix for +# this currently, as even performing fsync in a different thread will block +# our synchronous write(2) call. +# +# In order to mitigate this problem it's possible to use the following option +# that will prevent fsync() from being called in the main process while a +# BGSAVE or BGREWRITEAOF is in progress. +# +# This means that while another child is saving, the durability of Redis is +# the same as "appendfsync none". In practical terms, this means that it is +# possible to lose up to 30 seconds of log in the worst scenario (with the +# default Linux settings). +# +# If you have latency problems turn this to "yes". Otherwise leave it as +# "no" that is the safest pick from the point of view of durability. + +no-appendfsync-on-rewrite no + +# Automatic rewrite of the append only file. +# Redis is able to automatically rewrite the log file implicitly calling +# BGREWRITEAOF when the AOF log size grows by the specified percentage. +# +# This is how it works: Redis remembers the size of the AOF file after the +# latest rewrite (if no rewrite has happened since the restart, the size of +# the AOF at startup is used). +# +# This base size is compared to the current size. If the current size is +# bigger than the specified percentage, the rewrite is triggered. Also +# you need to specify a minimal size for the AOF file to be rewritten, this +# is useful to avoid rewriting the AOF file even if the percentage increase +# is reached but it is still pretty small. +# +# Specify a percentage of zero in order to disable the automatic AOF +# rewrite feature. + +auto-aof-rewrite-percentage 100 +auto-aof-rewrite-min-size 64mb + +# An AOF file may be found to be truncated at the end during the Redis +# startup process, when the AOF data gets loaded back into memory. +# This may happen when the system where Redis is running +# crashes, especially when an ext4 filesystem is mounted without the +# data=ordered option (however this can't happen when Redis itself +# crashes or aborts but the operating system still works correctly). +# +# Redis can either exit with an error when this happens, or load as much +# data as possible (the default now) and start if the AOF file is found +# to be truncated at the end. The following option controls this behavior. +# +# If aof-load-truncated is set to yes, a truncated AOF file is loaded and +# the Redis server starts emitting a log to inform the user of the event. +# Otherwise if the option is set to no, the server aborts with an error +# and refuses to start. When the option is set to no, the user requires +# to fix the AOF file using the "redis-check-aof" utility before to restart +# the server. +# +# Note that if the AOF file will be found to be corrupted in the middle +# the server will still exit with an error. This option only applies when +# Redis will try to read more data from the AOF file but not enough bytes +# will be found. +aof-load-truncated yes + +# When rewriting the AOF file, Redis is able to use an RDB preamble in the +# AOF file for faster rewrites and recoveries. When this option is turned +# on the rewritten AOF file is composed of two different stanzas: +# +# [RDB file][AOF tail] +# +# When loading Redis recognizes that the AOF file starts with the "REDIS" +# string and loads the prefixed RDB file, and continues loading the AOF +# tail. +# +# This is currently turned off by default in order to avoid the surprise +# of a format change, but will at some point be used as the default. +aof-use-rdb-preamble no + +################################ LUA SCRIPTING ############################### + +# Max execution time of a Lua script in milliseconds. +# +# If the maximum execution time is reached Redis will log that a script is +# still in execution after the maximum allowed time and will start to +# reply to queries with an error. +# +# When a long running script exceeds the maximum execution time only the +# SCRIPT KILL and SHUTDOWN NOSAVE commands are available. The first can be +# used to stop a script that did not yet called write commands. The second +# is the only way to shut down the server in the case a write command was +# already issued by the script but the user doesn't want to wait for the natural +# termination of the script. +# +# Set it to 0 or a negative value for unlimited execution without warnings. +lua-time-limit 5000 + +################################ REDIS CLUSTER ############################### +# +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# WARNING EXPERIMENTAL: Redis Cluster is considered to be stable code, however +# in order to mark it as "mature" we need to wait for a non trivial percentage +# of users to deploy it in production. +# ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +# +# Normal Redis instances can't be part of a Redis Cluster; only nodes that are +# started as cluster nodes can. In order to start a Redis instance as a +# cluster node enable the cluster support uncommenting the following: +# +# cluster-enabled yes + +# Every cluster node has a cluster configuration file. This file is not +# intended to be edited by hand. It is created and updated by Redis nodes. +# Every Redis Cluster node requires a different cluster configuration file. +# Make sure that instances running in the same system do not have +# overlapping cluster configuration file names. +# +# cluster-config-file nodes-6379.conf + +# Cluster node timeout is the amount of milliseconds a node must be unreachable +# for it to be considered in failure state. +# Most other internal time limits are multiple of the node timeout. +# +# cluster-node-timeout 15000 + +# A slave of a failing master will avoid to start a failover if its data +# looks too old. +# +# There is no simple way for a slave to actually have an exact measure of +# its "data age", so the following two checks are performed: +# +# 1) If there are multiple slaves able to failover, they exchange messages +# in order to try to give an advantage to the slave with the best +# replication offset (more data from the master processed). +# Slaves will try to get their rank by offset, and apply to the start +# of the failover a delay proportional to their rank. +# +# 2) Every single slave computes the time of the last interaction with +# its master. This can be the last ping or command received (if the master +# is still in the "connected" state), or the time that elapsed since the +# disconnection with the master (if the replication link is currently down). +# If the last interaction is too old, the slave will not try to failover +# at all. +# +# The point "2" can be tuned by user. Specifically a slave will not perform +# the failover if, since the last interaction with the master, the time +# elapsed is greater than: +# +# (node-timeout * slave-validity-factor) + repl-ping-slave-period +# +# So for example if node-timeout is 30 seconds, and the slave-validity-factor +# is 10, and assuming a default repl-ping-slave-period of 10 seconds, the +# slave will not try to failover if it was not able to talk with the master +# for longer than 310 seconds. +# +# A large slave-validity-factor may allow slaves with too old data to failover +# a master, while a too small value may prevent the cluster from being able to +# elect a slave at all. +# +# For maximum availability, it is possible to set the slave-validity-factor +# to a value of 0, which means, that slaves will always try to failover the +# master regardless of the last time they interacted with the master. +# (However they'll always try to apply a delay proportional to their +# offset rank). +# +# Zero is the only value able to guarantee that when all the partitions heal +# the cluster will always be able to continue. +# +# cluster-slave-validity-factor 10 + +# Cluster slaves are able to migrate to orphaned masters, that are masters +# that are left without working slaves. This improves the cluster ability +# to resist to failures as otherwise an orphaned master can't be failed over +# in case of failure if it has no working slaves. +# +# Slaves migrate to orphaned masters only if there are still at least a +# given number of other working slaves for their old master. This number +# is the "migration barrier". A migration barrier of 1 means that a slave +# will migrate only if there is at least 1 other working slave for its master +# and so forth. It usually reflects the number of slaves you want for every +# master in your cluster. +# +# Default is 1 (slaves migrate only if their masters remain with at least +# one slave). To disable migration just set it to a very large value. +# A value of 0 can be set but is useful only for debugging and dangerous +# in production. +# +# cluster-migration-barrier 1 + +# By default Redis Cluster nodes stop accepting queries if they detect there +# is at least an hash slot uncovered (no available node is serving it). +# This way if the cluster is partially down (for example a range of hash slots +# are no longer covered) all the cluster becomes, eventually, unavailable. +# It automatically returns available as soon as all the slots are covered again. +# +# However sometimes you want the subset of the cluster which is working, +# to continue to accept queries for the part of the key space that is still +# covered. In order to do so, just set the cluster-require-full-coverage +# option to no. +# +# cluster-require-full-coverage yes + +# This option, when set to yes, prevents slaves from trying to failover its +# master during master failures. However the master can still perform a +# manual failover, if forced to do so. +# +# This is useful in different scenarios, especially in the case of multiple +# data center operations, where we want one side to never be promoted if not +# in the case of a total DC failure. +# +# cluster-slave-no-failover no + +# In order to setup your cluster make sure to read the documentation +# available at http://redis.io web site. + +########################## CLUSTER DOCKER/NAT support ######################## + +# In certain deployments, Redis Cluster nodes address discovery fails, because +# addresses are NAT-ted or because ports are forwarded (the typical case is +# Docker and other containers). +# +# In order to make Redis Cluster working in such environments, a static +# configuration where each node knows its public address is needed. The +# following two options are used for this scope, and are: +# +# * cluster-announce-ip +# * cluster-announce-port +# * cluster-announce-bus-port +# +# Each instruct the node about its address, client port, and cluster message +# bus port. The information is then published in the header of the bus packets +# so that other nodes will be able to correctly map the address of the node +# publishing the information. +# +# If the above options are not used, the normal Redis Cluster auto-detection +# will be used instead. +# +# Note that when remapped, the bus port may not be at the fixed offset of +# clients port + 10000, so you can specify any port and bus-port depending +# on how they get remapped. If the bus-port is not set, a fixed offset of +# 10000 will be used as usually. +# +# Example: +# +# cluster-announce-ip 10.1.1.5 +# cluster-announce-port 6379 +# cluster-announce-bus-port 6380 + +################################## SLOW LOG ################################### + +# The Redis Slow Log is a system to log queries that exceeded a specified +# execution time. The execution time does not include the I/O operations +# like talking with the client, sending the reply and so forth, +# but just the time needed to actually execute the command (this is the only +# stage of command execution where the thread is blocked and can not serve +# other requests in the meantime). +# +# You can configure the slow log with two parameters: one tells Redis +# what is the execution time, in microseconds, to exceed in order for the +# command to get logged, and the other parameter is the length of the +# slow log. When a new command is logged the oldest one is removed from the +# queue of logged commands. + +# The following time is expressed in microseconds, so 1000000 is equivalent +# to one second. Note that a negative number disables the slow log, while +# a value of zero forces the logging of every command. +slowlog-log-slower-than 10000 + +# There is no limit to this length. Just be aware that it will consume memory. +# You can reclaim memory used by the slow log with SLOWLOG RESET. +slowlog-max-len 128 + +################################ LATENCY MONITOR ############################## + +# The Redis latency monitoring subsystem samples different operations +# at runtime in order to collect data related to possible sources of +# latency of a Redis instance. +# +# Via the LATENCY command this information is available to the user that can +# print graphs and obtain reports. +# +# The system only logs operations that were performed in a time equal or +# greater than the amount of milliseconds specified via the +# latency-monitor-threshold configuration directive. When its value is set +# to zero, the latency monitor is turned off. +# +# By default latency monitoring is disabled since it is mostly not needed +# if you don't have latency issues, and collecting data has a performance +# impact, that while very small, can be measured under big load. Latency +# monitoring can easily be enabled at runtime using the command +# "CONFIG SET latency-monitor-threshold " if needed. +latency-monitor-threshold 0 + +############################# EVENT NOTIFICATION ############################## + +# Redis can notify Pub/Sub clients about events happening in the key space. +# This feature is documented at http://redis.io/topics/notifications +# +# For instance if keyspace events notification is enabled, and a client +# performs a DEL operation on key "foo" stored in the Database 0, two +# messages will be published via Pub/Sub: +# +# PUBLISH __keyspace@0__:foo del +# PUBLISH __keyevent@0__:del foo +# +# It is possible to select the events that Redis will notify among a set +# of classes. Every class is identified by a single character: +# +# K Keyspace events, published with __keyspace@__ prefix. +# E Keyevent events, published with __keyevent@__ prefix. +# g Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ... +# $ String commands +# l List commands +# s Set commands +# h Hash commands +# z Sorted set commands +# x Expired events (events generated every time a key expires) +# e Evicted events (events generated when a key is evicted for maxmemory) +# A Alias for g$lshzxe, so that the "AKE" string means all the events. +# +# The "notify-keyspace-events" takes as argument a string that is composed +# of zero or multiple characters. The empty string means that notifications +# are disabled. +# +# Example: to enable list and generic events, from the point of view of the +# event name, use: +# +# notify-keyspace-events Elg +# +# Example 2: to get the stream of the expired keys subscribing to channel +# name __keyevent@0__:expired use: +# +# notify-keyspace-events Ex +# +# By default all notifications are disabled because most users don't need +# this feature and the feature has some overhead. Note that if you don't +# specify at least one of K or E, no events will be delivered. +notify-keyspace-events "" + +############################### ADVANCED CONFIG ############################### + +# Hashes are encoded using a memory efficient data structure when they have a +# small number of entries, and the biggest entry does not exceed a given +# threshold. These thresholds can be configured using the following directives. +hash-max-ziplist-entries 512 +hash-max-ziplist-value 64 + +# Lists are also encoded in a special way to save a lot of space. +# The number of entries allowed per internal list node can be specified +# as a fixed maximum size or a maximum number of elements. +# For a fixed maximum size, use -5 through -1, meaning: +# -5: max size: 64 Kb <-- not recommended for normal workloads +# -4: max size: 32 Kb <-- not recommended +# -3: max size: 16 Kb <-- probably not recommended +# -2: max size: 8 Kb <-- good +# -1: max size: 4 Kb <-- good +# Positive numbers mean store up to _exactly_ that number of elements +# per list node. +# The highest performing option is usually -2 (8 Kb size) or -1 (4 Kb size), +# but if your use case is unique, adjust the settings as necessary. +list-max-ziplist-size -2 + +# Lists may also be compressed. +# Compress depth is the number of quicklist ziplist nodes from *each* side of +# the list to *exclude* from compression. The head and tail of the list +# are always uncompressed for fast push/pop operations. Settings are: +# 0: disable all list compression +# 1: depth 1 means "don't start compressing until after 1 node into the list, +# going from either the head or tail" +# So: [head]->node->node->...->node->[tail] +# [head], [tail] will always be uncompressed; inner nodes will compress. +# 2: [head]->[next]->node->node->...->node->[prev]->[tail] +# 2 here means: don't compress head or head->next or tail->prev or tail, +# but compress all nodes between them. +# 3: [head]->[next]->[next]->node->node->...->node->[prev]->[prev]->[tail] +# etc. +list-compress-depth 0 + +# Sets have a special encoding in just one case: when a set is composed +# of just strings that happen to be integers in radix 10 in the range +# of 64 bit signed integers. +# The following configuration setting sets the limit in the size of the +# set in order to use this special memory saving encoding. +set-max-intset-entries 512 + +# Similarly to hashes and lists, sorted sets are also specially encoded in +# order to save a lot of space. This encoding is only used when the length and +# elements of a sorted set are below the following limits: +zset-max-ziplist-entries 128 +zset-max-ziplist-value 64 + +# HyperLogLog sparse representation bytes limit. The limit includes the +# 16 bytes header. When an HyperLogLog using the sparse representation crosses +# this limit, it is converted into the dense representation. +# +# A value greater than 16000 is totally useless, since at that point the +# dense representation is more memory efficient. +# +# The suggested value is ~ 3000 in order to have the benefits of +# the space efficient encoding without slowing down too much PFADD, +# which is O(N) with the sparse encoding. The value can be raised to +# ~ 10000 when CPU is not a concern, but space is, and the data set is +# composed of many HyperLogLogs with cardinality in the 0 - 15000 range. +hll-sparse-max-bytes 3000 + +# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in +# order to help rehashing the main Redis hash table (the one mapping top-level +# keys to values). The hash table implementation Redis uses (see dict.c) +# performs a lazy rehashing: the more operation you run into a hash table +# that is rehashing, the more rehashing "steps" are performed, so if the +# server is idle the rehashing is never complete and some more memory is used +# by the hash table. +# +# The default is to use this millisecond 10 times every second in order to +# actively rehash the main dictionaries, freeing memory when possible. +# +# If unsure: +# use "activerehashing no" if you have hard latency requirements and it is +# not a good thing in your environment that Redis can reply from time to time +# to queries with 2 milliseconds delay. +# +# use "activerehashing yes" if you don't have such hard requirements but +# want to free memory asap when possible. +activerehashing yes + +# The client output buffer limits can be used to force disconnection of clients +# that are not reading data from the server fast enough for some reason (a +# common reason is that a Pub/Sub client can't consume messages as fast as the +# publisher can produce them). +# +# The limit can be set differently for the three different classes of clients: +# +# normal -> normal clients including MONITOR clients +# slave -> slave clients +# pubsub -> clients subscribed to at least one pubsub channel or pattern +# +# The syntax of every client-output-buffer-limit directive is the following: +# +# client-output-buffer-limit +# +# A client is immediately disconnected once the hard limit is reached, or if +# the soft limit is reached and remains reached for the specified number of +# seconds (continuously). +# So for instance if the hard limit is 32 megabytes and the soft limit is +# 16 megabytes / 10 seconds, the client will get disconnected immediately +# if the size of the output buffers reach 32 megabytes, but will also get +# disconnected if the client reaches 16 megabytes and continuously overcomes +# the limit for 10 seconds. +# +# By default normal clients are not limited because they don't receive data +# without asking (in a push way), but just after a request, so only +# asynchronous clients may create a scenario where data is requested faster +# than it can read. +# +# Instead there is a default limit for pubsub and slave clients, since +# subscribers and slaves receive data in a push fashion. +# +# Both the hard or the soft limit can be disabled by setting them to zero. +client-output-buffer-limit normal 0 0 0 +client-output-buffer-limit slave 256mb 64mb 60 +client-output-buffer-limit pubsub 32mb 8mb 60 + +# Client query buffers accumulate new commands. They are limited to a fixed +# amount by default in order to avoid that a protocol desynchronization (for +# instance due to a bug in the client) will lead to unbound memory usage in +# the query buffer. However you can configure it here if you have very special +# needs, such us huge multi/exec requests or alike. +# +# client-query-buffer-limit 1gb + +# In the Redis protocol, bulk requests, that are, elements representing single +# strings, are normally limited ot 512 mb. However you can change this limit +# here. +# +# proto-max-bulk-len 512mb + +# Redis calls an internal function to perform many background tasks, like +# closing connections of clients in timeout, purging expired keys that are +# never requested, and so forth. +# +# Not all tasks are performed with the same frequency, but Redis checks for +# tasks to perform according to the specified "hz" value. +# +# By default "hz" is set to 10. Raising the value will use more CPU when +# Redis is idle, but at the same time will make Redis more responsive when +# there are many keys expiring at the same time, and timeouts may be +# handled with more precision. +# +# The range is between 1 and 500, however a value over 100 is usually not +# a good idea. Most users should use the default of 10 and raise this up to +# 100 only in environments where very low latency is required. +hz 10 + +# When a child rewrites the AOF file, if the following option is enabled +# the file will be fsync-ed every 32 MB of data generated. This is useful +# in order to commit the file to the disk more incrementally and avoid +# big latency spikes. +aof-rewrite-incremental-fsync yes + +# Redis LFU eviction (see maxmemory setting) can be tuned. However it is a good +# idea to start with the default settings and only change them after investigating +# how to improve the performances and how the keys LFU change over time, which +# is possible to inspect via the OBJECT FREQ command. +# +# There are two tunable parameters in the Redis LFU implementation: the +# counter logarithm factor and the counter decay time. It is important to +# understand what the two parameters mean before changing them. +# +# The LFU counter is just 8 bits per key, it's maximum value is 255, so Redis +# uses a probabilistic increment with logarithmic behavior. Given the value +# of the old counter, when a key is accessed, the counter is incremented in +# this way: +# +# 1. A random number R between 0 and 1 is extracted. +# 2. A probability P is calculated as 1/(old_value*lfu_log_factor+1). +# 3. The counter is incremented only if R < P. +# +# The default lfu-log-factor is 10. This is a table of how the frequency +# counter changes with a different number of accesses with different +# logarithmic factors: +# +# +--------+------------+------------+------------+------------+------------+ +# | factor | 100 hits | 1000 hits | 100K hits | 1M hits | 10M hits | +# +--------+------------+------------+------------+------------+------------+ +# | 0 | 104 | 255 | 255 | 255 | 255 | +# +--------+------------+------------+------------+------------+------------+ +# | 1 | 18 | 49 | 255 | 255 | 255 | +# +--------+------------+------------+------------+------------+------------+ +# | 10 | 10 | 18 | 142 | 255 | 255 | +# +--------+------------+------------+------------+------------+------------+ +# | 100 | 8 | 11 | 49 | 143 | 255 | +# +--------+------------+------------+------------+------------+------------+ +# +# NOTE: The above table was obtained by running the following commands: +# +# redis-benchmark -n 1000000 incr foo +# redis-cli object freq foo +# +# NOTE 2: The counter initial value is 5 in order to give new objects a chance +# to accumulate hits. +# +# The counter decay time is the time, in minutes, that must elapse in order +# for the key counter to be divided by two (or decremented if it has a value +# less <= 10). +# +# The default value for the lfu-decay-time is 1. A Special value of 0 means to +# decay the counter every time it happens to be scanned. +# +# lfu-log-factor 10 +# lfu-decay-time 1 + +########################### ACTIVE DEFRAGMENTATION ####################### +# +# WARNING THIS FEATURE IS EXPERIMENTAL. However it was stress tested +# even in production and manually tested by multiple engineers for some +# time. +# +# What is active defragmentation? +# ------------------------------- +# +# Active (online) defragmentation allows a Redis server to compact the +# spaces left between small allocations and deallocations of data in memory, +# thus allowing to reclaim back memory. +# +# Fragmentation is a natural process that happens with every allocator (but +# less so with Jemalloc, fortunately) and certain workloads. Normally a server +# restart is needed in order to lower the fragmentation, or at least to flush +# away all the data and create it again. However thanks to this feature +# implemented by Oran Agra for Redis 4.0 this process can happen at runtime +# in an "hot" way, while the server is running. +# +# Basically when the fragmentation is over a certain level (see the +# configuration options below) Redis will start to create new copies of the +# values in contiguous memory regions by exploiting certain specific Jemalloc +# features (in order to understand if an allocation is causing fragmentation +# and to allocate it in a better place), and at the same time, will release the +# old copies of the data. This process, repeated incrementally for all the keys +# will cause the fragmentation to drop back to normal values. +# +# Important things to understand: +# +# 1. This feature is disabled by default, and only works if you compiled Redis +# to use the copy of Jemalloc we ship with the source code of Redis. +# This is the default with Linux builds. +# +# 2. You never need to enable this feature if you don't have fragmentation +# issues. +# +# 3. Once you experience fragmentation, you can enable this feature when +# needed with the command "CONFIG SET activedefrag yes". +# +# The configuration parameters are able to fine tune the behavior of the +# defragmentation process. If you are not sure about what they mean it is +# a good idea to leave the defaults untouched. + +# Enabled active defragmentation +# activedefrag yes + +# Minimum amount of fragmentation waste to start active defrag +# active-defrag-ignore-bytes 100mb + +# Minimum percentage of fragmentation to start active defrag +# active-defrag-threshold-lower 10 + +# Maximum percentage of fragmentation at which we use maximum effort +# active-defrag-threshold-upper 100 + +# Minimal effort for defrag in CPU percentage +# active-defrag-cycle-min 25 + +# Maximal effort for defrag in CPU percentage +# active-defrag-cycle-max 75 + diff --git a/example_code/reflect/dep.h b/example_code/reflect/dep.h new file mode 100755 index 0000000..33be381 --- /dev/null +++ b/example_code/reflect/dep.h @@ -0,0 +1,66 @@ +#pragma once + +#include "helper.h" + +class COMM_DEPENDENCY +{ +public: + std::string _name; +}; + +class RPC: public COMM_DEPENDENCY +{ +public: + virtual void send(const std::string& text) = 0; +}; + +class GRPC final : public RPC +{ +public: + void send(const std::string& text) override + { + std::cout << "[GRPC] " << text << std::endl; + // todo + // use grpc to send data + } +}; + +class TRPC final : public RPC +{ +public: + void send(const std::string& text) override + { + std::cout << "[TRPC] " << text << std::endl; + // todo + // use trpc to send data + } +}; + +class LOG: public COMM_DEPENDENCY +{ +public: + virtual void print_log(const std::string& text) = 0; +}; + +class GLOG final : public LOG +{ +public: + void print_log(const std::string& text) override + { + std::cout << "[GLOG] " << text << std::endl; + } +}; + +class XXLOG final: public LOG +{ +public: + void print_log(const std::string& text) override + { + std::cout << "[XXLOG] " << text << std::endl; + } +}; + +REGISTER(GRPC); +REGISTER(TRPC); +REGISTER(GLOG); +REGISTER(XXLOG); diff --git a/example_code/reflect/helper.h b/example_code/reflect/helper.h new file mode 100755 index 0000000..7be2095 --- /dev/null +++ b/example_code/reflect/helper.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include + +class COMM_DEPENDENCY; + +class DEPENDENCY_HELPER +{ +private: + std::map _map_str2obj; + static DEPENDENCY_HELPER* helper; + DEPENDENCY_HELPER() {} + +public: + static DEPENDENCY_HELPER* inst() + { + if (!helper) + { + helper = new DEPENDENCY_HELPER(); + } + return helper; + } + + COMM_DEPENDENCY* get_by_name(std::string name) + { + if (_map_str2obj.find(name) != _map_str2obj.end()) + { + return _map_str2obj[name]; + } + return nullptr; + } + + void push(std::string name, COMM_DEPENDENCY * obj) + { + _map_str2obj[name] = obj; + } +}; + +DEPENDENCY_HELPER* DEPENDENCY_HELPER::helper = nullptr; + +#define REGISTER(CLASS_TYPE) \ + class CLASS_TYPE##Generator {\ + public:\ + CLASS_TYPE##Generator() {\ + DEPENDENCY_HELPER::inst()->push(#CLASS_TYPE, new CLASS_TYPE());\ + }\ + };\ + CLASS_TYPE##Generator* CLASS_TYPE##Inst = new CLASS_TYPE##Generator(); diff --git a/example_code/reflect/main.cc b/example_code/reflect/main.cc new file mode 100755 index 0000000..fb160b0 --- /dev/null +++ b/example_code/reflect/main.cc @@ -0,0 +1,48 @@ +#include +#include +#include +#include "helper.h" +#include "dep.h" + +class MY_SERVICE +{ +public: + int deps_init() + { + std::vector name = + { + "GRPC", + "GLOG", + }; + + for (int i = 0; i < name.size(); i++) + { + COMM_DEPENDENCY* obj = DEPENDENCY_HELPER::inst()->get_by_name(name[i]); + if (obj) + { + // init xxx + } + } + return 0; + } + + RPC* get_rpc() + { + RPC* obj = static_cast(DEPENDENCY_HELPER::inst()->get_by_name("GRPC")); + return obj; + } + + LOG* get_log() + { + LOG* obj = static_cast(DEPENDENCY_HELPER::inst()->get_by_name("GLOG")); + return obj; + } +}; + +int main() +{ + MY_SERVICE s; + s.get_rpc()->send("HELLO RPC"); + s.get_log()->print_log("HELLO LOG"); + return 0; +} \ No newline at end of file diff --git a/example_code/shell/cpu.sh b/example_code/shell/cpu.sh new file mode 100755 index 0000000..094e5af --- /dev/null +++ b/example_code/shell/cpu.sh @@ -0,0 +1,68 @@ +#! /bin/bash +PID=18493 + +while getopts "p:" option +do + case "$option" in + p) + PID=$OPTARG + ;; + :|\?) + echo "invalid option: '$option'" + exit 1; + ;; + esac +done + +cpu_core_num=`cat /proc/cpuinfo|grep processor|wc|awk '{print $1}'` + +print_process_cpu_precent() +{ + cpu_total_time1=`cat /proc/stat | head -n1 |awk '{print $2+$3+$4+$5+$6+$7+$8}'` + process_time1=`cat /proc/${PID}/stat | head -n1 | awk '{print $14+$15+$16+$17}'` + sleep 1 + + cpu_total_time2=`cat /proc/stat | head -n1 |awk '{print $2+$3+$4+$5+$6+$7+$8}'` + process_time2=`cat /proc/${PID}/stat | head -n1 | awk '{print $14+$15+$16+$17}'` + + cpu_time=$((cpu_total_time2 - cpu_total_time1)) + process_time=$((process_time2 - process_time1)) + + cpu_percent=$((100 * process_time * cpu_core_num / cpu_time)) + + echo "process : $PID, cpu percent : $cpu_percent" +} + +print_cpu_precent() +{ + n=1 + while [ $n -le $cpu_core_num ] + do + cpu_total_time1=`cat /proc/stat | head -${n} |awk '{print $2+$3+$4+$5+$6+$7+$8}' | tail -1` + cpu_user_time1=`cat /proc/stat | head -${n} |awk '{print $2}' | tail -1` + cpu_sys_time1=`cat /proc/stat | head -${n} |awk '{print $4}' | tail -1` + + sleep 0.2 + cpu_total_time2=`cat /proc/stat | head -${n} |awk '{print $2+$3+$4+$5+$6+$7+$8}' | tail -1` + cpu_user_time2=`cat /proc/stat | head -${n} |awk '{print $2}' | tail -1` + cpu_sys_time2=`cat /proc/stat | head -${n} |awk '{print $4}' | tail -1` + + cpu_time=$((cpu_total_time2 - cpu_total_time1)) + user_time=$((cpu_user_time2 - cpu_user_time1)) + sys_time=$((cpu_sys_time2 - cpu_sys_time1)) + + cpu_user_percent=$((100 * user_time / cpu_time)) + cpu_sys_percent=$((100 * sys_time / cpu_time)) + + echo "[cpu $n] user percent : $cpu_user_percent, syc percent $cpu_sys_percent" + + let n++ + done + sleep 1 +} + +while((1)) +do +print_process_cpu_precent +print_cpu_precent +done \ No newline at end of file diff --git a/example_code/test/coverage/bin/main b/example_code/test/coverage/bin/main new file mode 100755 index 0000000..392309c Binary files /dev/null and b/example_code/test/coverage/bin/main differ diff --git a/example_code/test/coverage/src/.main.c.gcov.swp b/example_code/test/coverage/src/.main.c.gcov.swp new file mode 100755 index 0000000..13782ae Binary files /dev/null and b/example_code/test/coverage/src/.main.c.gcov.swp differ diff --git a/example_code/test/coverage/src/Makefile b/example_code/test/coverage/src/Makefile new file mode 100755 index 0000000..beaad4b --- /dev/null +++ b/example_code/test/coverage/src/Makefile @@ -0,0 +1,21 @@ +APP_EXE=../bin/main + +all: $(APP_EXE) + +CFLAGS += -Wsign-conversion -Wpedantic -Wall -DNDEBUG -O3 +CFLAGS += -g --coverage + +$(APP_EXE):main.c module_a.c module_b.c Makefile + g++ -std=c++11 $(CFLAGS) main.c module_a.c module_b.c -o $(APP_EXE) + +clean: + rm $(APP_EXE) + rm *.gcno + +start: + ./$(APP_EXE) + +coverage: + gcov module_a.c + gcov module_b.c + gcov main.c \ No newline at end of file diff --git a/example_code/test/coverage/src/main.c b/example_code/test/coverage/src/main.c new file mode 100755 index 0000000..165c04b --- /dev/null +++ b/example_code/test/coverage/src/main.c @@ -0,0 +1,12 @@ +#include +#include "module_a.h" +#include "module_b.h" + +int main() +{ + int val = 50; + func_a(val); + func_b(val); + + return 0; +} \ No newline at end of file diff --git a/example_code/test/coverage/src/main.c.gcov b/example_code/test/coverage/src/main.c.gcov new file mode 100755 index 0000000..c263b1f --- /dev/null +++ b/example_code/test/coverage/src/main.c.gcov @@ -0,0 +1,17 @@ + -: 0:Source:main.c + -: 0:Graph:main.gcno + -: 0:Data:main.gcda + -: 0:Runs:1 + -: 0:Programs:1 + -: 1:#include + -: 2:#include "module_a.h" + -: 3:#include "module_b.h" + -: 4: + 1: 5:int main() + -: 6:{ + 1: 7: int val = 50; + 1: 8: func_a(val); + 1: 9: func_b(val); + -: 10: + 1: 11: return 0; + -: 12:} diff --git a/example_code/test/coverage/src/main.gcda b/example_code/test/coverage/src/main.gcda new file mode 100755 index 0000000..dbae869 Binary files /dev/null and b/example_code/test/coverage/src/main.gcda differ diff --git a/example_code/test/coverage/src/main.gcno b/example_code/test/coverage/src/main.gcno new file mode 100755 index 0000000..ad16a36 Binary files /dev/null and b/example_code/test/coverage/src/main.gcno differ diff --git a/example_code/test/coverage/src/module_a.c b/example_code/test/coverage/src/module_a.c new file mode 100755 index 0000000..9db5c58 --- /dev/null +++ b/example_code/test/coverage/src/module_a.c @@ -0,0 +1,15 @@ +#include +#include "module_a.h" + +int func_a(int &val) +{ + if (val > 100) + { + val = val * 100; + } + else + { + val++; + } + return 0; +} \ No newline at end of file diff --git a/example_code/test/coverage/src/module_a.c.gcov b/example_code/test/coverage/src/module_a.c.gcov new file mode 100755 index 0000000..1ceea4a --- /dev/null +++ b/example_code/test/coverage/src/module_a.c.gcov @@ -0,0 +1,20 @@ + -: 0:Source:module_a.c + -: 0:Graph:module_a.gcno + -: 0:Data:module_a.gcda + -: 0:Runs:1 + -: 0:Programs:1 + -: 1:#include + -: 2:#include "module_a.h" + -: 3: + 1: 4:int func_a(int &val) + -: 5:{ + 1: 6: if (val > 100) + -: 7: { + #####: 8: val = val * 100; + -: 9: } + -: 10: else + -: 11: { + 1: 12: val++; + -: 13: } + 1: 14: return 0; + -: 15:} diff --git a/example_code/test/coverage/src/module_a.gcda b/example_code/test/coverage/src/module_a.gcda new file mode 100755 index 0000000..4695b12 Binary files /dev/null and b/example_code/test/coverage/src/module_a.gcda differ diff --git a/example_code/test/coverage/src/module_a.gcno b/example_code/test/coverage/src/module_a.gcno new file mode 100755 index 0000000..9a437fd Binary files /dev/null and b/example_code/test/coverage/src/module_a.gcno differ diff --git a/example_code/test/coverage/src/module_a.h b/example_code/test/coverage/src/module_a.h new file mode 100755 index 0000000..b6b3e0f --- /dev/null +++ b/example_code/test/coverage/src/module_a.h @@ -0,0 +1,6 @@ +#ifndef __MODULE_A_H__ +#define __MODULE_A_H__ + +int func_a(int &val); + +#endif \ No newline at end of file diff --git a/example_code/test/coverage/src/module_b.c b/example_code/test/coverage/src/module_b.c new file mode 100755 index 0000000..e70fd7c --- /dev/null +++ b/example_code/test/coverage/src/module_b.c @@ -0,0 +1,15 @@ +#include +#include "module_b.h" + +int func_b(int &val) +{ + if (val > 500) + { + val = val * 500; + } + else + { + val++; + } + return 0; +} \ No newline at end of file diff --git a/example_code/test/coverage/src/module_b.gcda b/example_code/test/coverage/src/module_b.gcda new file mode 100755 index 0000000..f8d1dca Binary files /dev/null and b/example_code/test/coverage/src/module_b.gcda differ diff --git a/example_code/test/coverage/src/module_b.gcno b/example_code/test/coverage/src/module_b.gcno new file mode 100755 index 0000000..ff7d861 Binary files /dev/null and b/example_code/test/coverage/src/module_b.gcno differ diff --git a/example_code/test/coverage/src/module_b.h b/example_code/test/coverage/src/module_b.h new file mode 100755 index 0000000..9fdff1e --- /dev/null +++ b/example_code/test/coverage/src/module_b.h @@ -0,0 +1,6 @@ +#ifndef __MODULE_B_H__ +#define __MODULE_B_H__ + +int func_b(int &val); + +#endif \ No newline at end of file diff --git a/example_code/test/gmock/FooInterface.h b/example_code/test/gmock/FooInterface.h new file mode 100755 index 0000000..6eac1b5 --- /dev/null +++ b/example_code/test/gmock/FooInterface.h @@ -0,0 +1,24 @@ +#ifndef FOOINTERFACE_H_ +#define FOOINTERFACE_H_ + +#include + +namespace seamless { + +class FooInterface { +public: + virtual ~FooInterface() {} + +public: + virtual std::string get_from_rpc() = 0; + + std::string get_result() + { + std::string str = "reuslt is "; + return str + get_from_rpc(); + } +}; + +} // namespace seamless + +#endif // FOOINTERFACE_H_ \ No newline at end of file diff --git a/example_code/test/gmock/FooMain.cc b/example_code/test/gmock/FooMain.cc new file mode 100755 index 0000000..9a92cbf --- /dev/null +++ b/example_code/test/gmock/FooMain.cc @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include + +#include "FooMock.h" + +using namespace seamless; +using namespace std; + +using ::testing::Return; + +TEST(mock_test, get_result) +{ + MockFoo mockFoo; + string value = "Hello World!"; + EXPECT_CALL(mockFoo, get_from_rpc()) + .WillRepeatedly(Return(value)); + + string result1 = mockFoo.get_from_rpc(); + string result2 = mockFoo.get_result(); + + cout << "get_result() return : " << result1 << endl; + cout << "get_result() return : " << result2 << endl; + + EXPECT_EQ(value, result1); + EXPECT_EQ("reuslt is " + value, result2); +} + +int main(int argc, char** argv) +{ + ::testing::InitGoogleMock(&argc, argv); + return RUN_ALL_TESTS(); +} + +// g++ FooMain.cc -lpthread -lgtest -lgmock \ No newline at end of file diff --git a/example_code/test/gmock/FooMock.h b/example_code/test/gmock/FooMock.h new file mode 100755 index 0000000..ec0ad7a --- /dev/null +++ b/example_code/test/gmock/FooMock.h @@ -0,0 +1,18 @@ +#ifndef MOCKFOO_H_ +#define MOCKFOO_H_ + +#include +#include +#include "FooInterface.h" + +namespace seamless { + +class MockFoo: public FooInterface +{ + public: + MOCK_METHOD0(get_from_rpc, std::string()); +}; + +} // namespace seamless + +#endif // MOCKFOO_H_ \ No newline at end of file diff --git a/example_code/thread_pool b/example_code/thread_pool new file mode 160000 index 0000000..f21aaee --- /dev/null +++ b/example_code/thread_pool @@ -0,0 +1 @@ +Subproject commit f21aaee90eb7b8755528fe0bffb1a7683dccb36b diff --git "a/note/C++\345\255\227\350\212\202\345\257\271\351\275\220.md" "b/note/C++\345\255\227\350\212\202\345\257\271\351\275\220.md" new file mode 100755 index 0000000..2fcd30b --- /dev/null +++ "b/note/C++\345\255\227\350\212\202\345\257\271\351\275\220.md" @@ -0,0 +1,118 @@ +# c++ 字节对齐 + +## 目录 +* [为什么需要字节对齐](#为什么需要字节对齐) +* [字节对齐的原理](#字节对齐的原理) + +--- + +## 为什么需要字节对齐 + +在cpu访问内存的时候,访问内存的最小单位不是字节,而是字长(4个字节,8个字节,或其他)。如果没有字节对齐的机制,可能访问一个int(4字节的)在某些情况需要cpu访问两次内存,而且需要多余的cpu指令剔除掉不需要的数据。 + +而在网络的传输中,就一般不需要字节对齐。因为,在网络中需要尽可能的降低数据传输的流量。字节对齐的机制,会加入多余的填充字节,导致网络流量变大。 + +## 字节对齐的原理 + +对齐系数,gcc的默认对对齐系数是4,#pragma pack(4)。 + +假设 对齐系数 = N, 结构体中最长数据类型 = m; + +对齐单位 n = min{N,m} + +字节对齐的规则: +1. 成员对齐值: + + 首个成员的偏置地址(offset) = 0。 + + 假定该成员的类型占字节数 j,那么本成员的偏移地址(offset):min{n, j}的整数倍。 + +2. 整体对齐值: + + 结构体的总大小为 有效对齐值n 的整数倍。如果不是的话,需要进行填充字节。 + +## 验证一下 + +我的机器默认是pack(8), 我先改成pack(4) +``` +#pragma pack(4) +#include + +struct TEST +{ + int val1; + double val2; + char c; +}; + +struct TEST2 +{ + char val1; + char val2; + char val3; + char val4; + char val5; +}; + +int main() +{ + TEST test; + memset(&test, 0, sizeof(test)); + + test.val1 = 1; + test.val2 = 2; + test.c = 'a'; + + std::cout << sizeof(test) << std::endl; // 输出 16 + std::cout << sizeof(test2) << std::endl; // 输出 5 + return 0; +} +``` + +如果改成pack(1),就是13。 + +使用gdb看一下具体的内存分布: +``` +(gdb) p/x test +$3 = {val1 = 0x1, val2 = 0x2, c = 0x61} + +(gdb) x/16xb &test +0x7ffffffee270: 0x01 0x00 0x00 0x00 0x02 0x00 0x00 0x00 +0x7ffffffee278: 0x00 0x00 0x00 0x00 0x61 0x00 0x00 0x00 + ^ ^ + | <--padding--> | + +``` + + +关于gdb的几个命令: +``` +# 打印变量 +gdb +p/x 以16进制打印结构体 +``` + + +examine查看内存,缩写是x +命令的格式是: +``` +x/ +* n表示要打印的多少个单位的内存,默认是1,单位由u定义 +* f表示打印的格式,格式有: + o,octal,八进制; + x,hex,十六进制; + d,decimal,十进制; + u,unsigned decimal,无符号十进制; + t,binary,二进制; + f,float; + a,address; + i,instruction,指令; + c,char,字符; + s,string,字符串 +* u定义单位,b表示1字节,h表示2字节,w表示4字节,g表示8字节 + +示例: +x/16xb 指针 // 打印后面16的字节的数据 +``` + +test branch diff --git "a/note/C++\347\274\226\350\257\221\350\200\227\346\227\266\344\274\230\345\214\226.md" "b/note/C++\347\274\226\350\257\221\350\200\227\346\227\266\344\274\230\345\214\226.md" new file mode 100755 index 0000000..73e73d2 --- /dev/null +++ "b/note/C++\347\274\226\350\257\221\350\200\227\346\227\266\344\274\230\345\214\226.md" @@ -0,0 +1,273 @@ +# C++编译耗时优化 + +大型C++工程项目,都会面临编译耗时较长的问题。整理几招 优化编译时间过长的方法。 + +1. 预编译头文件 + + 在介绍预编译头之前,有必要了解一下C/C++的编译方式。C/C++的编译单元是源文件(带有.c、.cc、.cpp等扩展名的文件),在编译一个源文件之前,预处理器会把这个源文件中所有通过#include指令包含进来的头文件递归地展开,也就是把所有直接或间接包含的头文件原封不动地插入进来。当这个过程结束之后,才开始编译。 + + 这种编译方式的缺点是会使头文件被重复编译。假如有一百个源文件都包含了Windows.h,那么这个头文件会在一百个源文件中展开,它里面的代码会被重复编译了一百次,尽管每次编译的结果都相同。对于具有成千上万个源文件的大型项目来说,重复编译是难以接受的,会浪费大量的编译时间。 + + **为了解决这个问题,预编译头应运而生**。顾名思义,预编译头就是预先把头文件编译好,在编译源文件的时候直接取用这些编译结果,避免对头文件重复编译。这项技术能大幅提高C++的编译速度。 + + +* 预编译头文件使用注意事项: + + 1. 既然预编译头有这样的好处,那么是不是加入预编译的头文件越多越好呢?答案是否定的。上文已经提到,使用预编译头的时候必须在所有源文件中包含预编译头文件,由此造成的影响是,一旦其中的头文件发生了变化,不论这个变化有多细微,整个项目都要重新编译。把一个会被频繁修改的头文件包含到预编译头文件中是非常不明智的做法,因此,理想的选择是下列几乎不会修改的头文件 + + 2. **预编译头文件只能使用一个,不能在一个cpp文件中include多个gch文件。** + + 3. **在cpp文件中,如果要使用gch,gch一定要放在include的第一个文件。** + + 如果不满足2和3,预编译头文件也是没效果啊!!!! + + https://stackoverflow.com/questions/12437955/gcc-and-precompiled-headers/12438040#12438040?newreg=2f0c19d30d2d4dd99dfda4f2aa21dd66 + +* 举个例子 + + ``` + # 假设 main.cpp 是程序的核心逻辑, comm1.cpp comm2.cpp 是两个底层库 并且不经常修改 + # main.cpp 可以使用他们的预编译头文件 + # 这样在编译mian.cpp的时候,预处理阶段 就不会再次展开include这个头文件在找一次了 + ls + comm1.cpp comm1.h comm2.cpp comm2.h comm_header.h main.cpp + ``` + + main.cpp文件入下: (include了底层的头文件) + ``` + $ cat main.cpp + + #include "comm_header.h" + #include + int main() + { + + printf("hello world, val %d\n", comm2_show()); + printf("hello world, val %d\n", comm1_show()); + return 0; + } + ``` + + ``` + # 预编译头文件 ,这里会生成一个gch的文件 + g++ -x c++-header comm_header.h + ``` + + 在生成gch文件之后,再次编译main.cpp的文件,编译器在这里就会先找gch文件,如果找到了就用它。找不到就使用原来的头文件。 + + 然后,也可以使用gcc -H 这个命令查看是否有使用预编译的头文件。 + ``` + $ g++ -H main.cpp + ! comm_header.h.gch + main.cpp + . /usr/include/stdio.h + .. /usr/include/features.h + ... /usr/include/sys/cdefs.h + .... /usr/include/bits/wordsize.h + ... /usr/include/gnu/stubs.h + .... /usr/include/gnu/stubs-64.h + .. /usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stddef.h + .. /usr/include/bits/types.h + ... /usr/include/bits/wordsize.h + ... /usr/include/bits/typesizes.h + .. /usr/include/libio.h + ... /usr/include/_G_config.h + .... /usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stddef.h + .... /usr/include/wchar.h + ... /usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stdarg.h + .. /usr/include/bits/stdio_lim.h + .. /usr/include/bits/sys_errlist.h + Multiple include guards may be useful for: + /usr/include/bits/stdio_lim.h + /usr/include/bits/sys_errlist.h + /usr/include/bits/typesizes.h + /usr/include/gnu/stubs-64.h + /usr/include/gnu/stubs.h + /usr/include/wchar.h + /tmp/ccACOfpF.o: In function `main': + main.cpp:(.text+0x5): undefined reference to `comm2_show()' + main.cpp:(.text+0x1b): undefined reference to `comm1_show()' + collect2: error: ld returned 1 exit status + ``` + + 当删除gch文件后,再次查看,现在找不到gch了,无法使用预编译的结果了,使用原来的正常头文件进行编译。 + ``` + $rm comm_header.h.gch + $g++ -H main.cpp + + . comm_header.h + .. comm1.h + .. comm2.h + . /usr/include/stdio.h + .. /usr/include/features.h + ... /usr/include/sys/cdefs.h + .... /usr/include/bits/wordsize.h + ... /usr/include/gnu/stubs.h + .... /usr/include/gnu/stubs-64.h + .. /usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stddef.h + .. /usr/include/bits/types.h + ... /usr/include/bits/wordsize.h + ... /usr/include/bits/typesizes.h + .. /usr/include/libio.h + ... /usr/include/_G_config.h + .... /usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stddef.h + .... /usr/include/wchar.h + ... /usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stdarg.h + .. /usr/include/bits/stdio_lim.h + .. /usr/include/bits/sys_errlist.h + Multiple include guards may be useful for: + /usr/include/bits/stdio_lim.h + /usr/include/bits/sys_errlist.h + /usr/include/bits/typesizes.h + /usr/include/gnu/stubs-64.h + /usr/include/gnu/stubs.h + /usr/include/wchar.h + /tmp/ccSGFuir.o: In function `main': + main.cpp:(.text+0x5): undefined reference to `comm2_show()' + main.cpp:(.text+0x1b): undefined reference to `comm1_show()' + collect2: error: ld returned 1 exit status + ``` + + 当然,如果交换了头文件的顺序。没有把预编译的头文件放到第一个,这样也是不会生效的啊!!!!! + ``` + #include + #include "comm_header.h" + + int main() + { + + printf("hello world, val %d\n", comm2_show()); + printf("hello world, val %d\n", comm1_show()); + return 0; + } + ``` + + ``` + $ g++ -H main.cpp + . /usr/include/stdio.h + .. /usr/include/features.h + ... /usr/include/sys/cdefs.h + .... /usr/include/bits/wordsize.h + ... /usr/include/gnu/stubs.h + .... /usr/include/gnu/stubs-64.h + .. /usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stddef.h + .. /usr/include/bits/types.h + ... /usr/include/bits/wordsize.h + ... /usr/include/bits/typesizes.h + .. /usr/include/libio.h + ... /usr/include/_G_config.h + .... /usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stddef.h + .... /usr/include/wchar.h + ... /usr/lib/gcc/x86_64-redhat-linux/4.8.5/include/stdarg.h + .. /usr/include/bits/stdio_lim.h + .. /usr/include/bits/sys_errlist.h + . comm_header.h + .. comm1.h + .. comm2.h + Multiple include guards may be useful for: + /usr/include/bits/stdio_lim.h + /usr/include/bits/sys_errlist.h + /usr/include/bits/typesizes.h + /usr/include/gnu/stubs-64.h + /usr/include/gnu/stubs.h + /usr/include/wchar.h + /tmp/cccPO3oj.o: In function `main': + main.cpp:(.text+0x5): undefined reference to `comm2_show()' + main.cpp:(.text+0x1b): undefined reference to `comm1_show()' + collect2: error: ld returned 1 exit status + ``` + + 在大型项目里面预编译头文件是可以很明显的加快编译速度的。 + +---- + +2. 并行编译 + + 修改make的逻辑,将没有依赖的独立的底层模块尽可能的并行编译。 + + 比如下面这样,想让mod1和mod2并行编译的话。 + + ![](../pic/make_pic1.png) + + ``` + # 模块1 和 模块2 并行编译 + MAKE=make -s + PARALLEL_ARG =-j 20 + + SUBDIRS_MOD1 = mod1 # 独立的模块1 + SUBDIRS_MOD2 = mod2 # 独立的模块2 + + .PHONY: all $(SUBDIRS_MOD1) $(SUBDIRS_MOD2) + + all: + $(MAKE) $(PARALLEL_ARG) $(SUBDIRS_MOD1) $(SUBDIRS_MOD2); + + $(SUBDIRS_MOD1): + echo "mod 1" + $(MAKE) -C $@ + + $(SUBDIRS_MOD2): + echo "mod 2" + $(MAKE) -C $@ + ``` + + 这样两个mod是同时开始进行编译的。不会先编译mod1,等mod1好了在编译mod2。这里使用的前提是,项目里面已经调整好了依赖的部分,mod1和mod2不会相互依赖(或者依赖的部分已经抽离出去,提前编译好了)。 + + 在Linux平台上一般使用GNU的Make工具进行编译,在执行make命令时可以加上-j参数增加编译并行度,如make -j 4将开启4个任务。在实践中我们并不将该参数写死,而是通过$(nproc)方法动态获取编译机的CPU核数作为编译并发度。 + +---- + +3. ccache + + CCache(Compiler Cache是一个编译缓存工具,其原理是将cpp的编译结果保存在文件缓存中,以后编译时若对应文件无变动可直接从缓存中获取编译结果。需要注意的是,Make本身也有一定缓存功能,当目标文件已编译(且依赖无变化)时,若源文件时间戳无变化也不会再次编译;但CCache是按文件内容做的缓存,且同一机器的多个项目可以共享缓存,因此适用面更大。 + + 这里有几个坑: + + ccache和头文件预编译是冲突的,如果开启了头文件预编译,那么ccache就无法工作了。chache的命中率就是零。 + + ccache和 gcc/g++的-MM选项是冲突的,如果使用了-MM的选项,那么ccache的命中率是零。使用-MMD的选项可以有效解决问题。 + + (以上两点在ccahce的主页里面都有介绍,用的时候没仔细看,然后果断掉坑。) + +4. 分布式编译 + + distcc是一个分布式编译的组件,可以将本地的任务分发到其他的机器上,实现分布式编译。 + + +5. 链接ld阶段优化 + + 将一些公共的底层模块打包为动态库,底层模块修改的时候,需要编译出对应的so即可。如果是静态库的话,对应的可执行文件还需要重新链接一次。 + +6. include-what-you-use + + cpp的编写规范里面经常提到,只include需要的头文件。当include了一些没用的头文件,会带来额外的负担。因为编译器在第一步预处理阶段,就会把include的文件都展开,如果include很多没用的,对编译的时间还是有影响的。 + + 说到include头文件,在开发的时候可以使用前置声明,不需要include进来的就不要include了。 + + include-what-you-use 这个就是google出品,解决这个问题的。 + + +7. 其他 + + 还有一个小技巧,makefile有一个很棒的track,帮助分析整个构建的过程。 + ``` + make --debug target + make --trace target + ``` + +8. 守住编译优化的结果 + + 编译脚本中增加记录构建时间的记录,简单点的`time make`。放到ci的流水线上,在每天的构建记录中都可以保存到每次构建多了多长时间。哪一次的提交让时间变长。发现了问题,也可以及时处理。 + +---- + +参考: + +https://zh.m.wikipedia.org/zh-hans/%E9%A2%84%E7%BC%96%E8%AF%91%E5%A4%B4 + +http://zplutor.github.io/2015/09/28/use-precompiled-header-to-speed-up-compilation/ + +https://tech.meituan.com/2020/12/10/apache-kylin-practice-in-meituan.html + + +test master diff --git "a/note/CMAKE\346\225\231\347\250\213.md" "b/note/CMAKE\346\225\231\347\250\213.md" old mode 100644 new mode 100755 diff --git a/note/PhysX.md b/note/PhysX.md new file mode 100755 index 0000000..9862c2b --- /dev/null +++ b/note/PhysX.md @@ -0,0 +1,266 @@ +## PhysX 入门 + +## 目录 +* [简介](#简介) +* [编译](#编译) +* [pvd](#pvd) +* [基本原理](#基本原理) + +--- + +## 简介 + +Physx 官网:https://developer.nvidia.com/physx-sdk + +Physx Github:https://github.com/NVIDIAGameWorks/PhysX + +PVD 下载地址:https://developer.nvidia.com/physx-visual-debugger + +Physx API文档: physx/documentation/PhysXGuide/Manual/API.htm + +--- + +## 编译 + +在linux下搭建px环境 + +1. nv的github上clone代码到本地,这是4.1的版本。 + + 前置依赖是cmake 3.11以上的版本 和 python ,clang yum install clang + ``` + # 下载 + git clone https://github.com/NVIDIAGameWorks/PhysX . + + # 构建 + cd physx + ./generate_projects.sh + 输入数字,选择对应的linux版本 + + # 分别进入以下两个目录,编译对应的版本 + cd physx/compiler/linux-checked + cd physx/compiler/linux-relase + 执行make + + # 遇到些额外的问题,找不到x11,手动安装下 + sudo yum install libX11-devel + ``` + +2. 查看编译后的产物 + ``` + physx/bin/linux.clang/release$ ll + -rw-rw-r-- 1 298K Sep 29 11:33 libPhysXCharacterKinematic_static_64.a + -rw-rw-r-- 1 3.9M Sep 29 11:32 libPhysXCommon_static_64.a + -rw-rw-r-- 1 531K Sep 29 11:34 libPhysXCooking_static_64.a + -rw-rw-r-- 1 2.9M Sep 29 11:34 libPhysXExtensions_static_64.a + -rw-rw-r-- 1 140K Sep 29 11:32 libPhysXFoundation_static_64.a + -rw-rw-r-- 1 22M Sep 29 10:55 libPhysXGpu_64.so + -rw-rw-r-- 1 548K Sep 29 11:33 libPhysXPvdSDK_static_64.a + -rw-rw-r-- 1 6.9M Sep 29 11:33 libPhysX_static_64.a + -rw-rw-r-- 1 1.3M Sep 29 11:34 libPhysXVehicle_static_64.a + -rw-rw-r-- 1 590K Sep 29 11:38 libSampleBase_static_64.a + -rw-rw-r-- 1 252K Sep 29 11:38 libSampleFramework_static_64.a + -rw-rw-r-- 1 28K Sep 29 11:37 libSamplesToolkit_static_64.a + -rw-rw-r-- 1 30K Sep 29 11:34 libSnippetRender_static_64.a + -rw-rw-r-- 1 17K Sep 29 11:34 libSnippetUtils_static_64.a + ``` + + ``` + ~physx/bin/linux.clang/checked$ ll + -rw-rw-r-- 1 2.1M Sep 29 11:47 libPhysXCharacterKinematic_static_64.a + -rw-rw-r-- 1 31M Sep 29 11:46 libPhysXCommon_static_64.a + -rw-rw-r-- 1 3.1M Sep 29 11:48 libPhysXCooking_static_64.a + -rw-rw-r-- 1 25M Sep 29 11:47 libPhysXExtensions_static_64.a + -rw-rw-r-- 1 709K Sep 29 11:45 libPhysXFoundation_static_64.a + -rw-rw-r-- 1 15M Sep 29 10:55 libPhysXGpu_64.so + -rw-rw-r-- 1 3.5M Sep 29 11:46 libPhysXPvdSDK_static_64.a + -rw-rw-r-- 1 84M Sep 29 11:47 libPhysX_static_64.a + -rw-rw-r-- 1 12M Sep 29 11:48 libPhysXVehicle_static_64.a + -rw-rw-r-- 1 4.5M Sep 29 11:49 libSampleBase_static_64.a + -rw-rw-r-- 1 1.8M Sep 29 11:49 libSampleFramework_static_64.a + -rw-rw-r-- 1 171K Sep 29 11:49 libSamplesToolkit_static_64.a + -rw-rw-r-- 1 188K Sep 29 11:48 libSnippetRender_static_64.a + -rw-rw-r-- 1 58K Sep 29 11:48 libSnippetUtils_static_64.a + ``` + +3. 编译出一个可运行的程序 + physx/snippets/snippethelloworld 在这里路径下,找到示例文件 SnippetHelloWorld.cpp + + 改动如下: + ``` + -int snippetMain(int, const char*const*) + +int main(int, const char*const*) + ``` + + Makefile 修改如下: + ``` + BINARY = $(patsubst %.cpp,%,$(wildcard *.cpp)) + + SRC_BASE=../../.. + + PHYSX_ROOT=$(SRC_BASE) + PHYSX_BASE=$(PHYSX_ROOT)/physx + + PHYSX_INC = $(foreach dir, $(shell find $(PHYSX_BASE)/include -type d), -isystem$(dir)) + PHYSX_INC += $(foreach dir, $(shell find $(PHYSX_ROOT)/pxshared/include -type d), -isystem$(dir)) + + CINC += $(PHYSX_INC) + CINC += -isystem$(PHYSX_ROOT)/pxshared/include + CINC += -isystem$(PHYSX_BASE)/source/geomutils/src + CINC += -isystem$(PHYSX_BASE)/source/geomutils/src/hf + CINC += -isystem$(PHYSX_BASE)/source/foundation/include + CINC += -isystem$(PHYSX_BASE)/source/common/src + + #ifdef SUPPORT_PVD + PHYSX_LIB=$(PHYSX_BASE)/bin/linux.clang/checked + #else + #PHYSX_LIB=$(PHYSX_BASE)/bin/linux.clang/release + #endif + + LIBS += -L$(PHYSX_LIB) + #LIBS += -lPhysXGpu_64 + LIBS += $(PHYSX_LIB)/libPhysXCooking_static_64.a + LIBS += $(PHYSX_LIB)/libPhysXExtensions_static_64.a + LIBS += $(PHYSX_LIB)/libPhysXFoundation_static_64.a + LIBS += $(PHYSX_LIB)/libPhysXPvdSDK_static_64.a + LIBS += $(PHYSX_LIB)/libPhysXCharacterKinematic_static_64.a + LIBS += $(PHYSX_LIB)/libPhysXVehicle_static_64.a + LIBS += $(PHYSX_LIB)/libPhysX_static_64.a + LIBS += $(PHYSX_LIB)/libPhysXCommon_static_64.a + LIBS += $(PHYSX_LIB)/libPhysXPvdSDK_static_64.a + LIBS += $(PHYSX_LIB)/libPhysXFoundation_static_64.a + + DEBUG_FLAG=-g -Werror -Wall -fPIC -fno-strict-aliasing -lpthread -ldl -rdynamic -D NDEBUG -D PX_SUPPORT_PVD + + + all:SnippetHelloWorld.cpp + g++ SnippetHelloWorld.cpp -o test0 $(DEBUG_FLAG) $(CINC) $(LIBS) + ``` + + 运行: + ``` + ./test0 + SnippetHelloWorld done. + ``` + +---- + +## Pvd调试工具 + +在linux下执行px程序,在window下使用pvd查看或调试。 + +首先,在官方下载pvd,下载地址:https://developer.nvidia.com/physx-visual-debugger + +在linux下编译px程序,注意这里不要使用relase版本编译,release是不支持使用pvd的,可以使用checked或者debug版本编译。 + +px的程序中,需要添加连接pvd的代码。这样程序允许的时候,linux下的程序会尝试连接pvd。不过由于pvd是运行在window的机器上,不在同一台机器上,需要配置隧道转发。 + +``` +gPvd = PxCreatePvd(*gFoundation); +PxPvdTransport* transport = PxDefaultPvdSocketTransportCreate("127.0.0.1", 5425, 10); +gPvd->connect(*transport,PxPvdInstrumentationFlag::eALL); +``` + +* linux运行px程序,在win下使用pvd。如何搭建隧道? + +下载putty + +![pic](../pic/px_pic2.png) + +![pic](../pic/px_pic3.png) + +完成后,在linux输入telnet测试 +``` +telnet 127.0.0.1 5425 +``` + +---- + +## 基本概念 + +* PhysX世界包含多个scene,每个场景包含多个Actor。 + + Acotr主要有三种类型:Rigid Body(刚体)、Particles(粒子,如:流水)、Cloth(布料) + + PhysX内置的Shape:—— 同一actor内的shape可以互相嵌入。 + + 基础几何体: + + * PxBoxGeometry(盒子) + + * PxSphereGeometry(球体) + + * PxCapsuleGeometry(胶囊体) + + * PxPlaneGeometry(平面) + + 复杂几何体: + + * PxConvexMeshGeometry、PxTriangleMeshGeometry(网格,凸面体 和 三角面) + + * PxHeightFieldGeometry(高度场,如:水面和地形) + + Actor类型: + + * 静态static + + * 动力dynamic + + * 运动kinematic + + Kinematic Actors会推开普通的Dynamic Actors,但是不会受到反作用力。 + + Kinematic Actors之间或者Kinematic Actors与Static Actors之间没有相互作用和碰撞。 + +--- + +* 碰撞(collision)是整个物理引擎的基础和核心。 + + 原理:刚体不能嵌入。 + + 方法:先让碰撞/嵌入发生,然后再修复。 + + 碰撞检测(detection)是整个引擎的基础。 + + 分为宽泛阶段(broad phase)和精细阶段(narrow phase) + + 碰撞求解(solve)是引擎的一个核心工作。 + + 引擎主要由simulate(模拟)驱动。 + + 应用主要由query(查询)驱动。业务的大部分逻辑都是根据查询(及simulate回调)驱动游戏逻辑。 + + 我们需要知道模拟之后特定空间内、方向上的shape信息。 + 需要将所有元素按照特定关系组织起来以便快速查询。数据库使用B+树,物理引擎使用八叉树/二叉树等。 + +--- + +* 场景查询SceneQuery类型: + + raycast(射线)、sweep(扫掠)、overlap(重叠)—— 基于查询树(AABBTree) + + 角色控制CCT(Charactor ConTroller)基于SceneQuery。 + + 载具Vehicle基于joint和SceneQuery。 + +--- + +* 代码设计: + + ![pic](../pic/px_pic1.png) + +---- + +* 参考 + + Physx 官网:https://developer.nvidia.com/physx-sdk + + Physx Github:https://github.com/NVIDIAGameWorks/PhysX + + PVD 下载地址:https://developer.nvidia.com/physx-visual-debugger + + Physx的多线程框架解析 - 志创大侠的文章 - 知乎 +https://zhuanlan.zhihu.com/p/60733992 + + https://github.com/ThisisGame/cpp-game-engine-book + + > https://github.com/ThisisGame/cpp-game-engine-book/blob/main/pages/22.%20physics_engine_physx/22.1%20hello_physx.md \ No newline at end of file diff --git "a/note/TCP\345\222\214\347\275\221\347\273\234\347\274\226\347\250\213.md" "b/note/TCP\345\222\214\347\275\221\347\273\234\347\274\226\347\250\213.md" old mode 100644 new mode 100755 index b1c15c0..f3da6bd --- "a/note/TCP\345\222\214\347\275\221\347\273\234\347\274\226\347\250\213.md" +++ "b/note/TCP\345\222\214\347\275\221\347\273\234\347\274\226\347\250\213.md" @@ -35,17 +35,19 @@ * [几个值的思考的问题](#几个值的思考的问题) - * 建立tcp建立之后,断开网线,会发生什么? + * 建立tcp建立之后,断开网线,会发生什么?(tcp半开连接) * 向一个没有监听的端口建立tcp连接,会发生什么? + * accept 出现在三次握手的什么时候? + + * 为什么需要四次挥手?(为什么上次不可以?) + * 什么时候会出现rst包? * 服务器已经close了fd,然后client取从这个fd上面接受和发送数据,分别会出现什么问题? * sigpipe信号什么时候会出现?出现了会怎么样? - - --- * close和shutdown关闭tcp连接的区别? @@ -57,6 +59,10 @@ * 惊群问题 + * tcp中为什么时候会出现closing状态 + + * epoll模式下的server把数据从网卡接受到数据到读入buff的流程 + --- ## tcp/ip原理 @@ -72,8 +78,11 @@ 3. Server 应答(acknowledge (ACK)) the client's SYN, 同时自己也发送一个SYN分节,包含Server将在同一连接中发送的数据的初始化序号。服务器发送自己的SYN,并对Client's SYN确认(ACK). 4. client ACK the server's SYN - - ![](../pic/tcp1.png) + + + ![tu](../pic/tcp1.PNG) + + * 四次挥手 @@ -85,7 +94,7 @@ 4. 接收这个最终FIN的原发送端TCP(即主动关闭的那一端)确认这个FIN - ![](../pic/tcp2.png) + ![tu](../pic/tcp2.PNG) * time_wait @@ -93,7 +102,11 @@ * close_wait +完整的tcp流程: + +![tu](../pic/tcp3.PNG) +--- * rst 包 @@ -290,6 +303,24 @@ http://blog.51cto.com/yaocoder/1309358 http://blog.51cto.com/yaocoder/1589919 + +### 1.1 TCP建立连接之后,kill客户端后会发生什么? + +如果一个epoll的server启动,和使用telnet建立了连接,那么现在tcp的连接是ESTABLISHED了。如果把telnet kill掉的话,(如果epoll sever上面没有特殊处理的事件的话)那么,使用netstat查看的话,就会看到一个server上面出现close wait的情况。 + +这就表示server没有处理fd异常关闭的情况,这样会导致服务器一直出现一个close wait的情况,并且占用了一个fd。那么解决的办法是,在epoll上面添加一个EPOLLRDHUP事件的处理。比如我用了epoll,那么我监听客户端连接套接字(5)的EPOLLRDHUP这个事件。当客户端意外断开时,这个事件就会被触发,触发之后。我们针对性的对这个fd(5)执行close()操作就可以了。 + + +**kill 和 直接断网的区别是:** + +unix 网络编程书里面写“TCP FIN sent by kernel when client is killed or crashed”当client被kill的时候,内核会发送fin包给server。这样服务器这边进入close wait的状态,若epoll注册了HUP的事件,把连接关闭close wait变为close;若没有处理,服务器这里就有一个close wait的状态,占用了fd。 + + +**参考:** + +服务端close-wait或者time-wait状态过多会导致什么样的后果? - 果冻虾仁的回答 - 知乎 +https://www.zhihu.com/question/298214130/answer/1090787813 + --- ### 2. 向一个没有监听的端口建立tcp连接,会发生什么? @@ -593,4 +624,41 @@ net.ipv4.tcp_wmem = 4096 16384 4194304 Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN - -``` \ No newline at end of file +``` + +## 5. epoll 相关的监听事件 和 epoll工作的原理 + +* epoll的一个简答example : + + https://github.com/zhaozhengcoder/Algorithm/blob/master/---Others---/%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B%E5%9F%BA%E6%9C%AC%E7%9A%84api/epoll/epoll_test_event.cpp + +* epoll 可以监听的事件的类型: + ``` + events可以是以下几个宏的集合: + + EPOLLIN : 表示对应的文件描述符可以读(包括对端SOCKET正常关闭); + + EPOLLOUT: 表示对应的文件描述符可以写; + + EPOLLPRI: 表示对应的文件描述符有紧急的数据可读(这里应该表示有带外数据到来); + + EPOLLERR: 表示对应的文件描述符发生错误; + + EPOLLHUP: 表示对应的文件描述符被挂断; + + EPOLLET: 将 EPOLL设为边缘触发(Edge Triggered)模式(默认为水平触发),这是相对于水平触发(Level Triggered)来说的。 + + EPOLLONESHOT: 只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,需要再次把这个socket加入到EPOLL队列里 + ``` + +* epoll的原理: + + https://blog.csdn.net/Monzart7an/article/details/26092727 + + 一颗红黑树,一张准备就绪句柄链表,少量的内核cache,就帮我们解决了大并发下的socket处理问题。执行epoll_create时,创建了红黑树和就绪链表,执行epoll_ctl时,如果增加socket句柄,则检查在红黑树中是否存在,存在立即返回,不存在则添加到树干上,然后向内核注册回调函数,用于当中断事件来临时向准备就绪链表中插入数据。执行epoll_wait时立刻返回准备就绪链表里的数据即可。 + + 最后看看epoll独有的两种模式LT和ET。无论是LT和ET模式,都适用于以上所说的流程。区别是,LT模式下,只要一个句柄上的事件一次没有处理完,会在以后调用epoll_wait时次次返回这个句柄,而ET模式仅在第一次返回。 + + + + diff --git a/note/asan.md b/note/asan.md new file mode 100755 index 0000000..382808c --- /dev/null +++ b/note/asan.md @@ -0,0 +1,138 @@ +## Address Sanitizer + +## 目录 + +* [简介](#简介) +* [hello-world实例](#hello-world实例) + +--- + +## 简介 + +asan是一个Google提供的一个内存检测的工具。 + +https://github.com/google/sanitizers/wiki/AddressSanitizer + +* asan原理 + + shadow-memory (影子内存) + +--- +## hello-world实例 + +* 测试使用asan定位一个服务器内存泄露的例子 + ``` + #include + #include + char leaktest() { + char * x = (char *)malloc(10 * sizeof(char)); + x[20] = 'b'; + return x[5]; + } + + int main() + { + printf("==== main ==== \n"); + + // 伪造内存越界写入和泄漏 + leaktest(); + // 假设这是一个服务器程序,不停的运行中 + while(1) {} + + printf("==== end ===== \n"); + return 0; + } + + // g++ -fsanitize=address -fsanitize-recover=address -g test.c -o test + // export ASAN_OPTIONS=halt_on_error=0:log_path=/home/zhaozheng/log/asan.log + ``` + +* 输出日志: + + ``` + cat asan.log.358177 + ================================================================= + ==358177==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000024 at pc 0x0000004011e8 bp 0x7fffffffe1e0 sp 0x7fffffffe1d0 + WRITE of size 1 at 0x602000000024 thread T0 + #0 0x4011e7 in leaktest() /home/zhaozheng/workspace/asan/test.c:5 + #1 0x401244 in main /home/zhaozheng/workspace/asan/test.c:13 + #2 0x7ffff63376a2 in __libc_start_main (/lib64/libc.so.6+0x236a2) + #3 0x4010dd in _start (/home/zhaozheng/workspace/asan/test2+0x4010dd) + + 0x602000000024 is located 10 bytes to the right of 10-byte region [0x602000000010,0x60200000001a) + allocated by thread T0 here: + #0 0x7ffff70f4c58 in __interceptor_malloc (/lib64/libasan.so.5+0xefc58) + #1 0x4011a8 in leaktest() /home/zhaozheng/workspace/asan/test.c:4 + #2 0x401244 in main /home/zhaozheng/workspace/asan/test.c:13 + #3 0x7ffff63376a2 in __libc_start_main (/lib64/libc.so.6+0x236a2) + + SUMMARY: AddressSanitizer: heap-buffer-overflow /home/zhaozheng/workspace/asan/test.c:5 in leaktest() + Shadow bytes around the buggy address: + 0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + =>0x0c047fff8000: fa fa 00 02[fa]fa fa fa fa fa fa fa fa fa fa fa + 0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + Shadow byte legend (one shadow byte represents 8 application bytes): + Addressable: 00 + Partially addressable: 01 02 03 04 05 06 07 + Heap left redzone: fa + Freed heap region: fd + Stack left redzone: f1 + Stack mid redzone: f2 + Stack right redzone: f3 + Stack after return: f5 + Stack use after scope: f8 + Global redzone: f9 + Global init order: f6 + Poisoned by user: f7 + Container overflow: fc + Array cookie: ac + Intra object redzone: bb + ASan internal: fe + Left alloca redzone: ca + Right alloca redzone: cb + ``` + +* asan的编译选项 + +1. 内存越界时程序直接abort,而是继续执行。(对于服务器程序很关键) + + `-fsanitize-recover=address` + +2. 通过ASAN_OPTIONS变量设置recover模式 + + `ASAN_OPTIONS=halt_on_error=0` + `#强烈建议你不要这么做,因为recover出来是什么结果是无法预测的` + +3. 通过非标准的C++修饰__attribute__((no_sanitize_address)) 指定某些具体函数屏蔽内存检查功能 + + 也可以通过-fsanitize-blacklist=your_ignore_list.txt 或者 ASAN_OPTIONS=suppressions=your_ignore_list.txt 指定屏蔽列表。 + + 具体请参考: + + https://github.com/google/sanitizers/wiki/AddressSanitizer#turning-off-instrumentation + +4. asan的日志输出到指定的地方 + + `export ASAN_OPTIONS=log_path=` + +5. 内存泄露检测跑得更快 + + `-fsanitize=address替换成-fsanitize=leak` + + https://github.com/google/sanitizers/wiki/AddressSanitizerLeakSanitizer + + +----- +其他文档: + +* Linux下内存检测工具:asan + + http://www.cppblog.com/markqian86/archive/2018/06/14/215728.html diff --git "a/note/bash&shell\347\274\226\347\250\213.md" "b/note/bash&shell\347\274\226\347\250\213.md" old mode 100644 new mode 100755 diff --git a/note/c++.md b/note/c++.md new file mode 100755 index 0000000..b5db831 --- /dev/null +++ b/note/c++.md @@ -0,0 +1,71 @@ +# c++ + +## 目录 + +* [语法基础](#语法基础) + +* [STL](#STL) + +* [c++字节对齐](#c++字节对齐) + +* [多个文件链接的初始化顺序](#多个文件链接的初始化顺序) + +* [内存分配](#内存分配) + +* [面向对象](#面向对象) + +* [多线程](#多线程) + +* [模板与泛型编程](#模板与泛型编程) + +* [其他](#其他) + +--- + +#### 语法基础 + +> [c++语法基础](./C++学习.md) + +#### STL + +> [c++ STL](./C++STL.md) + +#### 内存分配 + +> [c++内存管理](./c++内存管理.md) + +> [智能指针](./c++智能指针.md) + +#### 面向对象 + +>[c++面向对象](./c++面向对象.md) + +>[c++的多态和虚函数](./c++的多态和虚函数.md) + +#### 多线程 + +> [多线程](./c++11多线程.md) + +> [线程同步](./线程同步.md) + +#### 模板与泛型编程 + +> [模板](./c++模板与泛型编程.md) + +#### 其他 + +> [c++字节对齐](./C++字节对齐.md) + +> [c++多个文件链接的时候no_static多个文件链接变量初始化顺序问题](./c++多个文件链接初始化顺序问题.md) + +> [c++ 关于我用到的static 和 const的一些场景](./c++类中使用static和const.md) + +> [线程同步](./线程同步.md) + +> [c++的前置声明](./c++的前置声明.md) + +> [c++面向对象](./c++面向对象.md) + +> [c++类型转换cast](./c++类中使用static和const.md) + +> [没想好名字的一些东西](./c++其他.md) \ No newline at end of file diff --git "a/note/c++11\345\244\232\347\272\277\347\250\213.md" "b/note/c++11\345\244\232\347\272\277\347\250\213.md" old mode 100644 new mode 100755 index 772b912..fc3a417 --- "a/note/c++11\345\244\232\347\272\277\347\250\213.md" +++ "b/note/c++11\345\244\232\347\272\277\347\250\213.md" @@ -12,6 +12,7 @@ * [promise](#promise) * [async](#async) * [packaged_task](#packaged_task) +* [内存模型](#内存模型) --- @@ -138,6 +139,26 @@ cout << thread::hardware_concurrency() << endl; ps -T -p 进程pid pidstat -t -p 进程pid -u 1 + +top -H -p pid +``` + +* gdb调试 +``` +1. 查看线程 +info threads + +2. 跳转到某个线程 +thread 2/3/4 + +3. +set scheduler-locking off|on|step + +估计是实际使用过多线程调试的人都可以发现,在使用step或者continue命令调试当前被调试线程的时候,其他线程也是同时执行的,怎么只让被调试程序执行呢? +通过这个命令就可以实现这个需求。 +off 不锁定任何线程,也就是所有线程都执行,这是默认值。 +on 只有当前被调试程序会执行。 +step 在单步的时候,除了next过一个函数的情况(熟悉情况的人可能知道,这其实是一个设置断点然后continue的行为)以外,只有当前线程会执行。 ``` ## 数据竞争和资源互斥 @@ -459,7 +480,7 @@ int main() thread t1(cal_fib,n,ref(result)); unique_lock locker(mu); - cond.wait(locker); + cond.wait(locker); // void wait(std::unqiue_lock & lock); condition_variable::wait 定义 cout< &p) { int arr[n]; arr[0] = 0; @@ -521,66 +542,86 @@ int main() arr[i]=arr[i-1]+arr[i-2]; usleep(50000); } - return arr[n]; + p.set_value(arr[n]); // 设置一个值 + return 0; } - int main() { - promise p; //保证未来会传递一个值 - future f = p.get_future(); - - future fu = async(cal_fib,20); + promise p; // 保证未来会传递一个值 + future futureObj = p.get_future(); + future fu = async(cal_fib, 30, ref(p)); - p.set_value(100); //传递一个值 - int result = fu.get(); + cout << "wait result ... " << endl; + int result = futureObj.get(); cout< &f) + std::condition_variable cv; + bool done; + std::mutex m; + + bool wait_loop() { - int n = f.get(); - int arr[n]; - arr[0] = 0; - arr[1] = 1; - for(int i=2;i<=n;i++) + std::cout << "enter wait_loop ... " << std::endl; + auto const timeout= std::chrono::steady_clock::now()+ + std::chrono::milliseconds(5000); + std::unique_lock lk(m); + while(!done) { - arr[i]=arr[i-1]+arr[i-2]; - usleep(50000); + std::cout << "enter while ... " << std::endl; + if(cv.wait_until(lk,timeout)==std::cv_status::timeout) + { + std::cout << "break" << std::endl; + break; + } } - return arr[n]; + return done; } + ``` - int main() - { - promise p; //保证未来会传递一个值 - future f = p.get_future(); - - future fu = async(cal_fib, ref(f)); // 注意,这个传递的是一个future的类型 +* 内存模型 - p.set_value(30); //传递一个值 - int result = fu.get(); - cout<[pdf1](../example_code/pdf/C%2B%2B11%E7%9A%84%E5%86%85%E5%AD%98%E6%95%B0%E6%8D%AE1.pdf) + + >[pdf2](../example_code/pdf/C%2B%2B11%E7%9A%84%E5%86%85%E5%AD%98%E6%95%B0%E6%8D%AE2.pdf) --- ## 参考 -* C++并发编程(中文版) https://legacy.gitbook.com/book/chenxiaowei/cpp_concurrency_in_action/details +* C++并发编程(中文版) + + https://legacy.gitbook.com/book/chenxiaowei/cpp_concurrency_in_action/details * cppreference https://en.cppreference.com/w/cpp/thread -* 腾讯学堂的一个视频也不错 +* 现代 C++ 教程:高速上手 C++ 11/14/17/20 - https://ke.qq.com/course/131596 \ No newline at end of file + https://changkun.de/modern-cpp/zh-cn/07-thread/ \ No newline at end of file diff --git a/note/c++STL.md b/note/c++STL.md old mode 100644 new mode 100755 index 08c19b8..711e3d7 --- a/note/c++STL.md +++ b/note/c++STL.md @@ -3,18 +3,21 @@ ## 目录 * [迭代器失效](#迭代器失效) - - +* [map访问不存在的元素会怎么样](#map访问一个不存在key的元素会怎么样?) +* [emplace_back](#emplace_back) +* [使用swap缩容](#swap) +* [stl sort的坑](#sort) --- -## 迭代器失效 +**基本的STL的使用方法就不在这里赘述了,这里会整理一下stl使用的一些常见的坑。** -* erase 失效的例子 +### 1. 迭代器失效 -* 在遍历的时候,添加/删除元素 +迭代器在添加,删除元素之后都有可能失效。在添加,删除之后,要确保自己的迭代器是没有失效的。 + +* erase 失效的例子 :在遍历的时候,添加/删除元素 - 迭代器失效的原理:因为对应的元素存放的内存的地址发生了改变,导致迭代器失效。 举个例子,比如push_back多次之后,vector会被迁移。这样原来的地址发生了改变。导致迭代器失效。 @@ -40,7 +43,7 @@ { if (*iter != delete_ele) { - iter = vi.erase(iter); + iter = vi.erase(iter); // 删除元素之后,iter指向被删除的元素的下一个了,不需要再iter++了 } else { @@ -53,8 +56,112 @@ { vector vi = { 1,2,3,3,5,3}; delete_ele(vi, 3); - - return 0; } - ``` \ No newline at end of file + ``` + +--- + +### 2. map访问一个不存在key的元素会怎么样? + +这个如果不知道这个规则的话,可能会掉坑。**如果map里面不存在这个key的话,访问的时候,会创建一个默认的value对象,然后把这个默认的对象返回。** 所以, 判断一个map里面是否包含某个元素,最好用如这样的逻辑进行判断 map.find() == map.end() + +``` +class STUDENT +{ + private: + int student_id; + int class_id; + public: + STUDENT () + { + cout << "init defualt" << endl; + this->student_id = -123; + this->class_id = -345; + } + + STUDENT(int student_id, int class_id) + { + cout << "init" << endl; + this->student_id = student_id; + this->class_id = class_id; + } + + int print_student_id() + { + return this->student_id; + } +}; + +int main() +{ + map student_map; + cout << student_map.size() << endl; // size 0 + cout << student_map[100].print_student_id() << endl; + cout << student_map.size() << endl; // size 1 // 不要通过这种方式去判断对象是否存在,因为它会在map中创建一个对象 + return 0; +} +``` + +输出: +``` +$ ./a.out +init defualt +-123 +``` + + +---- + +### 3. emplace_back + +emplace_back和push_back的区别,为什么要使用emplace_back? + +emplace_back的优点是避免了一次对象的拷贝构造。explace可以直接在vector的空间上面进行初始化对象。 + +``` +int main() +{ + vector student_vec; + cout<<"emplace back" << endl; + student_vec.emplace_back(200,201); + + cout << "push back" << endl; + student_vec.push_back(STUDENT(100,101)); + + // xxx +} +``` + +输出: +``` +$ ./a.out +emplace back +init +push back +init +copy +copy +``` + +--- +### 4. swap + +一个vector中有size和capacity两个概念,当向一个vector里面push元素的时候,size和capacity都增长。然后,当删除元素的时候,size会减小,但是capacity不会。如果希望capacity也可以减小的话,往往会利用swap的机制。 + +``` +vector(vi).swap(vi); + +等价于 +vector tmp = vi; +vi.swap(tmp); +``` + +### 5. std::sort 的坑 + +stl中sort函数有个bug或者是个坑(或者是个feature),就是sort的时候,如果重载了cmp函数,需要cmp函数需要满足**严格弱序**。 + +### 6. 其他 + +C++后端开发的踩坑整理 +https://www.jianshu.com/p/b67222570785 \ No newline at end of file diff --git "a/note/c++\345\205\266\344\273\226.md" "b/note/c++\345\205\266\344\273\226.md" new file mode 100755 index 0000000..b85398d --- /dev/null +++ "b/note/c++\345\205\266\344\273\226.md" @@ -0,0 +1,33 @@ +# c++ 一些乱七八糟的东西整理 + + +* 看到一个来自知乎的问题,https://zhuanlan.zhihu.com/p/82895086 + ``` + // Version 1, by-value copy name to the function. + void addName(std::string name) { + names_.push_back(std::move(name)); + } + + // Version 2, provide two overloads, one with const reference, another with rvalue reference. + void addName(const std::string& name) { + names_.push_back(name); + } + void addName(std::string&& name) { + names_.push_back(std::move(name)); + } + + // Version 3, use universal reference to integrate lvalue reference and rvalue reference. + template + void addName(T&& name) { + names_.push_back(std::forward(name)); + } + + 作者:王金戈 + 链接:https://zhuanlan.zhihu.com/p/82895086 + 来源:知乎 + 著作权归作者所有,转载请联系作者获得授权。 + ``` + + 这里没有最优解,版本2和版本3最节约性能,但可能会导致源码或二进制码体积较大,版本1最简洁,但会多出一个移动构造。取舍的关键在于具体的应用场景,假如对象的移动构造非常廉价,完全不耗费性能,那就选择版本1,否则就选择版本2或3。 + + 说到这里,便又涉及到另一个问题,你是否清楚对象拷贝构造和移动构造的代价?对于自定义类,如果没有手动声明这些构造函数和赋值运算符,编译器会为我们自动生成。但编译器自动生成的这些函数长什么样?如果我们需要自定义这些函数,应该遵循什么规则?答案很繁琐,但我们必须逐一理清。 \ No newline at end of file diff --git "a/note/c++\345\206\205\345\255\230\347\256\241\347\220\206.md" "b/note/c++\345\206\205\345\255\230\347\256\241\347\220\206.md" new file mode 100755 index 0000000..ffbce74 --- /dev/null +++ "b/note/c++\345\206\205\345\255\230\347\256\241\347\220\206.md" @@ -0,0 +1,405 @@ +# c++ 的内存管理 + + +### new和delete + +* new 和 delete 做了什么? + + new: + ``` + 1. 申请内存 + new -> operator new -> malloc -> linux系统分配内存 + + 2. 在申请的内存上调用构造函数,构造对象 + new (raw_memory) Test(); + ``` + + delete: + ``` + 1. 析构函数 + 2. 释放对象 + ``` + + new申请的内存来自于什么地方? + ![tu](../pic/malloc3.png) + +* new[] 和 delete[] 和 new ,delete的区别? + + **先把结论写在前面**,后面的问题就好理解了 + + * new/malloc 会记录分配的内存的长度,delete/free 的时候无需指定长度,只要传入首地址即可。 + + * 对于有 non-trivial destructor 的 class T, 现在通常的 C++ 实现会在 new[] 的时候多分配 sizeof(size_t) 字节用于保存数组大小,在 delete[] 的时候会依次逆序调用数组中各对象的析构函数。有的文献管这多分配的几个字节叫 new cookie (Itanium C++ ABI)。 + + +1. 为什么申请内存的时候,需要带上size,而释放内存的时候不需要? + + 在malloc申请内存的时候,在返回的指针上面会携带一个cookie的信息,信息中携带了内存这块内存的大小。所以,释放的时候,并不需要携带size。因为根据要释放内存的指针,就可以找到对应cookie信息,然后释放这块内存。 + + ![tu](../pic/malloc.png) + + https://www.zhihu.com/question/302440083 + +2. new[]申请的内存和new的行为是一样的吗? + + 不一样,对于是new[]的的情况,会多申请一个size_t的内存,用来存储申请的数量。 + + ![](../pic/malloc2.png) + + ``` + #include + //#include + + // 重载 c++的运算符号 + void * operator new(std::size_t size) + { + void* k_buf = malloc(size); + std::cout << "size : "<< size <<", malloc : " << k_buf << std::endl; + return k_buf; + } + + void * operator new[](std::size_t size) + { + void * k_buf = malloc(size); + std::cout << "size : " << size <<", malloc[] : " << k_buf < + T* new_op(Args&&... args) + { + void* block = operator new(sizeof(T)); + // 在 block 这块内存上原地调用构造函数 + return new(block) T(std::forward(args)...); + } + + // new T[size]() + template + T* new_array_op(std::size_t size) + { + if constexpr (std::is_trivially_destructible_v) { + // 可平凡析构,无需记录大小。 + void* block = operator new[](sizeof(T) * size); + T* p = reinterpret_cast(block); + // 依次调用默认构造函数。 + for (std::size_t i = 0; i < size; ++i) { + new(p + i) T(); + } + return p; + } else { + // 不可平凡析构,需要记录大小。 + void* block = operator new[](sizeof(T) * size + sizeof(size_t)); + *reinterpret_cast(block) = size; + T* p = reinterpret_cast( + reinterpret_cast(block) + sizeof(size_t)); + // 依次调用默认构造函数。 + for (std::size_t i = 0; i < size; ++i) { + new(p + i) T(); + } + return p; + } + } + + // delete ptr + template + void delete_op(T* ptr) noexcept(std::is_nothrow_destructible_v) + { + if (ptr != nullptr) { + ptr->~T(); + operator delete(ptr); + } + } + + // delete[] ptr + template + void delete_array_op(T* ptr) noexcept(std::is_nothrow_destructible_v) + { + if (ptr == nullptr) { + return; + } + if constexpr (std::is_trivially_destructible_v) { + // 可平凡析构,直接释放内存。 + operator delete[](ptr); + } else { + // 需要先获取数组大小。 + void* block = reinterpret_cast(ptr) - sizeof(size_t); + size_t size = *reinterpret_cast(block); + // 然后依次调用析构函数。 + for (std::size_t i = 0; i < size; ++i) { + (ptr + i)->~T(); + } + // 最后释放内存。 + operator delete[](block); + } + } + ``` + +3. 如果申请内存内存和释放的new和delete不匹配,会怎么样? + + 分为两种情况,比如class T 没有析构函数(或者class T 是内置的成员变量)那么,使用错误没有太大影响。 + 如果class T有析构函数,那程序会coredump掉。 + ``` + class inner + { + public: + inner() { cout << "inner Constructing " << hex << this << endl; } + ~inner() { cout << "inner Destructing" << endl; } + private: + int val; + }; + + class normal + { + public: + normal() { cout << "normal Constructing " << hex << this << endl; } + private: + int val; + }; + + int main(int argc, char *argv[]) + { + inner * pa = new inner[2]; + normal * pb = new normal[2]; + int * pc = new int[2]; + + delete pc; + delete pb; + delete pa; // coredump heres + return 0; + } + + /a.out + inner Constructing 0x210ceb8 + inner Constructing 0x210cebc + normal Constructing 0x210d2e0 + normal Constructing 0x210d2e4 + inner Destructing + munmap_chunk(): invalid pointer + Aborted (core dumped) + ``` + +* new 和 delete的重载 + + operator new 和 opertor delete 分为两种重载,分别是全局的重载和类内部的重载。 + + 其他的部分整理在这里: + + https://www.jianshu.com/p/27e2a80a158c + +* placement new + + ``` + class TEST + { + private: + int val; + public: + TEST(int value) + { + this->val = value; + } + void print() + { + cout<val<(raw_memory); + // placement new + for(int i=0;i<10;i++) + { + new(test+i) TEST(val); + } + + // visit + for(int i=0;i<10;i++) + { + (test+i)->print(); + } + + return 0; + } + ``` + +* delete 的时候 我觉得这样安全一点 + + ``` + delete obj; + obj = NULL; # 让指针指空 + ``` + +### brk 和 mmap的区别 + +内存分配通过两个系统调用完成,分别是brk 和 mmap。判断的标准是如果小于128k的话,会通过brk分配,大于的话走mmap。 + + +brk分配的内存需要等到高地址内存释放以后才能释放(例如,在B释放之前,A是不可能释放的,这就是内存碎片产生的原因,什么时候紧缩看下面),而mmap分配的内存可以单独释放。比如当前释放内存块A,当A释放时候,堆顶指针并不能收缩。只有当内存块B也释放的时候,data指针参会收缩。 + +![brk](../pic/brk1.png) + +当通过brk申请到内存之后,修改edata指针之后,并不会真的分配内存,直到访问这块内存的时候,才会出发缺页中断。 + +http://abcdxyzk.github.io/blog/2015/08/05/kernel-mm-malloc/ + + +#### 进程的内存空间 +附图一张 + +![tu](../pic/内存_1.png) + + +#### 其他 + +关于内存管理,除了了解内存的基本原理,还有整理了一些其他的东西, + +比如:C++不用工具,如何检测内存泄漏? + +https://www.jianshu.com/p/27e2a80a158c + +基于LD_PRELOAD的动态库函数hook +https://www.jianshu.com/p/c2c6644a7380 + +jemalloc内存profile +https://www.jianshu.com/p/4f9689ffca2d + +--- +### 参考 + +1. https://www.zhihu.com/question/406164583/answer/2040289707 + +2. new和delete以及new[]和delete[]一定要配对使用吗 - 程序喵大人的文章 - 知乎 +https://zhuanlan.zhihu.com/p/144600712 + +3. 关于malloc返回值的问题? - 程序喵大人的回答 - 知乎 +https://www.zhihu.com/question/275695474/answer/1648135150 + +4. https://wetest.qq.com/lab/view/318.html + +5. C++的new操作符,底层使用的是malloc吗,在析构时,是如何确定自己需要释放内存的大小的? 作者:yuantj + + 链接:https://www.zhihu.com/question/406164583/answer/2040289707 + +6. 关于vm和brk系统的分析: + + https://blog.holbertonschool.com/hack-the-virtual-memory-malloc-the-heap-the-program-break/ + + + https://mp.weixin.qq.com/s/3bXAGR_7XLX21nkdl9dQ8Q + +7. 作者:yuantj + 链接:https://www.zhihu.com/question/406164583/answer/2040289707 + +8. https://www.zhangjiee.com/blog/2013/analyse-new-delete-malloc-free.html \ No newline at end of file diff --git "a/note/c++\345\244\232\344\270\252\346\226\207\344\273\266\351\223\276\346\216\245\345\210\235\345\247\213\345\214\226\351\241\272\345\272\217\351\227\256\351\242\230.md" "b/note/c++\345\244\232\344\270\252\346\226\207\344\273\266\351\223\276\346\216\245\345\210\235\345\247\213\345\214\226\351\241\272\345\272\217\351\227\256\351\242\230.md" new file mode 100755 index 0000000..790c82e --- /dev/null +++ "b/note/c++\345\244\232\344\270\252\346\226\207\344\273\266\351\223\276\346\216\245\345\210\235\345\247\213\345\214\226\351\241\272\345\272\217\351\227\256\351\242\230.md" @@ -0,0 +1,34 @@ +# c++ 多个文件链接的时候非static变量初始化顺序问题 + +这是一个非常需要注意的坑,在多个文件链接的时候,文件a定义了test1对象,文件b定义了test2对象。那么,问题来了,test1对象先初始化,还是test2对象先初始化? + +答:其实是不一定的。当然,这个可能没有问题,但是如果test2对象的初始化依赖于test1,或者是test1的对象依赖于test2,那么,问题就来了。举个例子,如果test1的初始化依赖于test2,但是编译器先初始化了test1,test1初始化的时候test2还没有初始化,那么test1的初始化就会失败。 + +举个例子: +show_code_here -> https://github.com/zhaozhengcoder/CoderNoteBook/tree/master/example_code/mult_file_no_static_obj_init + +**这个问题出现在程序执行main函数之前,初始化“全局变量”(数据段的成员)之前,如果在代码里面出现了一个no-static变量的初始化依赖于另外一个,这个的代码估计是要除问题的,需要做检查。** + + +* 解决的办法 + +如果在程序中出现全局变量的初始化依赖问题,那么ok,不需要关心这个问题。如果在代码中,写了类似于**一个对象的初始化**依赖于**另外一个全局变量的对象**,那么就需要注意了。 + +解决的办法: + +``` +# 原来初始化对象的方法 +# TEST test1 + +# 修改办的创建对象的方法 +TEST1 &get_test1_obj() +{ + static TEST1 test1; + return test1; +} + +# 这样如果需要访问一个对象的话,那么一定要通过访问这个函数 +# 那么c++的机制可以保证访问函数的时候,static变量一定会函数被调用的时候初始化 +``` + +show_code_here -> https://github.com/zhaozhengcoder/CoderNoteBook/tree/master/example_code/mult_file_no_static_obj_init/fix_bug_demo \ No newline at end of file diff --git "a/note/c++\345\255\246\344\271\240.md" "b/note/c++\345\255\246\344\271\240.md" old mode 100644 new mode 100755 index 1ab4302..d858b34 --- "a/note/c++\345\255\246\344\271\240.md" +++ "b/note/c++\345\255\246\344\271\240.md" @@ -13,11 +13,7 @@ * [临时对象](#临时对象) * [作用域符号 : :](#作用域符号) * [宏,const,inline](#宏) - -* [比较重要的零散的东西](#比较重要的零散的东西) - * [拷贝构造函数](#拷贝构造函数) * [一个对象的空间布局](#一个对象的空间布局) - * [STL迭代器失效](#STL迭代器失效) --- @@ -26,11 +22,9 @@ 关于c++ 是一门什么样的语言,分享一篇我觉得写的很好的文章 http://www.cnblogs.com/miloyip/archive/2010/09/17/behind_cplusplus.html +整理一下C++一些基本的语法规则 - -## 语法 - -### extern关键字 +### 1. extern关键字 思考一个问题,如何在main.cpp文件里面调用 fun.c 文件里面的func 函数? 换一句话,就是如果在c++的代码里面调用c的代码。 @@ -87,7 +81,20 @@ int add(int x, int y); #endif ``` -### 初始化列表初始化 +当extern 修饰变量的时候,表示此变量在其他的编译单元中定义。 + +``` +// module_a.cpp + +extern int val; + +int foo(int a) +{ + return val * a; +} +``` + +### 2. 使用初始化列表初始化 为什么要使用初始化列表初始化? @@ -105,9 +112,9 @@ public: }; ``` -### 右值引用 +### 3. 右值引用 -右值引用,是c++11里面一个新特性。他解决的问题是:**延长临时对象的生命周期**。 +右值引用,是c++里面一个重要的特性。他解决的问题是:**延长临时对象的生命周期,避免对象拷贝的开销**。 从下面几个方面入手: @@ -125,29 +132,26 @@ using namespace std; int g_constructCount=0; int g_copyConstructCount=0; int g_destructCount=0; -struct A -{ + +struct A { A(){ cout<<"construct: "<<++g_constructCount< using namespace std; -class test -{ +class test { public: - test() - { + test() { cout<<"construct"< [c++智能指针](./c++智能指针.md) - 为什么要使用weak_Ptr? - - weak_Ptr表达的是对资源的弱引用。同时,也可以解决shered_ptr 相互引用,无法gc的情况。 - -* shared_ptr - ``` - //test 是一个class ,需要include - //创建 - shared_ptr p_test(new test()); - - //调用 - p_test->print_func(); - - //查看引用计数 - cout< p_test2; - p_test2 = p_test; - cout< pb_; - ~A() - { - cout<<"A delete\n"; - } - }; - class B - { - public: - shared_ptr pa_; - ~B() - { - cout<<"B delete\n"; - } - }; - - void fun() - { - shared_ptr pb(new B()); - shared_ptr pa(new A()); - pb->pa_ = pa; - pa->pb_ = pb; - cout< pb_; - ~A() - { - cout<<"A delete\n"; - } - }; - class B - { - public: - shared_ptr pa_; - ~B() - { - cout<<"B delete\n"; - } - }; - - void fun() - { - shared_ptr pb(new B()); - shared_ptr pa(new A()); - pb->pa_ = pa; - pa->pb_ = pb; - cout< ptr(p); - } - ``` - - 因为智能指针释放的时候,调用的是delete,而不是delete [] 。 - - -* enable_shared_from_this - - 当类A被share_ptr管理,且在类A的成员函数里需要把当前类对象作为参数传给其他函数时,就需要传递一个指向自身的share_ptr。这个时候用enable_shared_from_this 比较好。 - - https://blog.csdn.net/caoshangpa/article/details/79392878 - - 正确的例子: - ``` - #include - #include - - struct Good : std::enable_shared_from_this // 注意:继承 - { - public: - std::shared_ptr getptr() { - return shared_from_this(); - } - ~Good() { std::cout << "Good::~Good() called" << std::endl; } - }; - - int main() - { - // 大括号用于限制作用域,这样智能指针就能在system("pause")之前析构 - { - std::shared_ptr gp1(new Good()); - std::shared_ptr gp2 = gp1->getptr(); - // 打印gp1和gp2的引用计数 - std::cout << "gp1.use_count() = " << gp1.use_count() << std::endl; - std::cout << "gp2.use_count() = " << gp2.use_count() << std::endl; - } - system("pause"); - } - ``` - - 错误的例子: - ``` - #include - #include - - class Bad - { - public: - std::shared_ptr getptr() { - return std::shared_ptr(this); - } - ~Bad() { std::cout << "Bad::~Bad() called" << std::endl; } - }; - - int main() - { - // 错误的示例,每个shared_ptr都认为自己是对象仅有的所有者 - // 造成2个非共享的share_ptr指向同一个对象,未增加引用计数导对象被析构两次。 - std::shared_ptr bp1(new Bad()); - std::shared_ptr bp2 = bp1->getptr(); - // 打印bp1和bp2的引用计数 - std::cout << "bp1.use_count() = " << bp1.use_count() << std::endl; - std::cout << "bp2.use_count() = " << bp2.use_count() << std::endl; - } // Bad 对象将会被删除两次 - ``` - -## 函数指针 +## 7. 函数指针 定义一个函数的指针 ``` @@ -743,7 +563,7 @@ int main() https://elloop.github.io/c++/2015-12-15/learning-using-stl-12-std-bind -## cpp11的语法糖 +## 8. cpp11的语法糖 * for-each ``` @@ -782,7 +602,7 @@ https://elloop.github.io/c++/2015-12-15/learning-using-stl-12-std-bind ``` -## cpp11的其他新特性 +## 9. cpp11的其他新特性 * 占位符和bind函数 @@ -821,15 +641,7 @@ https://elloop.github.io/c++/2015-12-15/learning-using-stl-12-std-bind c++11 线程库 -## 模板与泛型编程 - -## 异常机制 - -## 空间分配 - -## 多态/虚函数 - -## 临时对象 +## 10. 临时对象 c++ 里面的临时对象是不可见的 —— 他们不在堆上面创建,同时也没有名字,这样的对象就是临时对象。 常见的有两种: @@ -915,7 +727,7 @@ int main() // g++ -fno-elide-constructors 好像是这个参数可以关闭 ``` -## 作用域符 :: +## 11. 作用域符 :: 1. global scope (全局作用域符),用法(::name) @@ -923,7 +735,7 @@ int main() 3. namespace scope (命名空间作用域符),用法(namespace::name) -## 宏 +## 12. 宏 宏,const,inline的区别在《effective c++》里面的第一部分就由提到。 但是,我的学习顺序是 先学习了c++,然后再看了c。我会更习惯于用const,inline,而不是宏。 @@ -950,9 +762,9 @@ forceinline字面意思上是强制内联,一般可能只是对代码体积不 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 -## 比较重要的零散的东西 +## 13. 比较重要的零散的东西 -### 拷贝构造函数 +* 拷贝构造函数为什么需要是const 下面这段代码有什么问题? ``` @@ -969,4 +781,8 @@ class A 拷贝构造函数无法通过编译。原因是,实参给形参赋值的时候,又存在一个给调用拷贝构造函数的过程。因此必须要改成 const + 引用的形式。 ``` A(const A & other) { m = other.m; } -``` \ No newline at end of file +``` + +## 一个对象的空间布局 + +> [c++多态和虚函数](./c++的多态和虚函数.md) diff --git "a/note/c++\346\231\272\350\203\275\346\214\207\351\222\210.md" "b/note/c++\346\231\272\350\203\275\346\214\207\351\222\210.md" new file mode 100755 index 0000000..eb54345 --- /dev/null +++ "b/note/c++\346\231\272\350\203\275\346\214\207\351\222\210.md" @@ -0,0 +1,445 @@ +# C++ 智能指针 + +## 目录 + +* [智能指针的基本概念](#智能指针的基本概念) + +* [智能指针的基本用法](#智能指针的基本用法) + +* [其他](#其他) + +--- + +## 智能指针的基本概念 + +1. 为什么要使用智能机制? + +* 解决new之后,需要手动delete + +* 异常安全 + ``` + void process() + { + Widget* w = new Widget(); + w->do_something(); // 可能会发生异常 + delete w; + } + ``` + + 在正常流程下,我们会在函数末尾 delete 创建的对象 w,正常调用析构函数,释放内存。 + + 但是如果 w->do_something() 发生了异常,那么 delete w 将不会被执行。此时就会发生 内存泄漏。 + 我们当然可以使用 try…catch 捕捉异常,在 catch 里面执行 delete,但是这样代码上并不美观,也容易漏写。 + + 如果我们用 std::unique_ptr,那么这个问题就迎刃而解了。无论代码怎么抛异常,在 unique_ptr 离开函数作用域的时候,内存就将会自动释放。 + +2. 什么场景下,应该什么什么样的指针? shared_ptr, weak_ptr, unique_ptr + + 这三种语义是不一样的,要看new出来的内存的管理权。unqiue ptr表示的是唯一的管理权,shared ptr表示是共享的管理权。 + + 所以,unique ptr 没有提供拷贝的接口,只有移动的接口。 + + 有的时候写代码的时候,可能会无脑使用shared ptr。如果这个内存资源没有共享的需求,那最好使用unique ptr。并且,unique ptr 的性能会高。(因为移动的语义比拷贝的语义更好) + + **使用场景**: + + * shared_ptr 通常使用在共享权不明的场景。有可能多个对象同时管理同一个内存时。 + + * 对象的延迟销毁。陈硕在《Linux 多线程服务器端编程》中提到,当一个对象的析构非常耗时,甚至影响到了关键线程的速度。可以使用 BlockingQueue> 将对象转移到另外一个线程中释放,从而解放关键线程。 + +3. 为什么要使用weak ptr ? + + weak ptr 是 shared ptr的助手,解决的是 shared ptr 循环引用的问题。(weak ptr 也智能是 shared ptr的助手,不能用来做其他的) + + ** 智能指针如何解决循环引用问题** + + weak_ptr是用来解决shared_ptr相互引用时的死锁问题,如果说两个shared_ptr相互引用,那么这两个指针的引用计数永远不可能下降为0,资源永远不会释放。它是对对象的一种弱引用,不会增加对象的引用计数,和shared_ptr之间可以相互转化,shared_ptr可以直接赋值给它,它可以通过调用lock函数来获得shared_ptr。 + + ``` + class B; + class A + { + public: + weak_ptr pb_; + ~A() + { + cout<<"A delete\n"; + } + }; + class B + { + public: + shared_ptr pa_; + ~B() + { + cout<<"B delete\n"; + } + }; + + void fun() + { + shared_ptr pb(new B()); + shared_ptr pa(new A()); + pb->pa_ = pa; + pa->pb_ = pb; + cout< + #include + + struct Good : std::enable_shared_from_this // 注意:继承 + { + public: + std::shared_ptr getptr() { + return shared_from_this(); + } + ~Good() { std::cout << "Good::~Good() called" << std::endl; } + }; + + int main() + { + // 大括号用于限制作用域,这样智能指针就能在system("pause")之前析构 + { + std::shared_ptr gp1(new Good()); + std::shared_ptr gp2 = gp1->getptr(); + // 打印gp1和gp2的引用计数 + std::cout << "gp1.use_count() = " << gp1.use_count() << std::endl; + std::cout << "gp2.use_count() = " << gp2.use_count() << std::endl; + } + system("pause"); + } + ``` + + 错误的例子: + ``` + #include + #include + + class Bad + { + public: + std::shared_ptr getptr() { + return std::shared_ptr(this); + } + ~Bad() { std::cout << "Bad::~Bad() called" << std::endl; } + }; + + int main() + { + // 错误的示例,每个shared_ptr都认为自己是对象仅有的所有者 + // 造成2个非共享的share_ptr指向同一个对象,未增加引用计数导对象被析构两次。 + std::shared_ptr bp1(new Bad()); + std::shared_ptr bp2 = bp1->getptr(); + // 打印bp1和bp2的引用计数 + std::cout << "bp1.use_count() = " << bp1.use_count() << std::endl; + std::cout << "bp2.use_count() = " << bp2.use_count() << std::endl; + } // Bad 对象将会被删除两次 + ``` + + * enable_shared_from_this 实现的原理是什么? + + // todo , 基于weak_ptr + + // https://www.cnblogs.com/yang-wen/p/8573269.html + +## 智能指针的基本用法 + +* shared_ptr + 接受指针作为参数的智能指针的构造函数是explicit类型,意味着只能以初始化的方式定义。 + ``` + shared_ptr p1; + //被初始化成为一个空指针 + + shared_ptr p2 (new int(4)); + //指向一个值是4的int类型数据 + + shared_ptr p3 = new int(4); + //错误,必须直接初始化 + ``` + + shared_ptr的一些操作 + ``` + shared_ptr p; + //空智能指针,可指向类型是T的对象 + + if(p) + //如果p指向一个对象,则是true + + (*p) + //解引用获取指针所指向的对象 + + p -> number == (*p).number; + + p.get(); + //返回p中保存的指针 + + swap(p,q); + //交换p q指针 + + p.swap(q); + //交换p,q指针 + + make_shared(args) + //返回一个shared_ptr的对象,指向一个动态类型分配为T的对象,用args初始化这个T对象 + shared_ptr p1 = make_shared(10, '9'); + shared_ptr p2 = make_shared("hello"); + shared_ptr p3 = make_shared(); + + shared_ptr p(q) + //p 是q的拷贝,q的计数器++,这个的使用前提是q的类型能够转化成是T* + + p = q; + //p的引用计数-1,q的+1,p为零释放所管理的内存 + + p.unique(); + //判断引用计数是否是1,是,返回true + + p.use_count(); + //返回和p共享对象的智能指针数量 + ``` + +* weak_ptr +``` +``` + +* unique_ptr + ``` + unique_ptr p(new string("China")); + //没问题 + + unique_ptr p (q); + //错误,不支持拷贝 + + unique_ptr q; + + q = p; + //错误,不支持赋值 + ``` + + unique_ptr的一些操作: + ``` + unique_ptr p; + //空智能指针,可指向类型是T的对象 + + if(p) + //如果p指向一个对象,则是true + + (*p) + //解引用获取指针所指向的对象 + + p -> number == (*p).number; + + p.get(); + //返回p中保存的指针 + + swap(p,q); + //交换p q指针 + + p.swap(q); + //交换p,q指针 + + unique_ptrp; + //p使用D类型的可调用对象释放它的指针 + + p = nullptr; + //释放对象,将p置空 + + p.release(); + //p放弃对指针的控制,返回指针,p置数空 + + p.reset(); + //释放p指向的对象 + + p.reset(q); + //让u指向内置指针q + ``` + +* weak ptr + weak ptr 并不执行raw Pointer,而是指向shared ptr。 + ``` + weak_ptr w(sp); + //定义一个和shared_ptr sp指向相同对象的weak_ptr w,T必须能转化成sp指向的类型 + + w = p; + //p是shared_ptr或者weak_ptr,w和p共享对象 + + w.reset(); + //w置为空 + + w.use_count(); + //计算与w共享对象的shared_ptr个数 + + w.expired(); + //w.use_count()为0,返回true + + w.lock(); + //w.expired()为true,返回空shared_ptr,否则返回w指向对象的shared_ptr + ``` + +## 其他 + +* shared ptr的错误用法 + + 写一个错误的shared_ptr的使用例子: + ``` + #include + #include + using namespace std; + + struct Task + { + int mId; + int *p; + Task(int id) : mId(id) + { + p = new int[10]; + std::cout << "Task::Constructor" << std::endl; + } + ~Task() + { + std::cout << "p[1] : " << p[1] << std::endl; + delete[] p; + std::cout << "Task::Destructor" << std::endl; + } + }; + + int main() + { + // 使用shared ptr 的问题 + { + Task *task3 = new Task(333); + shared_ptr p1(task3); + shared_ptr p2(task3); // core + + // 原因p1 和 p2 都认为自己的引用计数是1,于是当自己声明周期结束的时候,去释放ptr。于是导致core + + // 这应该是c++智能智能被诟病的一个原因 + } + + // 改为unique ptr 就没有问题 + { + Task *task2 = new Task(222); + std::unique_ptr testPtr2(task2); + std::cout << testPtr2->mId << std::endl; + + std::unique_ptr testPtr3(task2); + std::cout << testPtr3->mId << std::endl; + } + } + ``` + +* enable_shared_from_this 的实现 + + 一个对象返回this指针,其实是无法确认这个对象是否是被智能指针管理的。这样就带来一个问题,如果没有办法确认,那么如果这个this对象被另外一个shared ptr管理。那么就会出现一个多个shared ptr 管理一个对象。 并且,每个shared ptr的use count 都是 = 1; + + 那么,释放的时候,这个对象就会被释放多次。两个shared ptr各自释放一次。 + + ``` + #include + #include + + class Bad + { + public: + std::shared_ptr getptr() { + return std::shared_ptr(this); + } + ~Bad() { std::cout << "Bad::~Bad() called" << std::endl; } + }; + + int main() + { + // 错误的示例,每个shared_ptr都认为自己是对象仅有的所有者 + // 造成2个非共享的share_ptr指向同一个对象,未增加引用计数导对象被析构两次。 + std::shared_ptr bp1(new Bad()); + std::shared_ptr bp2 = bp1->getptr(); + // 打印bp1和bp2的引用计数 + std::cout << "bp1.use_count() = " << bp1.use_count() << std::endl; + std::cout << "bp2.use_count() = " << bp2.use_count() << std::endl; + } // Bad 对象将会被删除两次 + ``` + + +--- + +附上一个《c++ 标准库》的例子 +``` +作者:明月照我心 +链接:https://zhuanlan.zhihu.com/p/72354412 +来源:知乎 +著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 + + 1 #include + 2 #include + 3 #include + 4 #include + 5 using namespace std; + 6 + 7 int main(void) + 8 { + 9 // two shared pointers representing two persons by their name +10 shared_ptr pNico(new string("nico")); +11 shared_ptr pJutta(new string("jutta"), +12 // deleter (a lambda function) +13 [](string *p) +14 { +15 cout << "delete " << *p << endl; +16 delete p; +17 } +18 ); +19 +20 // capitalize person names +21 (*pNico)[0] = 'N'; +22 pJutta->replace(0, 1, "J"); +23 +24 // put them multiple times in a container +25 vector> whoMadeCoffee; +26 whoMadeCoffee.push_back(pJutta); +27 whoMadeCoffee.push_back(pJutta); +28 whoMadeCoffee.push_back(pNico); +29 whoMadeCoffee.push_back(pJutta); +30 whoMadeCoffee.push_back(pNico); +31 +32 // print all elements +33 for (auto ptr : whoMadeCoffee) +34 cout << *ptr << " "; +35 cout << endl; +36 +37 // overwrite a name again +38 *pNico = "Nicolai"; +39 +40 // print all elements +41 for (auto ptr : whoMadeCoffee) +42 cout << *ptr << " "; +43 cout << endl; +44 +45 // print some internal data +46 cout << "use_count: " << whoMadeCoffee[0].use_count() << endl; +47 +48 return 0; +49 } + +// + +1)对智能指针pNico的拷贝是浅拷贝,所以当我们改变对象“Nico”的值为“Nicolai”时,指向它的指针都会指向新值。   + +2)指向对象“Jutta”的有四个指针:pJutta和pJutta的三份被安插到容器内的拷贝,所以上述程序输出的use_count为4。 +``` + diff --git "a/note/c++\346\250\241\346\235\277.md" "b/note/c++\346\250\241\346\235\277.md" deleted file mode 100644 index e69de29..0000000 diff --git "a/note/c++\346\250\241\346\235\277\344\270\216\346\263\233\345\236\213\347\274\226\347\250\213.md" "b/note/c++\346\250\241\346\235\277\344\270\216\346\263\233\345\236\213\347\274\226\347\250\213.md" new file mode 100755 index 0000000..c0f871a --- /dev/null +++ "b/note/c++\346\250\241\346\235\277\344\270\216\346\263\233\345\236\213\347\274\226\347\250\213.md" @@ -0,0 +1,3 @@ +# 模板与泛型编程 + +https://www.jianshu.com/p/57baa98fa337 \ No newline at end of file diff --git "a/note/c++\347\232\204new\345\222\214delete.md" "b/note/c++\347\232\204new\345\222\214delete.md" deleted file mode 100644 index d41098e..0000000 --- "a/note/c++\347\232\204new\345\222\214delete.md" +++ /dev/null @@ -1,74 +0,0 @@ -# c++ 的new和delete - - -* 使用placement new 在栈上面构建对象 - - ``` - class TEST - { - private: - int val; - public: - TEST(int value) - { - this->val = value; - } - void print() - { - cout<val<(raw_memory); - // placement new - for(int i=0;i<10;i++) - { - new(test+i) TEST(val); - } - - // visit - for(int i=0;i<10;i++) - { - (test+i)->print(); - } - - return 0; - } - ``` - - * 知识点 - - 1. 使用operator new 分配一块空间 (约等于malloc) - ``` - void * raw_memory = operator new(size); - ``` - - 2. 使用placement new 完成调用构造函数 - - ``` - new (raw_memory) Test(); - ``` - - - -* delete 的时候 我觉得这样安全一点 - - ``` - delete obj; - obj = NULL; # 让指针指空 - ``` - -* 推荐阅读 - - 1. https://wetest.qq.com/lab/view/318.html diff --git "a/note/c++\347\232\204\345\211\215\347\275\256\345\243\260\346\230\216.md" "b/note/c++\347\232\204\345\211\215\347\275\256\345\243\260\346\230\216.md" old mode 100644 new mode 100755 diff --git "a/note/c++\347\232\204\345\244\232\346\200\201\345\222\214\350\231\232\345\207\275\346\225\260.md" "b/note/c++\347\232\204\345\244\232\346\200\201\345\222\214\350\231\232\345\207\275\346\225\260.md" old mode 100644 new mode 100755 diff --git "a/note/c++\347\232\204\347\261\273\345\236\213\350\275\254\346\215\242cast.md" "b/note/c++\347\232\204\347\261\273\345\236\213\350\275\254\346\215\242cast.md" old mode 100644 new mode 100755 index e939647..fa6c5c0 --- "a/note/c++\347\232\204\347\261\273\345\236\213\350\275\254\346\215\242cast.md" +++ "b/note/c++\347\232\204\347\261\273\345\236\213\350\275\254\346\215\242cast.md" @@ -2,87 +2,133 @@ ## 目录 -* static_cast +## static_cast - ``` - // 在基本数据类型之间转换 - // 在int和char 类型之间的转换 - int val = 80; - char c = static_cast (val); - cout<(3.14); + 进行上行转换(把派生类的指针或引用转换成基类表示)是安全的; +   - // void * 转换为 int * - void * raw_memory = operator new (sizeof(int)); - int * p_int = static_cast(raw_memory); + 进行下行转换(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。 +   +* 用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。 +   +* 把空指针转换成目标类型的空指针。 +   +* 把任何类型的表达式转换成void类型。 - // int * 转换为 void * - void * void_p = static_cast(&val); +---- - ``` +比如: - **这个是我理解不了的地方 :** - ``` - // 这个是我理解不了的地方,在基本指针类型之间的转换 int * 和 char * ,会无法通过编译 - int * p_val = &val; - //char * p_c = static_cast(p_val); //为什么会报错? - char * p_c =(char *)p_val; - cout<<*p_c< (val); +cout<(&addr); - sockaddr * p = static_cast(pp); - - - //报错 - //同样的原因,我也不知道为什么 - sockaddr * p = static_cast(&addr); - } - ``` - - c语言的写法,进行类型转换,但是上面用static_cast 进行类型转换,就有问题 : - ``` - int sockfd; - struct sockaddr_in servaddr; - sockfd = Socket(AF_INET, SOCK_STREAM, 0); +// 在float 和int 之间转换 +int p = static_cast(3.14); + +// void * 转换为 int * +void * raw_memory = operator new (sizeof(int)); +int * p_int = static_cast(raw_memory); + +// int * 转换为 void * +void * void_p = static_cast(&val); + +``` + + +static_cast 相比较于c风格的类型转换,编译器自带了一些语法检查。比如int * 指针 转换为char * 指针,显然是不科学的。编译器会报错。 +``` +// 这个是我理解不了的地方,在基本指针类型之间的转换 int * 和 char * ,会无法通过编译 +int * p_val = &val; +//char * p_c = static_cast(p_val); +char * p_c =(char *)p_val; +cout<<*p_c<(&addr); + sockaddr * p = static_cast(pp); + + + //报错 + //同样的原因,我也不知道为什么 + sockaddr * p = static_cast(&addr); +} +``` + +c语言的写法,进行类型转换,但是上面用static_cast 进行类型转换,就有问题 : +``` +int sockfd; +struct sockaddr_in servaddr; +sockfd = Socket(AF_INET, SOCK_STREAM, 0); + +/* 填充struct sockaddr_in */ +bzero(&servaddr, sizeof(servaddr)); +servaddr.sin_family = AF_INET; +servaddr.sin_port = htons(SERV_PORT); +inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr); + +/* 强制转换成struct sockaddr */ +connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); +``` + +--- + +## dynamic_cast + +static_cast 在下行检查的时候(把基类指针或引用转换成派生类表示)时,由于没有动态类型检查,所以是不安全的。 + +dynamic_cast是可以在运行的时候,进行动态检查。检查需要运行时信息RTTI,而RTTI存储在虚函数表中。 + +[C++的对象布局]( +https://mp.weixin.qq.com/s?__biz=MzkyODE5NjU2Mw==&mid=2247484758&idx=1&sn=4e614430f666f63ab135c13a716d07c1&source=41#wechat_redirect) + +---- + +## const_cast +用于常量指针或引用与非常量指针或引用之间的转换,只有const_cast才可以对常量进行操作,一般都是用它来去除常量性,去除常量性是危险操作,还是要谨慎操作。 + +--- + +## reinterpret_cast +没啥场景,类似C语言中的强制类型转换,什么都可以转,万不得已不要使用,一般前三种转换方式不能解决问题了使用这种强制类型转换方式。 + +----- + +## 参考 +https://mp.weixin.qq.com/s/6YW7VX787X7kZiRBLbVn-Q -* dynamic_cast \ No newline at end of file +https://blog.csdn.net/wangshubo1989/article/details/49105627 \ No newline at end of file diff --git "a/note/c++\347\261\273\344\270\255\344\275\277\347\224\250static\345\222\214const.md" "b/note/c++\347\261\273\344\270\255\344\275\277\347\224\250static\345\222\214const.md" new file mode 100755 index 0000000..fd4eff6 --- /dev/null +++ "b/note/c++\347\261\273\344\270\255\344\275\277\347\224\250static\345\222\214const.md" @@ -0,0 +1,99 @@ +# c++在类中使用static和const的用法 + +我用到的几个场景: + +* 第一种 + + 如果类里面需要定义一个数组,比较好的方式在把size写为static const(在类中可见) + ``` + class CO_SCHEDULE + { + public: + // xxxx + + private: + static const int STACK_SIZE = 1024 * 1024; + char stack[STACK_SIZE]; + }; + ``` + +* 第二种 + 类中定义static变量 + + 而静态数据成员被当作是类的成员。也就是说,静态数据成员是该类的所有对象所共有的。对该类的多个对象来说,静态数据成员只分配一次内存,供所有对象共用。所以,静态数据成员的值对每个对象都是一样的,**它的值可以更新**。 + ``` + class Myclass + { + public: + int val; + static int mysum; + }; + int Myclass::mysum = 0; // 定义放在类的外面,并且这个不需要再写static了 + + int main() + { + cout << Myclass::mysum++ << endl; + cout << Myclass::mysum << endl; + return 0; + } + ``` + +* 第三种 + + 在函数中定义static,这样可以避免反复初始化一个变量。 + ``` + struct LARGE_STRUCT + { + // 一个特定大的结构体 + }; + + int test_func() + { + static LARGE_STRUCT obj; // 定义为static,这个可以避免每次调用这个函数的时候,会进行初始化 + memset(&obj, 0, sizeof(obj)); + } + ``` + + +* 第四种 + + 这个是val的可见性只在当前文件内部可见。避免了暴露不必要的符号。 + ``` + static int val; // 定义一个全局static变量 + ``` + +* 第五种 + + 在程序中定义全部变量的时候 + file1.cpp + ``` + XXX obj1; // 定义一个全局变量 + ``` + + file2.cpp + ``` + cout << obj1.val << endl; // 在另外一个文件访问 + ``` + + 我一般会写成这样: + file1.cpp + ``` + XXX& get_obj() + { + static XXX obj1; // 定义一个全局变量 + return ob1; + } + ``` + + file2.cpp + ``` + cout << get_obj().val < +#include "adapter.h" + +using namespace std; + +int func(OLD_CLASS * old) +{ + old->dosomething(); + return 0; +} + +int adapter_demo(NEW_CLASS * new_obj) +{ + // ����˵ֱ�ӵ�����Ϊ�������Զ����� + // func(new) + + Adapter adapter(new_obj); + adapter.dosomething(); + + return 0; +} \ No newline at end of file diff --git a/note/design_pattern/example_code/adapter.h b/note/design_pattern/example_code/adapter.h new file mode 100755 index 0000000..4226c00 --- /dev/null +++ b/note/design_pattern/example_code/adapter.h @@ -0,0 +1,37 @@ +#ifndef __ADAPTER_H__ +#define __ADAPTER_H__ + +#include +using namespace std; + +class OLD_CLASS +{ + public: + virtual void dosomething() {cout<<"do something OLD_CLASS"<dosomething(); + } + + private: + NEW_CLASS * _new_obj; +}; + +#endif \ No newline at end of file diff --git a/note/design_pattern/example_code/command.c b/note/design_pattern/example_code/command.c new file mode 100755 index 0000000..2719dc9 --- /dev/null +++ b/note/design_pattern/example_code/command.c @@ -0,0 +1,13 @@ +#include "command.h" +#include + +int func() +{ + Receiver r; + ADD_COMMAND c1(&r); + MULT_COMMAND c2(&r); + + c1.exec(); + c2.exec(); + return 0; +} \ No newline at end of file diff --git a/note/design_pattern/example_code/command.h b/note/design_pattern/example_code/command.h new file mode 100755 index 0000000..fa7b931 --- /dev/null +++ b/note/design_pattern/example_code/command.h @@ -0,0 +1,40 @@ +#ifndef __COMMAND_H__ +#define __COMMAND_H__ + +#include +using namespace std; + +class Receiver +{ + public: + void add() {cout << "add" << endl;} + void multi() {cout << "multi" << endl;} +}; + +class COMMAND +{ + public: + virtual void exec() = 0; +}; + +class ADD_COMMAND : public COMMAND +{ + public: + ADD_COMMAND(Receiver * r):_r(r) {}; + void exec() {_r->add();}; + + private: + Receiver * _r; +}; + +class MULT_COMMAND : public COMMAND +{ + public: + MULT_COMMAND(Receiver * r) : _r(r) {}; + void exec() {_r->multi();}; + + private: + Receiver * _r; +}; + +#endif diff --git a/note/design_pattern/example_code/deco.c b/note/design_pattern/example_code/deco.c new file mode 100755 index 0000000..3961864 --- /dev/null +++ b/note/design_pattern/example_code/deco.c @@ -0,0 +1,4 @@ +#include "deco.h" +#include +using namespace std; + diff --git a/note/design_pattern/example_code/deco.h b/note/design_pattern/example_code/deco.h new file mode 100755 index 0000000..574375f --- /dev/null +++ b/note/design_pattern/example_code/deco.h @@ -0,0 +1,50 @@ +#ifndef __DECO_H__ +#define __DECO_H__ + +#include +using namespace std; + +class Cake +{ +public: + virtual void showCake()=0; + virtual ~Cake(){}; + std::string name; +}; + +class ConcreteCake :public Cake +{ +public: + ConcreteCake() + { + name = "ԭʼ����"; + } + void showCake(){ std::cout << name.c_str() << std::endl; }; + virtual ~ConcreteCake(){}; +}; + +class CakeDecrator :public Cake +{ +protected: + Cake* pCake; //ά��һ��Cake��������ã�ΪCake��������װ�� +public: + virtual void showCake() = 0; + virtual ~CakeDecrator(){}; +}; + +class CakeDecratorMilk : public CakeDecrator +{ + public: + CakeDecratorMilk(Cake* pCake) + { + this->pCake = pCake; + } + void showCake() + { + this->name = pCake->name + "������"; + std::cout << name.c_str()< +#include +using namespace std; + +#include "factory.h" + +string FRUIT::get_name() const +{ + return _name; +} +string FRUIT::name() const +{ + return _name; +} + +string APPLE::get_name() const +{ + string tmp = "apple + : " + name(); + return tmp; +} + +FRUIT* APPLE_FACTORY::build_obj(const string & name) +{ + FRUIT * fruit = new APPLE(name); + cout << fruit->get_name() << endl; + return fruit; +} \ No newline at end of file diff --git a/note/design_pattern/example_code/factory.h b/note/design_pattern/example_code/factory.h new file mode 100755 index 0000000..869590d --- /dev/null +++ b/note/design_pattern/example_code/factory.h @@ -0,0 +1,44 @@ +#ifndef __FACTORY_H__ +#define __FACTORY_H__ + +#include +#include +using namespace std; + +class FRUIT +{ + public: + FRUIT(const string &name):_name(name) {} + ~FRUIT() {} + + public: + virtual string get_name() const; + string name() const; + + private: + string _name; +}; + +class APPLE : public FRUIT +{ + public: + APPLE(string name):FRUIT(name) {} + ~APPLE() {} + + public: + string get_name() const; +}; + +class FACTORY +{ + public: + virtual FRUIT * build_obj(const string & name) = 0; +}; + +class APPLE_FACTORY : public FACTORY +{ + public: + FRUIT * build_obj(const string & name); +}; + +#endif \ No newline at end of file diff --git a/note/design_pattern/example_code/fecade.c b/note/design_pattern/example_code/fecade.c new file mode 100755 index 0000000..1d5ece4 --- /dev/null +++ b/note/design_pattern/example_code/fecade.c @@ -0,0 +1,18 @@ +#include +#include "fecade.h" + +FECADE_OBJ* FECADE::build_obj() +{ + FECADE_OBJ * obj = new FECADE_OBJ(); + + // 1. step 1 + obj->set_name(); + + // 2. step 2 + obj->set_attr(); + + // 3. step 3 + obj->set_info(); + + return obj; +} \ No newline at end of file diff --git a/note/design_pattern/example_code/fecade.h b/note/design_pattern/example_code/fecade.h new file mode 100755 index 0000000..0db3fb6 --- /dev/null +++ b/note/design_pattern/example_code/fecade.h @@ -0,0 +1,25 @@ +#ifndef __FECADE_H__ +#define __FECADE_H__ + +#include +using namespace std; + +class FECADE_OBJ +{ + public: + int _data; + + public: + void set_name() {cout << "set name" << endl;} + void set_attr() {cout << "set attr" << endl;} + void set_info() {cout << "set info" << endl;} +}; + +class FECADE +{ + public: + FECADE_OBJ* build_obj(); +}; + + +#endif \ No newline at end of file diff --git a/note/design_pattern/example_code/fecade2.c b/note/design_pattern/example_code/fecade2.c new file mode 100755 index 0000000..c478e68 --- /dev/null +++ b/note/design_pattern/example_code/fecade2.c @@ -0,0 +1,18 @@ +#include +#include "fecade2.h" + +FECADE2* FECADE2::build_obj() +{ + FECADE2 * obj = new FECADE2(); + + // 1. step 1 + obj->set_name(); + + // 2. step 2 + obj->set_attr(); + + // 3. step 3 + obj->set_info(); + + return obj; +} \ No newline at end of file diff --git a/note/design_pattern/example_code/fecade2.h b/note/design_pattern/example_code/fecade2.h new file mode 100755 index 0000000..e0096a7 --- /dev/null +++ b/note/design_pattern/example_code/fecade2.h @@ -0,0 +1,22 @@ +#ifndef __FECADE2_H__ +#define __FECADE2_H__ + +#include +using namespace std; + +class FECADE2 +{ + public: + void set_name() {cout << "set name" << endl;} + void set_attr() {cout << "set attr" << endl;} + void set_info() {cout << "set info" << endl;} + + public: + static FECADE2* build_obj(); + + public: + int _data; +}; + + +#endif \ No newline at end of file diff --git a/note/design_pattern/example_code/flyweight.c b/note/design_pattern/example_code/flyweight.c new file mode 100755 index 0000000..9ca25ed --- /dev/null +++ b/note/design_pattern/example_code/flyweight.c @@ -0,0 +1,31 @@ +#include +#include + +#include "flyweight.h" + +using namespace std; + +FLYWEIGHT_OBJ* FLYWEIGHT::build_obj(int key) +{ + if (_map.find(key) == _map.end()) + { + FLYWEIGHT_OBJ * obj = new FLYWEIGHT_OBJ(); + _map[key] = obj; + return obj; + } + else + { + return _map[key]; + } +} + +int FLYWEIGHT::clear() +{ + map::iterator iter = _map.begin(); + for (; iter != _map.end(); iter++) + { + FLYWEIGHT_OBJ * obj = iter->second; + delete obj; + } + return 0; +} \ No newline at end of file diff --git a/note/design_pattern/example_code/flyweight.h b/note/design_pattern/example_code/flyweight.h new file mode 100755 index 0000000..ad22028 --- /dev/null +++ b/note/design_pattern/example_code/flyweight.h @@ -0,0 +1,27 @@ +#ifndef __FLY_WEIGHT_H__ +#define __FLY_WEIGHT_H__ + +#include +#include + +using namespace std; + +class FLYWEIGHT_OBJ +{ + public: + FLYWEIGHT_OBJ():_data(0) {cout << "create obj" < _map; +}; + +#endif \ No newline at end of file diff --git a/note/design_pattern/example_code/observer.c b/note/design_pattern/example_code/observer.c new file mode 100755 index 0000000..ee86e77 --- /dev/null +++ b/note/design_pattern/example_code/observer.c @@ -0,0 +1,23 @@ +#include +#include + +#include "observer.h" +using namespace std; + +int TOPIC::notfiy() +{ + cout << "TOPIC::notfiy" << endl; + return 0; +} + +int NEWS::notfiy() +{ + cout << "TOPIC::notfiy" << endl; + return 0; +} + +int MUSIC::notfiy() +{ + cout << "TOPIC::notfiy" << endl; + return 0; +} diff --git a/note/design_pattern/example_code/observer.h b/note/design_pattern/example_code/observer.h new file mode 100755 index 0000000..210372d --- /dev/null +++ b/note/design_pattern/example_code/observer.h @@ -0,0 +1,51 @@ +#ifndef __OBSERVER_H__ +#define __OBSERVER_H__ + +#include +#include + +class TOPIC +{ + public: + TOPIC() {} + ~TOPIC() {} + + public: + virtual int notfiy(); +}; + +class NEWS : public TOPIC +{ + public: + NEWS() {} + ~NEWS() {} + + public: + virtual int notfiy(); +}; + +class MUSIC : public TOPIC +{ + public: + MUSIC(){} + ~MUSIC(){} + + public: + virtual int notfiy(); +}; + +class OBSERVER +{ + public: + OBSERVER() {} + ~OBSERVER() {} + + public: + int add(TOPIC*) {return 0;} + int rm(TOPIC*) {return 0;} + + private: + std::vector topic_vec; +}; + +#endif \ No newline at end of file diff --git a/note/design_pattern/example_code/proxy.c b/note/design_pattern/example_code/proxy.c new file mode 100755 index 0000000..a5d8637 --- /dev/null +++ b/note/design_pattern/example_code/proxy.c @@ -0,0 +1,17 @@ +#include +#include "proxy.h" +using namespace std; + +int REQUEST::do_requst() +{ + cout << "do request" << endl; + return 0; +} + +int PROXY::do_request_proxy() +{ + pre_request(); + do_requst(); + post_request(); + return 0; +} \ No newline at end of file diff --git a/note/design_pattern/example_code/proxy.h b/note/design_pattern/example_code/proxy.h new file mode 100755 index 0000000..4666852 --- /dev/null +++ b/note/design_pattern/example_code/proxy.h @@ -0,0 +1,27 @@ +#ifndef __PROYX_H__ +#define __PROYX_H__ + +#include +using namespace std; + +class REQUEST +{ + public: + REQUEST() {} + ~REQUEST() {} + + public: + int do_requst(); +}; + + +class PROXY : public REQUEST +{ + public: + int do_request_proxy(); + + void pre_request() {cout<<"pre"< +#include "singleton.h" + +SINGLETON * SINGLETON::_instance = get_instance(); + +SINGLETON* SINGLETON::get_instance() +{ + if (_instance == NULL) + { + LOCK guard; + if (_instance == NULL) + { + _instance = new SINGLETON(); + } + } + return _instance; +} \ No newline at end of file diff --git a/note/design_pattern/example_code/singleton.h b/note/design_pattern/example_code/singleton.h new file mode 100755 index 0000000..abfb3ec --- /dev/null +++ b/note/design_pattern/example_code/singleton.h @@ -0,0 +1,24 @@ +#ifndef __SINGLETON_H__ +#define __SINGLETON_H__ + +#include +using namespace std; + +class LOCK +{ + public: + LOCK(){} + ~LOCK(){} +}; + +class SINGLETON +{ + public: + static SINGLETON * get_instance(); + ~SINGLETON() {} + private: + SINGLETON() { cout <<"SINGLETON()"< +#include "strategy.h" +using namespace std; + +int TAX::cal_tax() +{ + cout << "TAX cal_tax" << endl; + return 0; +} + +int CHINA_TAX::cal_tax() +{ + cout << "CHINA_TAX cal_tax" << endl; + return 0; +} \ No newline at end of file diff --git a/note/design_pattern/example_code/strategy.h b/note/design_pattern/example_code/strategy.h new file mode 100755 index 0000000..7b248d1 --- /dev/null +++ b/note/design_pattern/example_code/strategy.h @@ -0,0 +1,24 @@ +#ifndef __STRATEGY_H__ +#define __STRATEGY_H__ + +class TAX +{ + public: + TAX(){} + ~TAX(){} + public: + virtual int cal_tax(); +}; + +class CHINA_TAX : public TAX +{ + public: + CHINA_TAX(){} + ~CHINA_TAX(){} + + public: + virtual int cal_tax(); +}; + + +#endif \ No newline at end of file diff --git a/note/design_pattern/example_code/template.c b/note/design_pattern/example_code/template.c new file mode 100755 index 0000000..5bccc85 --- /dev/null +++ b/note/design_pattern/example_code/template.c @@ -0,0 +1,53 @@ +#include +#include "template.h" + +using namespace std; + +int FRAMEWORK::init() +{ + cout << "frame work init" << endl; + return 0; +} + +int FRAMEWORK::load() +{ + cout << "frame work load" << endl; + return 0; +} + +int FRAMEWORK::work() +{ + cout << "frame work work" << endl; + return 0; +} + +int FRAMEWORK::fini() +{ + cout << "frame work fini" << endl; + return 0; +} + +// BUSINESS +int BUSINESS::init() +{ + cout << "business work init" << endl; + return 0; +} + +int BUSINESS::load() +{ + cout << "business work load" << endl; + return 0; +} + +int BUSINESS::work() +{ + cout << "business work work" << endl; + return 0; +} + +int BUSINESS::fini() +{ + cout << "business work fini" << endl; + return 0; +} diff --git a/note/design_pattern/example_code/template.h b/note/design_pattern/example_code/template.h new file mode 100755 index 0000000..84ebe93 --- /dev/null +++ b/note/design_pattern/example_code/template.h @@ -0,0 +1,31 @@ +#ifndef __TEMPLATE_H__ +#define __TEMPLATE_H__ + + +class FRAMEWORK +{ + public: + FRAMEWORK() {} + ~FRAMEWORK(){} + + public: + virtual int init(); + virtual int load(); + virtual int work(); + virtual int fini(); +}; + +class BUSINESS : public FRAMEWORK +{ + public: + BUSINESS() {} + ~BUSINESS(){} + + public: + virtual int init(); + virtual int load(); + virtual int work(); + virtual int fini(); +}; + +#endif \ No newline at end of file diff --git a/note/design_pattern/example_code/test_main.c b/note/design_pattern/example_code/test_main.c new file mode 100755 index 0000000..0c44090 --- /dev/null +++ b/note/design_pattern/example_code/test_main.c @@ -0,0 +1,46 @@ +#include +#include "singleton.h" +#include "template.h" +#include "factory.h" +#include "flyweight.h" +#include "fecade.h" +#include "fecade2.h" +#include "proxy.h" + +using namespace std; + +int main() +{ + cout << "main" << endl; + + SINGLETON * instance = SINGLETON::get_instance(); + if (instance != NULL) + { + cout << "get instance" << endl; + } + + FRAMEWORK * business = new BUSINESS(); + business->init(); + business->load(); + business->work(); + business->fini(); + + FACTORY * f = new APPLE_FACTORY(); + f->build_obj("hahah"); + + FLYWEIGHT mgr; + int key1 = 100; + FLYWEIGHT_OBJ * obj1 = mgr.build_obj(key1); + FLYWEIGHT_OBJ * obj2 = mgr.build_obj(key1); + + // FECADE fecade; + // fecade.build_obj(); + + FECADE2 f2; + f2.build_obj(); + + PROXY proxy; + proxy.do_request_proxy(); + + return 0; +} \ No newline at end of file diff --git "a/note/design_pattern/note/0\346\250\241\346\235\277\346\250\241\345\274\217.md" "b/note/design_pattern/note/0\346\250\241\346\235\277\346\250\241\345\274\217.md" new file mode 100755 index 0000000..3a46296 --- /dev/null +++ "b/note/design_pattern/note/0\346\250\241\346\235\277\346\250\241\345\274\217.md" @@ -0,0 +1,81 @@ +## 模板模式 + +在日常的开发中,经常遇到的场景是: +``` +int main() +{ + library lib(); // 框架层逻辑 + application app(); // 应用层逻辑 + + lib.step1(); + lib.step2(); + + if(app.step3()) + { + lib.step4(); + app.step5(); + } + + // xxx +} +``` +--- + +如果把代码写成下面的样子,看看会不会更好? +``` +class library +{ + public: + void step1(); + void step2(); + void step3(); + + // 提供给app实现 + virtual void step3() = 0; + virtual void step5() = 0; + + // 逻辑 + void run() + { + step1(); + step2(); + + if(step3()) + { + step4(); + step5(); + } + } +}; + +class app : public library +{ + public: + void step3() + { + // dosomething + } + + void step5() + { + // dosomething + } +}; + +int main() +{ + library lib(); + lib.run(); + + + return 0; +} +``` + +对比一下,这样的好处是: + +lib层面提供抽象的接口,step3(), step5(),继承的app类可以提供自己的实现。这样对于频繁的变化的app类,修改自己实现的step3,step5函数即可。 + +这样可能更加符合基本的设计原则,开放封闭原则 和 依赖倒置原则(依赖于抽象而不是依赖于具体)。 + +实际上,在现在的各种框架里面都可以看到这样的影子。lib层面在开发的层面上,已经提供了相关的逻辑的接口,app层面只需要继承这个接口,实现里面的逻辑即可。 \ No newline at end of file diff --git "a/note/design_pattern/note/10\350\243\205\351\245\260\345\231\250\346\250\241\345\274\217.md" "b/note/design_pattern/note/10\350\243\205\351\245\260\345\231\250\346\250\241\345\274\217.md" new file mode 100755 index 0000000..72b2077 --- /dev/null +++ "b/note/design_pattern/note/10\350\243\205\351\245\260\345\231\250\346\250\241\345\274\217.md" @@ -0,0 +1,79 @@ +## 装饰器模式 + +对于一个class的设计,如果需要引入一个新的功能,比如企鹅类添加一个会飞的方法。加入这个方法会破环原有的类的设计,另外一个方法就是引入装饰器模式。 + +这个模式在很多的项目可以看到,**最明显的一个标志是,一个Decrator的class,持有基类class的指针。** + +补充一个图: + + +``` +class Decrator :public BASE +{ +protected: + BASE* base; //维护一个base对象的引用,为bass对象添加装饰 +public: + +}; +``` + +----------- + +基类对象: +``` +//定义一个原始的抽象类蛋糕,装饰器的功能是给蛋糕加上各种装饰,如奶油,巧克力,瓜子仁,花生米等 +class Cake +{ +public: + virtual void showCake()=0; + virtual ~Cake(){}; + std::string name; +}; + +class ConcreteCake :public Cake +{ +public: + ConcreteCake() + { + name = "原始蛋糕"; + } + void showCake(){ std::cout << name.c_str() << std::endl; }; + virtual ~ConcreteCake(){}; +}; + +// 装饰器类 +class CakeDecrator :public Cake +{ +protected: + Cake* pCake; //维护一个Cake对象的引用,为Cake对象添加装饰 +public: + virtual void showCake() = 0; + virtual ~CakeDecrator(){}; +}; + +class CakeDecratorMilk : public CakeDecrator +{ + public: + CakeDecratorMilk(Cake* pCake) + { + this->pCake = pCake; + } + void showCake() + { + this->name = pCake->name + "加奶油"; + std::cout << name.c_str()<showCake(); + + CakeDecratorMilk* pDecMilk = new CakeDecratorMilk(pConCake); + pDecMilk->showCake(); + + // xxx +} +``` \ No newline at end of file diff --git "a/note/design_pattern/note/11\345\221\275\344\273\244\346\250\241\345\274\217.md" "b/note/design_pattern/note/11\345\221\275\344\273\244\346\250\241\345\274\217.md" new file mode 100755 index 0000000..2fbc0ce --- /dev/null +++ "b/note/design_pattern/note/11\345\221\275\344\273\244\346\250\241\345\274\217.md" @@ -0,0 +1,25 @@ +## 命令模式 + +命令模式核心的是把不同的操作行为都封装为command的派生类。然后提供一个exec()函数,把自己的行为实现在这个函数内部。这样上层只需要关系exec函数就可以。 + +不过,命令模式我还没有体会它的博大精深,感觉一个类要被拆分为更多的类,把他们都封装为command类的派生类。 +看起来反而更复杂了。 + +``` +int func() +{ + SHIT shit_obj; + shit_obj.do_copy(); + shit_obj.do_paste(); +} +``` + +// command模式改良 +``` +class COMMAMD +{ + +}; + +class CO +``` \ No newline at end of file diff --git "a/note/design_pattern/note/12\351\227\250\351\235\242fecade\346\250\241\345\274\217.md" "b/note/design_pattern/note/12\351\227\250\351\235\242fecade\346\250\241\345\274\217.md" new file mode 100755 index 0000000..d5a6003 --- /dev/null +++ "b/note/design_pattern/note/12\351\227\250\351\235\242fecade\346\250\241\345\274\217.md" @@ -0,0 +1,34 @@ +## 门面Fecade模式 + +门面模式很像一个中介,帮client把一些逻辑隐藏起来,对外提供简洁的接口。其实,这个不仅仅是一个设计模式,更多的表现的是设计的分层。 + +``` +{ + WORKER work; + + work.init(); + work.load(); + work.do(); +} +``` + + +``` +class FECADE +{ + int do() + { + work->init(); + work->load(); + work->do(); + } +}; + +{ + WORKER work; + FECADE fecade(work); + + // + fecade.do(); +} +``` \ No newline at end of file diff --git "a/note/design_pattern/note/1\347\255\226\347\225\245\346\250\241\345\274\217.md" "b/note/design_pattern/note/1\347\255\226\347\225\245\346\250\241\345\274\217.md" new file mode 100755 index 0000000..e8b2914 --- /dev/null +++ "b/note/design_pattern/note/1\347\255\226\347\225\245\346\250\241\345\274\217.md" @@ -0,0 +1,63 @@ +## 策略模式 + +策略模式使用的一个常见的场景: + + +如果你的代码里面有大量的if-else, switch-case, 那么可能是一个需要考虑策略模式了。 + +``` +int main() +{ + if (type == "中国") + { + // 使用中国的方式计算税务 + } + else if (type == "美国") + { + // 使用美国的方式计算税务 + } + else if (type == "xxx") + { + // 其他xxx + } + else + { + // 其他 + } +} +``` + + +这是一种看起来具有 “坏味道”的代码。 + +如果把代码写成下面的样子,看看会不会更好? +``` +class TAX +{ +public: + virtual void calc_tax() = 0; +}; + +class TAX_CHINA : public TAX +{ +public: + void calc_tax(); +}; + +class TAX_US : public TAX +{ +public: + void calc_tax(); +}; + +int main() +{ + TAX_CHINA tax; + tax.calc_tax(); +} +``` + +对比一下,这种模式的好处显而易见,通过使用多态的方式来控制“变化”。将变化控制在多态的函数里面。这是典型的开放封闭原则和依赖抽象的原则。 + +如果有一天一个人跳出来多,我还要新家几个类型,那对于这个模式来说,只需要新加一个class 继承一把,把逻辑写进行就可以。 + diff --git "a/note/design_pattern/note/2\350\247\202\345\257\237\350\200\205\346\250\241\345\274\217.md" "b/note/design_pattern/note/2\350\247\202\345\257\237\350\200\205\346\250\241\345\274\217.md" new file mode 100755 index 0000000..bebdf01 --- /dev/null +++ "b/note/design_pattern/note/2\350\247\202\345\257\237\350\200\205\346\250\241\345\274\217.md" @@ -0,0 +1,38 @@ +## 观察者模式 + +观察者模式是一个非常经典的模式。在大量的软件中都会使用。这个就不举例子了,直接写这个模式的demo了。 + +``` +class SUBJECT +{ + vector observer_vector; + public: + void add_ob(); + void rm_ob(); + + void update() + { + for (xxx) + { + ob->notify(); + } + } +}; + +class OBSERVER +{ + public: + vitual void notify () = 0; +}; + +class OBSERVER_V1: public OBSERVER +{ + public: + void notify () + { + // do something + } +}; +``` + +不同类型的observer可以继承基类observer,实现自己不同的notify函数。 \ No newline at end of file diff --git "a/note/design_pattern/note/3\345\267\245\345\216\202\346\250\241\345\274\217.md" "b/note/design_pattern/note/3\345\267\245\345\216\202\346\250\241\345\274\217.md" new file mode 100755 index 0000000..bac3be3 --- /dev/null +++ "b/note/design_pattern/note/3\345\267\245\345\216\202\346\250\241\345\274\217.md" @@ -0,0 +1,72 @@ +## 工厂模式 + +工厂模式的作用是绕开new的一种设计模式 + +``` +class FRUIT +{ + public: + virtual void show_name() = 0; + virtual ~FRUIT() {}; +}; + +class APPLE_FRUIT: public FRUIT +{ + public: + void show_name() + { + cout << "apple" << endl; + } +}; + +class BANAN_FRUIT: public FRUIT +{ + public: + void show_name() + { + cout << "banan" << endl; + } +}; + +class FACTORY +{ + public: + virtual FRUIT* build_fruit() = 0; +}; + +class APPLE_FACTORY: public FACTORY +{ + public: + FRUIT * build_fruit() + { + return new APPLE_FRUIT(); + } +}; + +class BANAN_FACTORY: public FACTORY +{ + public: + FRUIT * build_fruit() + { + return new BANAN_FRUIT(); + } +}; + +int main() +{ + // factory (工厂的这一层还是需要new的) + FACTORY * factory = new BANAN_FACTORY(); + + { + // 水果这一层是看不到new的 + // 工厂的基类指针指到了什么类型的工厂对象,就会build出什么类型的水果 + FRUIT * fruit = factory->build_fruit(); + fruit->show_name(); + + // todo + // ... + } + + return 0; +} +``` \ No newline at end of file diff --git "a/note/design_pattern/note/4\345\215\225\344\276\213\346\250\241\345\274\217.md" "b/note/design_pattern/note/4\345\215\225\344\276\213\346\250\241\345\274\217.md" new file mode 100755 index 0000000..25938fe --- /dev/null +++ "b/note/design_pattern/note/4\345\215\225\344\276\213\346\250\241\345\274\217.md" @@ -0,0 +1,213 @@ +## 单例模式 + +单例模式就不多说了,class的设计方 提供给class的使用方唯一的对象。 + +``` +class SINGLETON +{ + private: + SINGLETON() {} + ~ SINGLETON() {} + static SINGLETON * instance; + + public: + static SINGLETON * get_instance() + { + if (instance == NULL) + { + instance = new SINGLETON(); + return instance; + } + return instance; + } + + void dosomething() + { + cout << "do something" << endl; + } +}; + +SINGLETON* SINGLETON::instance = NULL; + +int main() +{ + SINGLETON * instance = SINGLETON::get_instance(); + instance->dosomething(); + + return 0; +} +``` + +如果是多线程的环境下,上面的代码有些问题。需要写一个多线程安全的版本。 +``` + static SINGLETON * get_instance() + { + LOCK lock(); //持有一把锁,但是这个锁的粒度太大了 + if (instance == NULL) + { + instance = new SINGLETON(); + return instance; + } + return instance; + } +``` + + +改良版本: + +双检查版本: 检查两次 +``` + static SINGLETON * get_instance() + { + if (instance == NULL) + { + LOCK lock(); // + if (isntance == NULL) + { + instance = new SINGLETON(); + return instance; + } + } + return instance; + } +``` + +这个版本也是后面被发现也是有问题的,就是著名的编译器优化重排“reorder”问题。正常的流程是: +``` +new SINGLETON(); +1. 分配空间 +2. 调用构造函数 +3. 返回 + +reorder +1. 分配空间 +2. 返回 +3. 调用构造函数 +``` + +那么针对单例模式的设计,就会存在这样一个问题:线程 A 开始创建 Singleton 的实例,此时线程 B已经调用了 getInstance的()方法,首先判断 instance 是否为 null。而我们上面说的那种模型, A 已经把 instance 指向了那块内存,只是还没来得及调用构造方法进行初始化,因此 B 检测到 instance 不为 null,于是直接把 instance 返回了。那么问题出现了:尽管 instance 不为 null,但是 A 并没有构造完成。 + + +解决的办法是c++11之后引入了atomic。C++11引进了memory model,提供了Atomic实现内存的同步访问,即不同线程总是获取对象修改前或修改后的值,无法在对象修改期间获得该对象。 +``` +#include +#include +using namespace std; + +class SINGLETON +{ + private: + SINGLETON() {} + ~ SINGLETON() {} + static atomic instance; + + public: + static SINGLETON * get_instance() + { + if (instance == NULL) + { + instance = new SINGLETON(); + return instance; + } + return instance; + } + + void dosomething() + { + cout << "do something" << endl; + } +}; + +atomic SINGLETON::instance { nullptr }; + +int main() +{ + SINGLETON * instance = SINGLETON::get_instance(); + instance->dosomething(); + + return 0; +} +``` + + +#### 其他 + +饱汉模式 / 饿汉模式 + +这个概念听着很高端,其实就是什么时候去创建对象。饱汉模式就是 提前创建好对象。 + + +饱汉模式 + +头文件 +``` +#ifndef __SINGLETON_H__ +#define __SINGLETON_H__ + +#include +using namespace std; + +class LOCK +{ + public: + LOCK(){} + ~LOCK(){} +}; + +class SINGLETON +{ + public: + static SINGLETON * get_instance(); + ~SINGLETON() {} + private: + SINGLETON() { cout <<"SINGLETON()"< +#include "singleton.h" + +SINGLETON * SINGLETON::_instance = get_instance(); // 提前创建好对象 + +SINGLETON* SINGLETON::get_instance() +{ + if (_instance == NULL) + { + LOCK guard; + if (_instance == NULL) + { + _instance = new SINGLETON(); + } + } + return _instance; +} +``` + +饿汉模式 +``` +#include +#include "singleton.h" + +SINGLETON * SINGLETON::_instance = NULL; // 没有提前创建模式,在调用的时候创建对象 + +SINGLETON* SINGLETON::get_instance() +{ + if (_instance == NULL) + { + LOCK guard; + if (_instance == NULL) + { + _instance = new SINGLETON(); + } + } + return _instance; +} +``` + +饱汉模式有一个优点,通过提前创建对象,来实现线程安全。 + diff --git "a/note/design_pattern/note/5\344\272\253\345\205\203\346\250\241\345\274\217.md" "b/note/design_pattern/note/5\344\272\253\345\205\203\346\250\241\345\274\217.md" new file mode 100755 index 0000000..5ec171f --- /dev/null +++ "b/note/design_pattern/note/5\344\272\253\345\205\203\346\250\241\345\274\217.md" @@ -0,0 +1,80 @@ +## 享元模式 + +--- + +享元模式的思路常见。就是当有可能重复创建对象的时候,对相同或相似对象的重用。 + +比如: +``` +int create_obj(int key) +{ + if (_map.find(key) == _map.end()) + { + // 创建对象 + // 插入map + } + else + { + // 直接返回对象 + } +} +``` + +cpp文件 +``` +FLYWEIGHT_OBJ* FLYWEIGHT::build_obj(int key) +{ + if (_map.find(key) == _map.end()) + { + FLYWEIGHT_OBJ * obj = new FLYWEIGHT_OBJ(); + _map[key] = obj; + return obj; + } + else + { + return _map[key]; + } +} + +int FLYWEIGHT::clear() +{ + map::iterator iter = _map.begin(); + for (; iter != _map.end(); iter++) + { + FLYWEIGHT_OBJ * obj = iter->second; + delete obj; + } + return 0; +} +``` + +hpp文件 +``` +#ifndef __FLY_WEIGHT_H__ +#define __FLY_WEIGHT_H__ + +#include +#include + +using namespace std; + +class FLYWEIGHT_OBJ +{ + public: + FLYWEIGHT_OBJ():_data(0) {cout << "create obj" < _map; +}; + +#endif +``` \ No newline at end of file diff --git "a/note/design_pattern/note/6\344\273\243\347\220\206\346\250\241\345\274\217.md" "b/note/design_pattern/note/6\344\273\243\347\220\206\346\250\241\345\274\217.md" new file mode 100755 index 0000000..e2e7b7d --- /dev/null +++ "b/note/design_pattern/note/6\344\273\243\347\220\206\346\250\241\345\274\217.md" @@ -0,0 +1,31 @@ +## 代理模式 PROXY模式 + +proxy最常见的使用场景是,当开发的时候,看到一坨像shit一样的老代码,里面有一个函数func,需要调整or修改里面的部分逻辑。但是这个函数有无数个被引用的地方。直接改动func里面的逻辑,危险并且进一步使shit上再加shit。 + +因此,可以不去修改func内部的逻辑。可以重新写一个PROXY类继承原来的类,重新实现里面的逻辑。 +``` +class OLD_CLASS +{ + int func() + { + // shit + } +}; + +class PROXY_SHIT : public OLD_CLASS +{ + int proy_func() + { + pre_invoke(); + + // invoke shit + old_class->func(); + + post_invoke(); + } + + private: + OLD_CLASS * old_class; +} + +``` \ No newline at end of file diff --git "a/note/design_pattern/note/7\351\200\202\351\205\215\345\231\250\346\250\241\345\274\217.md" "b/note/design_pattern/note/7\351\200\202\351\205\215\345\231\250\346\250\241\345\274\217.md" new file mode 100755 index 0000000..85b6b95 --- /dev/null +++ "b/note/design_pattern/note/7\351\200\202\351\205\215\345\231\250\346\250\241\345\274\217.md" @@ -0,0 +1,74 @@ +## 适配器模式 Adapter + +使用的场景: + +将一个类的接口转换为 用户希望的接口。可以是原本不兼容的接口 放到一起来使用。 + +举个栗子 +``` +// 开发的时候看到一个接口 +int func(OLD_CLASS * a) +{ + a->dosomething(); +} + +// 但是手上有的对象是B * b +int foo() +{ + NEW_CLASS b; + func(&b); // complier error +} +``` + +如果让类型B转换为类型A, 适配器翻译的很准确,就是一个转换的插座。解决不同接口的类型的问题。 + +``` +class OLD_CLASS +{ + public: + virtual void dosomething() {cout<<"do something OLD_CLASS"<dosomething(); + } + + private: + NEW_CLASS * _new_obj; +}; +``` + +``` +int func(OLD_CLASS * old) +{ + old->dosomething(); + return 0; +} + +int adapter_demo(NEW_CLASS * new_obj) +{ + // 比如说直接调用因为参数不对而报错 + // func(new) + + Adapter adapter(new_obj); + adapter.dosomething(); + + return 0; +} +``` \ No newline at end of file diff --git "a/note/design_pattern/note/8\347\212\266\346\200\201\346\234\272\346\250\241\345\274\217.md" "b/note/design_pattern/note/8\347\212\266\346\200\201\346\234\272\346\250\241\345\274\217.md" new file mode 100755 index 0000000..21a25ab --- /dev/null +++ "b/note/design_pattern/note/8\347\212\266\346\200\201\346\234\272\346\250\241\345\274\217.md" @@ -0,0 +1,13 @@ +## 状态机模式 + +状态机模式可以被用在 软件设计中维护复杂的异步逻辑。 +``` +class STATE_MACHINE +{ + int msg; + int state; + int next_stat; +}; +``` + +基本的思路是维护一张函数表,在当前的state下,收到什么样的消息(或超时),执行什么样的逻辑,进入的下一个状态是什么。 diff --git "a/note/design_pattern/note/9\350\264\243\344\273\273\351\223\276\346\250\241\345\274\217.md" "b/note/design_pattern/note/9\350\264\243\344\273\273\351\223\276\346\250\241\345\274\217.md" new file mode 100755 index 0000000..29bce4a --- /dev/null +++ "b/note/design_pattern/note/9\350\264\243\344\273\273\351\223\276\346\250\241\345\274\217.md" @@ -0,0 +1,103 @@ +## 责任链模式 + +责任链模式可以用于的场景是: + +对于一个对象req,可以定义一系列的class(责任链)来处理它。感觉对于一个http的请求,或者是一个客户端上行来的请求,可以使用这种模式,来定义一条流水线(责任链)进行处理。 + +``` +#include +#include + +using namespace std; + +enum class RequestType +{ + REQ_HANDLER1, + REQ_HANDLER2, + REQ_HANDLER3 +}; + +class Reqest +{ + string description; + RequestType reqType; +public: + Reqest(const string & desc, RequestType type) : description(desc), reqType(type) {} + RequestType getReqType() const { return reqType; } + const string& getDescription() const { return description; } +}; + +class ChainHandler{ + + ChainHandler *nextChain; + void sendReqestToNextHandler(const Reqest & req) + { + if (nextChain != nullptr) + nextChain->handle(req); + } +protected: + virtual bool canHandleRequest(const Reqest & req) = 0; + virtual void processRequest(const Reqest & req) = 0; +public: + ChainHandler() { nextChain = nullptr; } + void setNextChain(ChainHandler *next) { nextChain = next; } + + + void handle(const Reqest & req) + { + if (canHandleRequest(req)) + processRequest(req); + else + sendReqestToNextHandler(req); + } +}; + + +class Handler1 : public ChainHandler{ +protected: + bool canHandleRequest(const Reqest & req) override + { + return req.getReqType() == RequestType::REQ_HANDLER1; + } + void processRequest(const Reqest & req) override + { + cout << "Handler1 is handle reqest: " << req.getDescription() << endl; + } +}; + +class Handler2 : public ChainHandler{ +protected: + bool canHandleRequest(const Reqest & req) override + { + return req.getReqType() == RequestType::REQ_HANDLER2; + } + void processRequest(const Reqest & req) override + { + cout << "Handler2 is handle reqest: " << req.getDescription() << endl; + } +}; + +class Handler3 : public ChainHandler{ +protected: + bool canHandleRequest(const Reqest & req) override + { + return req.getReqType() == RequestType::REQ_HANDLER3; + } + void processRequest(const Reqest & req) override + { + cout << "Handler3 is handle reqest: " << req.getDescription() << endl; + } +}; + +int main(){ + Handler1 h1; + Handler2 h2; + Handler3 h3; + h1.setNextChain(&h2); + h2.setNextChain(&h3); + + Reqest req("process task ... ", RequestType::REQ_HANDLER3); + h1.handle(req); + return 0; +} +``` \ No newline at end of file diff --git a/note/docker.md b/note/docker.md old mode 100644 new mode 100755 index b0ae5b9..fd724a7 --- a/note/docker.md +++ b/note/docker.md @@ -106,12 +106,185 @@ dd5b26affce3 nginx "bash" 26 minutes ago docker exec -it my_nginx bash ``` +------ +### 例子 +``` +# 运行一个redis镜像 +sudo docker run -d -p 6379:6379 --name redis redis:latest + +# 关闭容器 +docker stop container-id + +# 查看名字 +docker images +REPOSITORY TAG IMAGE ID CREATED SIZE +redis latest 2f66aad5324a 12 days ago 117MB + +# 启动 +docker start redis + +# 进入容器 +docker exec -it redis /bin/bash +docker exec -it <容器ID> /bin/bash + +# 执行redis客户端 +redis-cli +127.0.0.1:6379> + +``` +``` +# 查看 +docker ps 查看当前运行中的容器 +docker images 查看镜像列表 +docker rm container-id 删除指定 id 的容器 +docker stop/start container-id 停止/启动指定 id 的容器 +docker rmi image-id 删除指定 id 的镜像 +docker volume ls 查看 volume 列表 +docker network ls 查看网络列表 +``` + +* 交互式 +``` +docker run -i -t ubuntu:15.10 /bin/bash + +各个参数解析: +-t: 在新容器内指定一个伪终端或终端。 +-i: 允许你对容器内的标准输入 (STDIN) 进行交互。 +``` + +* 查看日志 +``` +# 启动一个docker +docker run -d ubuntu:15.10 /bin/sh -c "while true; do echo hello world; sleep 1; done" + +# 查看日志 +docker logs <容器ID> +docker logs -f <容器ID> +``` + +* 查看网络端口映射 +``` +docker port <容器ID> +``` + +* top查看 +``` +docker top <容器ID> +UID PID PPID C STIME TTY TIME CMD +root 5695 30047 0 19:23 ? 00:00:00 sleep 1 +root 30047 30025 0 18:59 ? 00:00:00 /bin/sh -c while true; do echo hello world; sleep 1; done +``` + +* 镜像 +``` +$ docker pull hello-world +Using default tag: latest +latest: Pulling from library/hello-world +2db29710123e: Pull complete +Digest: sha256:6e8b6f026e0b9c419ea0fd02d3905dd0952ad1feea67543f525c73a0a790fefb +Status: Downloaded newer image for hello-world:latest +docker.io/library/hello-world:latest + +$ docker images +REPOSITORY TAG IMAGE ID CREATED SIZE +redis latest 2f66aad5324a 12 days ago 117MB +hello-world latest feb5d9fea6a5 17 months ago 13.3kB +ubuntu 15.10 9b9cb95443b5 6 years ago 137MB + +# 运行 +$ docker run hello-world + +# 删除 +$ docker rmi hello-world +``` + +---- +### Dockerfile +在dockerfile所在的目录执行docker build命令,构建自己的docker镜像。 +``` +docker build -t test:v1 . +-t 设置镜像名字和版本号 // 这里指的是镜像名称是test,版本是v1 +``` + +### 目录挂载 +* bind mount 直接把宿主机目录映射到容器内,适合挂代码目录和配置文件。可挂到多个容器上 +* volume 由容器创建和管理,创建在宿主机,所以删除容器不会丢失,官方推荐,更高效,Linux 文件系统,适合存储数据库数据。可挂到多个容器上 +* tmpfs mount 适合存储临时文件,存宿主机内存中。不可多容器共享。 +``` +docker run -p 8080:8080 --name test-hello -v D:/code:/app -d test:v1 +``` + +### 虚拟网络--多容器通信 +``` +# 创建一个名为test-net的网络 +docker network create test-net + +# 运行 Redis 在 test-net 网络中,别名redis +docker run -d --name redis --network test-net --network-alias redis redis:latest +``` + +### Docker-Compose +* docker-compose 把项目的多个服务集合到一起,一键运行 +* 在docker-compose.yml 文件所在目录,执行:docker-compose up就可以跑起来了 + +``` +在后台运行只需要加一个 -d 参数docker-compose up -d +查看运行状态:docker-compose ps +停止运行:docker-compose stop +重启:docker-compose restart +重启单个服务:docker-compose restart service-name +进入容器命令行:docker-compose exec service-name sh +查看容器运行log:docker-compose logs [service-name] +``` + +--- + +#### kubernetes +k8s可以干什么? +* 当你的应用只是跑在一台机器,直接一个 docker + docker-compose 就够了,方便轻松; +* 当你的应用需要跑在 3,4 台机器上,你依旧可以每台机器单独配置运行环境 + 负载均衡器; +* 当你应用访问数不断增加,机器逐渐增加到十几台、上百台、上千台时,每次加机器、软件更新、版本回滚,都会变得非常麻烦。这时候Kubernetes 就可以一展身手了。 +![tu](../pic/docker_1.png) + +pdd是k8s调度、管理的最小单位,一个 Pod 可以包含一个或多个容器,每个 Pod 有自己的虚拟IP。一个工作节点可以有多个 pod,主节点会考量负载自动调度 pod 到哪个节点运行。 + +#### 安装 +``` +curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 +sudo install minikube-linux-amd64 /usr/local/bin/minikube +``` + +``` +minikube start --force --driver=docker + +minikube kubectl + +minikube kubectl -- get pods -A +``` + + +* 工作负载分类 + * Deployment +适合无状态应用,所有pod等价,可替代 + * StatefulSet +有状态的应用,适合数据库这种类型。 + * DaemonSet +在每个节点上跑一个 Pod,可以用来做节点监控、节点日志收集等 + * Job & CronJob +Job 用来表达的是一次性的任务,而 CronJob 会根据其时间规划反复运行。 + + +---- ## 参考 - [docker 入门到实践](https://yeasy.gitbooks.io/docker_practice/image/pull.html) - [使用Docker快速搭建Nginx+PHP-FPM环境](https://www.jianshu.com/p/3384e342502b) + +- [docker 教程](https://docker.easydoc.net/doc/81170005/cCewZWoN/XQEqNjiu) + +- [k8s 教程](https://k8s.easydoc.net/docs/dRiQjyTY/28366845/6GiNOzyZ/9EX8Cp45) \ No newline at end of file diff --git "a/note/git\346\225\231\347\250\213.md" "b/note/git\346\225\231\347\250\213.md" old mode 100644 new mode 100755 index 8fb952b..f6e3675 --- "a/note/git\346\225\231\347\250\213.md" +++ "b/note/git\346\225\231\347\250\213.md" @@ -4,7 +4,6 @@ 1. Git 属于分布式版本控制系统,而 SVN 属于集中式。 - 2. 集中式版本控制只有中心服务器拥有一份代码,而分布式版本控制每个人的电脑上就有一份完整的代码。 3. 集中式版本控制有安全性问题,当中心服务器挂了所有人都没办法工作了。 @@ -15,6 +14,8 @@ 6. 中心服务器用来交换每个用户的修改,没有中心服务器也能工作,但是中心服务器能够 24 小时保持开机状态,这样就能更方便的交换修改。**Github 就是一个中心服务器。** +--- + ## Git Git 里面又三个概念:分别是工作区,暂存区,和版本库。 @@ -27,72 +28,67 @@ Git 里面又三个概念:分别是工作区,暂存区,和版本库。 下面这个图展示了工作区、版本库中的暂存区和版本库之间的关系: - -![tu](../pic/git_1.JPG) +![tu](../pic/git_6.JPG) --- -* 图中左侧为工作区,右侧为版本库。在版本库中标记为 "index" 的区域是暂存区(stage, index),标记为 "master" 的是 master 分支所代表的目录树。图中我们可以看出此时 "HEAD" 实际是指向 master 分支的一个"游标"。所以图示的命令中出现 HEAD 的地方可以用 master 来替换。图中的 objects 标识的区域为 Git 的对象库,实际位于 ".git/objects" 目录下,里面包含了创建的各种对象及内容。 +提交的流程是比较简答的,整理一下**回滚的流程**。 -* 当对工作区修改(或新增)的文件执行 "git add" 命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。 +搞明白要回滚的内容处于哪个状态。 -* 当执行提交操作(git commit)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。 +1. 修改后 未git add -* 当执行 "git reset HEAD 或 commit_id " "git reset -- \ "命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。(git reset HEAD 命令用于取消已缓存的内容) + * git checkout -- file // 回滚单个文件 -* 当执行 "git rm --cached \ " 命令时,会直接从暂存区删除文件,工作区则不做出改变。 + * git checkout . // 回滚全部 -* 当执行 "git checkout ." 或者 "git checkout -- \" 命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区的改动。 +2. 修改后 git add,未commit -* 当执行 "git checkout HEAD . 或 git checkoout commit_id . " 或者 "git checkout HEAD \" 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。 + * git reset HEAD file (省略head也是可以的 git reset file) ---- + // 回滚单个文件 + + // 这里的回滚流 指的是从版本库用head版本去覆盖stage区 + // 对于这个文件的内容,它是没有变化的,只是文件的状态改变了(相当于去掉 git add状态) + + // 如果想回滚文件的内容,那么再次使用git checkout -- file -比如现在有一个文件 test.txt -``` -git add test.txt 把文件的修改添加到暂存区 -git commit -m 'add' 把暂存区的修改提交到当前分支,提交之后暂存区就被清空了 -git reset -- test.txt 使用当前分支上的修改覆盖暂存区,用来撤销最后一次 git add files -git checkout -- test.txt 使用暂存区的修改覆盖工作目录,用来撤销本地修改 -``` + * git reset HEAD . (省略head也是可以的 git reset .) -![tu](../pic/git_3.JPG) + // 回滚全部 -可以跳过暂存区域直接从分支中取出修改,或者直接提交修改到分支中。 + // 这里的回滚流 指的是从版本库用head版本去覆盖stage区 -git commit -a 直接把所有文件的修改添加到暂存区然后执行提交。 +3. 修改后 git add,commit -git checkout HEAD -- files 取出最后一次修改,可以用来进行回滚操作。 + * reset 回滚: + git reset commit-id --hard -``` -# 如果不是很清楚,文件的修改是否从工作区 add 到了暂存区,还是已经commit 到了版本库, -# 可以使用 git status 命令 -# 如果已经 commit,那么显示: -git status -位于分支 master -无文件要提交,干净的工作区 -``` + git reflog + // 查看回滚commit-id -撒销一个合并 -``` -# 如果你觉得你合并后的状态是一团乱麻,想把当前的修改都放弃,你可以用下面的命令回到合并之前的状态 -git reset --hard HEAD -git reset --hard commit_id -``` + * revert 回滚: + + // 回滚会变成一次提交 + + git reset commit-id -## 查看 +--------- + +### 查看 ``` git status git status -s git log git log --stat +git reflog ``` +--- - -## 分支管理 +### 分支管理 查看分支: ``` @@ -127,15 +123,22 @@ git merge dev ``` git branch -d (branchname) ``` - -## git diff +---- +### git diff 用git diff来找你当前工作目录和上次提交与本地索引间的差异。 ``` -git diff +git diff (diff 本地和暂存区) +git diff HEAD (diff 暂存区和版本库) +git diff dir (仅对比某个目录下的diff) + +查看某次提交的改动细节 +git show 0b7454290bea ``` -## .gitignore +--- + +### .gitignore 首先,在你的工作区新建一个名称为.gitignore的文件。 **然后,把要忽略的文件名填进去,Git就会自动忽略这些文件。** @@ -149,74 +152,235 @@ git diff *.out ``` -## git的工具 +------- + +### git的工具 ``` # 很漂亮的图形的显示项目的历史 -gitk +* sourcetree ``` -## 参考 +### git配置 -- [廖雪峰教程](https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000) +* zsh 不卡顿 +``` +git config --add oh-my-zsh.hide-dirty 1 +git config --add oh-my-zsh.hide-status 1 +``` -- [cyc_git教程](https://github.com/CyC2018/CS-Notes/blob/master/docs/notes/Git.md) +* 不需要输入密码 +``` +git config --global user.email "you@example.com" +git config --global user.name "Your Name" +git config credential.helper store +``` -- [runoob教程](http://www.runoob.com/git/git-workspace-index-repo.html) +------- -- [具体的每一个git命令的使用](https://www.yiibai.com/git/git_diff.html) +### rebase - https://gist.github.com/285571052/72fe4e85290d170b9de4634b6ad8c082 +rebase常用来做两个事情,一个是`rebase master`这种操作;一个是重写提交记录这种操作; - https://git-scm.com/book/zh/v2 +* rebase master -- [关于远程仓库](https://www.jianshu.com/p/9685a56bdf7a) + https://waynerv.com/posts/git-rebase-intro/ -更新一部分: + `git rebase master` 简单的讲,就是把在master的改动移动到新的分支上,然后再把在这个分支上提交的内容追加到后面。 -![tu](../pic/git_4.png) + ``` + 在开发过程中使用 git rebase 还是 git merge,优缺点分别是什么? - 民工哥的回答 - 知乎 + https://www.zhihu.com/question/36509119/answer/2009073898 + ``` +* 重写提交记录 -![tu](../pic/git_5.png) + 在rebase前,可以先确认一下git默认的编辑器是不是vim,如果不是的话,可以先改为vim + git config --global core.editor "vim" + `git rebase -i HEAD~~` 把最近的2条记录合并,这个时候会进入到一个新的界面 + `git rebase -i HEAD~3` 把最近的3条记录合并 + `git rebase -i cf7e875` 合并这个版本之前的提交(不包含这个版本) + ``` + pick c7f5204 [dev](update main.cpp) + pick 4c66629 update main.cpp -### 分支管理 + # Rebase 92037d5..4c66629 onto 92037d5 (2 commands) + # + # Commands: + # p, pick = use commit + # r, reword = use commit, but edit the commit message + # e, edit = use commit, but stop for amending + # s, squash = use commit, but meld into previous commit + # f, fixup = like "squash", but discard this commit's log message + # x, exec = run command (the rest of the line) using shell + # d, drop = remove commit + # + # These lines can be re-ordered; they are executed from top to bottom. + # + # If you remove a line here THAT COMMIT WILL BE LOST. + # + # However, if you remove everything, the rebase will be aborted. + # + # Note that empty commits are commented out + ``` -merge表示的合并某一个分支到当前分支,**但是如果有冲突的话,需要收到解决冲突。** + 把第二条改为 + ``` + pick c7f5204 [dev](update main.cpp) + s 4c66629 update main.cpp + ``` -|命令|内容| -|:---:|:---:| -|git merge dev | #在当前分支和并dev分支| -|git checkout -b [branch-name]| 创建分支并且切换到这个分支| -|git branch -d [branch-name]|删除分支| + 然后查看一下,多条记录已经合并了。 +---- +## git分支开发流程 +``` +# 创建一个新的分支dev +git branch dev -### reset命令 +# 切换到这个分支 +git checkout dev -reset 一般指的是将版本库的内容撤回到暂存区。 -但是,也可以加上--hard 之后,将版本库的内容直接撤回到workspace里面。 +# 推送这个分支到远端 +git push origin dev:dev +# 开工写代码 +# balalalala -![tu](../pic/git_6.JPG) +# 写完了 提交 +# git add . +# git commit -m "xxxx" -| 命令 | 内容 | -|:---:|:---:| -|git reset -- test.txt | 使用当前版本仓库里面的内容覆盖暂存区,用来覆盖最git add的内容| -|git reset —hard [commit] | 暂存区、工作区的内容都会被修改到与提交点完全一致的状态 | -|git reset --hard HEAD |让工作区回到上次提交时的状态| -|git reset —soft [commit]| 只改变提交点,暂存区和工作目录的内容都不改变| +# 需要推送到远端的话 +git push origin dev +# 大功告成开发完毕 +# 切回 master 分支,拉取 master 的最新代码 -## checkout +# 切回开发分支(反向合并master) +git rebase master (后面要处理一些冲突) +# 解决冲突的办法 +修改提示冲突的文件,git add xxx // 标记已解决冲突 +git rebase --continue // 继续执行 -## diff +# 切换到master分支 +# 把dev分支的内容合并到master上 +git merge dev + +# 删除分支dev +git branch -d dev git删除本地分支 +git push origin --delete branch git删除远程分支 +``` + +# git tag +``` +# 查看标签 +git tag -| 命令 | 内容 | -|:---:|:---:| -|git diff | 显示暂存区和工作区的差异| -|git diff [file-name]|显示某一个文件,暂存区和工作区的差异| -|git diff HEAD|显示工作区与当前分支最新commit之间的差异| +# 创建标签 (轻量标签) +git tag v0.1 +# 创建附注标签 +git tag -a v0.2 -m "my version 0.2" -## fetch \ No newline at end of file +# 查看细节 +git show v0.1 + +# 共享标签 +git push origin v1.5 +git push origin --tags # 推送所有的标签 + +# 删除标签 +git tag -d v1.4-lw + +``` + +--- + +# 常用 +* 拉取远程非master分支 + + ``` + git clone git@github.com:zhaozhengcoder/CoderNoteBook.git + + git checkout -b feature/dev-test origin/feature/dev-test + ``` + +* 更新分支 + + ``` + 更新master + git pull origin master + + 更新feature/dev-test分支 (远程分支和本地分支名一致) + 切换到对应的分支在操作 + git pull origin feature/dev-test + + 如果远程分支名和本地分支名不一致的话 + git pull origin origin_branch:local_branch + git pull origin feature/dev-test:feature/dev-test + ``` + +* 如果更新的时候,出现冲突(本地也该了,远程也改了) + + ``` + $ git status + On branch master + Your branch is ahead of 'origin/master' by 2 commits. + (use "git push" to publish your local commits) + + You have unmerged paths. + (fix conflicts and run "git commit") + (use "git merge --abort" to abort the merge) + + Unmerged paths: + (use "git add ..." to mark resolution) + + both modified: readme.txt + + no changes added to commit (use "git add" and/or "git commit -a") + ``` + + ``` + 手动修改冲突的文件,然后 + git add readme.md (冲突的文件名) + ``` + +* 提交本地修改到远程分支 + + ``` + git push origin feature/dev-test + + 如果本地分支和远程分支名不一致 + git push origin feature/dev-test:feature/dev-test + ``` + +* 查看某个commit id的改动 + + ``` + git show 2580fba + ``` + +------- + +## 参考 + +- [廖雪峰教程](https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000) + +- [cyc_git教程](https://github.com/CyC2018/CS-Notes/blob/master/docs/notes/Git.md) + +- [runoob教程](http://www.runoob.com/git/git-workspace-index-repo.html) + +- [具体的每一个git命令的使用](https://www.yiibai.com/git/git_diff.html) + + https://gist.github.com/285571052/72fe4e85290d170b9de4634b6ad8c082 + + https://git-scm.com/book/zh/v2 + +- [关于远程仓库](https://www.jianshu.com/p/9685a56bdf7a) + +更新一部分: + +![tu](../pic/git_5.png) diff --git a/note/grpc_helloworld.md b/note/grpc_helloworld.md new file mode 100755 index 0000000..54d30c6 --- /dev/null +++ b/note/grpc_helloworld.md @@ -0,0 +1,246 @@ +# grpc + +## 目录 + +* [grpc helloworld例子](#helloworld) + +* [几种rpc的类型](#demo) + +--- + +## helloworld + +目录结构: +``` +├── client.go +├── helloworld +│ ├── build.sh +│ ├── helloworld.pb.go +│ └── helloworld.proto +└── server.go +``` + +proto 定义 +``` +syntax = "proto3"; + +package helloworld; + +service Greeter { + rpc SayHello (Helloreq) returns (Hellorsp) {} +} + +message Helloreq { + string message = 1; +} + +message Hellorsp { + string message = 1; +} +``` + +构建 +``` +protoc -I . --go_out=plugins=grpc:. ./helloworld.proto +``` + +sever.go +``` +package main + +import ( + "context" + "log" + "net" + + pb "./helloworld" + "google.golang.org/grpc" +) + +const ( + port = ":50051" +) + +// server is used to implement helloworld.GreeterServer. +type server struct { + pb.UnimplementedGreeterServer +} + +// SayHello implements helloworld.GreeterServer +func (s *server) SayHello(ctx context.Context, in *pb.Helloreq) (*pb.Hellorsp, error) { + log.Printf("Received: %v", in.GetMessage()) + return &pb.Hellorsp{Message: "Hello " + in.GetMessage()}, nil +} + +func main() { + lis, err := net.Listen("tcp", port) + if err != nil { + log.Fatalf("failed to listen: %v", err) + } + s := grpc.NewServer() + pb.RegisterGreeterServer(s, &server{}) + if err := s.Serve(lis); err != nil { + log.Fatalf("failed to serve: %v", err) + } +} + +``` + +client.go +``` +package main + +import ( + "context" + "log" + "os" + "time" + + pb "./helloworld" + "google.golang.org/grpc" +) + +const ( + address = "localhost:50051" + defaultName = "world" +) + +func main() { + // Set up a connection to the server. + conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock()) + if err != nil { + log.Fatalf("did not connect: %v", err) + } + defer conn.Close() + c := pb.NewGreeterClient(conn) + + // Contact the server and print out its response. + message := defaultName + if len(os.Args) > 1 { + message = os.Args[1] + } + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + r, err := c.SayHello(ctx, &pb.Helloreq{Message: message}) + if err != nil { + log.Fatalf("could not greet: %v", err) + } + log.Printf("Greeting: %s", r.GetMessage()) +} +``` + +``` +go run server.go +go run client.go +``` + +## demo + +参考一个不错的例子: https://zhuanlan.zhihu.com/p/30624616 + +### 1. gRPC 中的三种类型的 RPC 方法。 + +* simple RPC + + 应用于常见的典型的 Request/Response 模型。客户端通过 stub 请求 RPC 的服务端并等待服务端的响应。 + +* Server-side streaming RPC + + 客户端给服务端发送一个请求并获取服务端返回的流,用以读取一连串的服务端响应。stream 关键字在响应类型的前面。// 例子 + + rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){} + + +* Client-side streaming RPC + + 客户端发送的请求 payload 有一连串的的信息,通过流给服务端发送请求。stream 关键字在请求类型前面。 // 例子 + + rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {} + +* Bidirectional streaming RPC + + 服务端和客户端之间都使用 read-write stream 进行通信。stream 关键字在请求类型和响应类型前面。// 例子 + + rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){} + + 双边流的rpcdemo : + + +流式rpc和普通rcp的区别: + + +举个例子: + +比如一对多的请求,比较适合用流式的rcp。比如,请求是一个点的坐标,响应是这个点最近的100个点。那么比较好的方式是,响应使用流式的rpc。 因为这是一个典型的一对多的例子。 + +那么,为什么不能改成1对1的响应,返回的响应是一个数组。为什么不能是这样的设计? + +不这样做的原因是: +1. 这样的相应包可能会很大,如果网络环境不是很好的话,容易超时。 +2. 就算不超时,这样的设计也并不是很优雅。因为,这样意味要,要不是等不到回包,要不然就是收到一个巨大的回包,然后开始“疯狂”的处理。 使用流式的rpc,尽量可能的用流的方式去一点点的平滑处理。 + +对应的demo : > [demo](../example_code/grpc_demo/stream_rpc/server.go) + +### 2. proto的声明 + +对应的demo : > [demo](../example_code/grpc_demo/demo/main.go) + +2.1 proto 如果有多个服务的话,可以在proto文件中,声明在一起: +``` +// The Customer sercie definition +service Customer { + rpc GetCustomers(GetCustomersRequest) returns (GetCustomersResponse) {} + + rpc CreateCustomer (CustomerRequest) returns (CustomerResponse) {} +} +``` + +2.2 proto 声明为数组: +``` +message GetCustomersResponse { + int32 ret = 1; + message keyword { + string word = 1; + } + + // 声明为数组 + repeated keyword wordarray = 3; +} +``` + +在代码里面可以这样写入rsp: +``` +func (s *server) GetCustomers(ctx context.Context, in *pb.GetCustomersRequest) (*pb.GetCustomersResponse, error) { + log.Printf("GetCustomers") + + return &pb.GetCustomersResponse{ + Ret: 1, + Wordarray: []*pb.GetCustomersResponseKeyword{ + &pb.GetCustomersResponseKeyword{ + Word: "hello", + }, + + &pb.GetCustomersResponseKeyword{ + Word: "golang", + }, + + &pb.GetCustomersResponseKeyword{ + Word: "grpc", + }, + }, + }, nil +} +``` + +### + +---- +## 参考 + +* rpc中文文档: + + http://doc.oschina.net/grpc?t=58009 + +* grpc github 提供的example : + + https://github.com/grpc/grpc-go/tree/master/examples/route_guide \ No newline at end of file diff --git a/note/jemalloc.md b/note/jemalloc.md new file mode 100755 index 0000000..e2b5c20 --- /dev/null +++ b/note/jemalloc.md @@ -0,0 +1,10 @@ +## Jemalloc + +## 目录 + +* [简介](#简介) +* [hello-world实例](#hello-world实例) + +--- + +https://www.jianshu.com/p/4f9689ffca2d \ No newline at end of file diff --git a/note/limiter.md b/note/limiter.md new file mode 100755 index 0000000..a529e45 --- /dev/null +++ b/note/limiter.md @@ -0,0 +1,34 @@ +# 限流 + +## 目录 + +* [令牌桶算法](#令牌桶算法) +* [时间漏桶](#时间漏桶) + +--- + +重要的服务需要做流量控制,保证服务正常工作。常见的招数有如下: + +## 令牌桶算法 + +1. 每秒会有 r 个令牌放入桶中,或者说,每过 1/r 秒桶中增加一个令牌 +2. 桶中最多存放 b 个令牌,如果桶满了,新放入的令牌会被丢弃 +3. 当一个 n 字节的数据包到达时,消耗 n 个令牌,然后发送该数据包 +4. 如果桶中可用令牌小于 n,则该数据包将被缓存或丢弃 + +![tu](../pic/rate_limit_1.PNG) + + +## 时间漏桶 + +1. 数据被填充到桶中,并以固定速率注入网络中,而不管数据流的突发性 +2. 如果桶是空的,不做任何事情 +3. 主机在每一个时间片向网络注入一个数据包,因此产生一致的数据流 + +![tu](../pic/rate_limit_2.PNG) + +小结: + +如果是一个服务希望限流的话,可以在服务的上游使用时间漏桶,在服务的接口上使用令牌桶。 + +调用方(使用漏桶)--> (使用令牌桶) 限流服务 diff --git "a/note/linux\345\221\275\344\273\244.md" "b/note/linux\345\221\275\344\273\244.md" old mode 100644 new mode 100755 index dc90865..0d09b18 --- "a/note/linux\345\221\275\344\273\244.md" +++ "b/note/linux\345\221\275\344\273\244.md" @@ -98,6 +98,25 @@ ``` grep -rn "iostream" ``` + + 在服务器上面远程的看日志 + ``` + # 查看xxx.log文件里面的ERROR + grep ERROR xxx.log + + # 查看这个目录下面所有文件的error + grep ERROR * + + # 查看这个目录下面所有文件的error,但是排除掉 tcp error + grep ERROR * | grep -iv "tcp_error" + ``` + +* du 查看占用磁盘的大小 + + ``` + du -h --max-depth=1 + ``` + * sz / rz 命令 sz 从服务器上面下载一个文件 @@ -122,6 +141,11 @@ continue #跳到下一个断点 bt #查看函数栈 + + watch var # 查看某个变量,一个变量值发生变化时,程序会中断 + call test_func(val) # test_func 是用户写的函数,gdb手动去执行这个程序 + p/x var # p/x 把var变量以十六进制表示 + info local # 显示当前函数中的局部变量信息 ``` * attach ``` diff --git "a/note/linux\345\221\275\344\273\244_gcc.md" "b/note/linux\345\221\275\344\273\244_gcc.md" old mode 100644 new mode 100755 diff --git "a/note/linux\345\221\275\344\273\244_linux\346\200\247\350\203\275\345\210\206\346\236\220\345\222\214\344\274\230\345\214\226.md" "b/note/linux\345\221\275\344\273\244_linux\346\200\247\350\203\275\345\210\206\346\236\220\345\222\214\344\274\230\345\214\226.md" old mode 100644 new mode 100755 index 80d290d..6f171f8 --- "a/note/linux\345\221\275\344\273\244_linux\346\200\247\350\203\275\345\210\206\346\236\220\345\222\214\344\274\230\345\214\226.md" +++ "b/note/linux\345\221\275\344\273\244_linux\346\200\247\350\203\275\345\210\206\346\236\220\345\222\214\344\274\230\345\214\226.md" @@ -6,7 +6,8 @@ * 平均负载 - 平均负载 = 活跃进程/ cpu的核心数 , 活跃进程 = runing的进程 + d状态的进程(不可中断的进程) + 平均负载 = 活跃进程数 = runing的进程 + d状态的进程(不可中断的进程) + uptime 命令可以查看 * cpu使用率 @@ -234,4 +235,38 @@ >第五个,不可中断进程和僵尸进程的案例。我们先用 top 观察到了 iowait 升高的问题,并发现了大量的不可中断进程和僵尸进程;接着我们用 dstat 发现是这是由磁盘读导致的,于是又通过 pidstat 找出了相关的进程。但我们用 strace 查看进程系统调用却失败了,最终还是用 perf 分析进程调用链,才发现根源在于磁盘直接 I/O 。 ->最后一个,软中断的案例。我们通过 top 观察到,系统的软中断 CPU 使用率升高;接着查看 /proc/softirqs, 找到了几种变化速率较快的软中断;然后通过 sar 命令,发现是网络小包的问题,最后再用 tcpdump ,找出网络帧的类型和来源,确定是一个 SYN FLOOD 攻击导致的。 \ No newline at end of file +>最后一个,软中断的案例。我们通过 top 观察到,系统的软中断 CPU 使用率升高;接着查看 /proc/softirqs, 找到了几种变化速率较快的软中断;然后通过 sar 命令,发现是网络小包的问题,最后再用 tcpdump ,找出网络帧的类型和来源,确定是一个 SYN FLOOD 攻击导致的。 + + + + +### 小结 + +* 关于cpu: + + 相关的命令:uptime, top/htop, mpstat,perf + +* 关于内存: + + 相关的命令:vmstat,free + +* 关于磁盘: + + 相关的命令:iostat,dstat,du -h + +* 关于网络: + + 相关的命令:sar + +* 定位单个进程的信息: + + 相关的命令:pidstat + +--- +其他: + +[linux性能分析2]( +https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/linux%E5%91%BD%E4%BB%A4_linux%E6%80%A7%E8%83%BD%E5%88%86%E6%9E%90%E5%92%8C%E4%BC%98%E5%8C%962.md) + +[linux性能分析3]( +https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/linux%E5%91%BD%E4%BB%A4_linux%E6%80%A7%E8%83%BD%E5%88%86%E6%9E%90%E5%92%8C%E4%BC%98%E5%8C%963.md) \ No newline at end of file diff --git "a/note/linux\345\221\275\344\273\244_linux\346\200\247\350\203\275\345\210\206\346\236\220\345\222\214\344\274\230\345\214\2262.md" "b/note/linux\345\221\275\344\273\244_linux\346\200\247\350\203\275\345\210\206\346\236\220\345\222\214\344\274\230\345\214\2262.md" old mode 100644 new mode 100755 diff --git "a/note/linux\345\221\275\344\273\244_linux\346\200\247\350\203\275\345\210\206\346\236\220\345\222\214\344\274\230\345\214\2263.md" "b/note/linux\345\221\275\344\273\244_linux\346\200\247\350\203\275\345\210\206\346\236\220\345\222\214\344\274\230\345\214\2263.md" old mode 100644 new mode 100755 index 24234a1..1dee0f6 --- "a/note/linux\345\221\275\344\273\244_linux\346\200\247\350\203\275\345\210\206\346\236\220\345\222\214\344\274\230\345\214\2263.md" +++ "b/note/linux\345\221\275\344\273\244_linux\346\200\247\350\203\275\345\210\206\346\236\220\345\222\214\344\274\230\345\214\2263.md" @@ -1,26 +1,39 @@ -## linux性能优化 +## linux性能优化整理一个例子 ## 目录 -* [内存泄漏](#l内存泄漏) +* [内存泄漏](#内存泄漏) ---- ## 内存泄漏 -### 内存泄漏导致的问题 +### 1. 内存泄漏导致的问题 简单的讲,内存泄漏指的是在堆上面分配的内存没有被free或是delete。 这样导致的问题是,系统的可用内存不断减少,于是导致: * 系统启用swap的空间,然后导致性能变差 * 系统开始回收cache和buffer的空间,然后导致性能变差 -### 如何发现内存泄漏 +### 2. 如何发现内存泄漏 使用memleak工具和valgrind工具可以分析。 - -### 可能出现内存泄漏的场景 - -1. new 和 delete 没有成对出现 -2. 多线程环境中,一个线程分配空间,另外的线程负责delete,但是忘记了。 \ No newline at end of file +简单的思路,比如说: +1. 发现问题,程序oom (out of memory)。 +2. 或者使用free 观察到 可用内存在不停的降低 +3. 使用 memleak 定位 + ``` + $ /usr/share/bcc/tools/memleak -p $(pidof app) -a + Attaching to pid 12512, Ctrl+C to quit. + [03:00:41] Top 10 stacks with outstanding allocations: + addr = 7f8f70863220 size = 8192 + addr = 7f8f70861210 size = 8192 + addr = 7f8f7085b1e0 size = 8192 + addr = 7f8f7085f200 size = 8192 + addr = 7f8f7085d1f0 size = 8192 + 40960 bytes in 5 allocations from stack + fibonacci+0x1f [app] + child+0x4f [app] + start_thread+0xdb [libpthread-2.27.so] + ``` \ No newline at end of file diff --git "a/note/linux\345\221\275\344\273\244_make\346\225\231\347\250\213.md" "b/note/linux\345\221\275\344\273\244_make\346\225\231\347\250\213.md" old mode 100644 new mode 100755 diff --git "a/note/linux\345\221\275\344\273\244_tcpdump.md" "b/note/linux\345\221\275\344\273\244_tcpdump.md" old mode 100644 new mode 100755 diff --git "a/note/linux\345\221\275\344\273\244_\345\270\270\347\224\250.md" "b/note/linux\345\221\275\344\273\244_\345\270\270\347\224\250.md" old mode 100644 new mode 100755 index 42aa7cb..8e0aeff --- "a/note/linux\345\221\275\344\273\244_\345\270\270\347\224\250.md" +++ "b/note/linux\345\221\275\344\273\244_\345\270\270\347\224\250.md" @@ -4,6 +4,7 @@ * [alias](#alias) +--- ## alias diff --git "a/note/linux\345\221\275\344\273\244\346\225\264\347\220\206.md" "b/note/linux\345\221\275\344\273\244\346\225\264\347\220\206.md" new file mode 100755 index 0000000..94eb6a3 --- /dev/null +++ "b/note/linux\345\221\275\344\273\244\346\225\264\347\220\206.md" @@ -0,0 +1,38 @@ +# Linux 乱七八糟的整理 + +## 目录 + +* [常用命令](#常用命令) +* [gcc](#gcc命令) +* [机器配置的命令](#配置命令) +* [shell语法](#shell语法) +* [tcpdump](#tcpdump命令) +* [linux系统编程](#linux系统编程) + +---- + +blog上也整理过一部分: +https://www.jianshu.com/p/f475023f5c8a + +## 常用命令 +> [linux 常用命令](./linux命令_常用.md) + +## gcc命令 +> [linux gcc命令](./linux命令_gcc.md) + +## 配置命令 +> [linux 关于配置的命令](./linux配置.md) + +## shell语法 +> [bash&shell 编程](./bash&shell编程.md) + +## 让shell跑的更快 shell并行 +> [todo](todo) + +## tcpdump命令 +> [linux tcpdump命令](./linux命令_tcpdump.md) + +## linux系统编程 +> [unix环境高级编程](./note/unix环境高级编程.md) + +> [linux网络编程](./note/TCP和网络编程.md) \ No newline at end of file diff --git "a/note/linux\351\205\215\347\275\256.md" "b/note/linux\351\205\215\347\275\256.md" old mode 100644 new mode 100755 index dd588b2..fcf08dc --- "a/note/linux\351\205\215\347\275\256.md" +++ "b/note/linux\351\205\215\347\275\256.md" @@ -1,7 +1,10 @@ ## linux 配置 ## 目录 +* [linux产生core文件](#linux产生core文件) +* [zsh](#zsh) +--- ## linux产生core文件 @@ -32,7 +35,30 @@ core-%e-%p-%t ``` -## linux更换源 +## zsh ``` +# 1. 安装zsh +yum -y install zsh + +# 切换sh +chsh -s /bin/zsh + +# 安装oh-my-zsh +sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" + +# 安装zsh插件 +git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting + +git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions + +# 在vim ~/.zshrc添加插件 +plugins=( + git + zsh-autosuggestions + zsh-syntax-highlighting +) + +# +source ~/.zshrc ``` diff --git a/note/protobuff_with_golang_tutorial.md b/note/protobuff_with_golang_tutorial.md new file mode 100755 index 0000000..04075e6 --- /dev/null +++ b/note/protobuff_with_golang_tutorial.md @@ -0,0 +1,73 @@ +# golang 使用 protobuff hello world 教程 + +## 为什么要protobuff ? + + protobuff的序列化和反序列化编码实现: + https://www.jianshu.com/p/131f0bf218ef + +## hello world + +目录结构: +``` +. +├── person.pb.go +├── person.proto +└── server.go +``` + +person.proto +``` +syntax = "proto3"; + +package main; + +message Person { + string name = 1; + int32 age = 2; +} +``` + +server.go +``` +package main + +import ( + "fmt" + "log" + + proto "github.com/golang/protobuf/proto" +) + +func main() { + fmt.Println("hello proto") + + elliot := &Person{ + Name: "elliot", + Age: 24, + } + + data, err := proto.Marshal(elliot) + if err != nil { + log.Fatal("Marshal error : ", err) + } + fmt.Println(data) + + newElliot := &Person{} + err = proto.Unmarshal(data, newElliot) + if err != nil { + log.Fatal("unmarshal error : ", err) + } + + fmt.Println(newElliot.GetAge()) + fmt.Println(newElliot.GetName()) +} +``` + +构建: +``` +# 根据proto,导出.go 文件 +protoc --go_out=./ *.proto + +# run +go run server.go person.pb.go +``` \ No newline at end of file diff --git "a/note/reactor\346\250\241\345\236\213.md" "b/note/reactor\346\250\241\345\236\213.md" old mode 100644 new mode 100755 index b2f5026..eb62dfe --- "a/note/reactor\346\250\241\345\236\213.md" +++ "b/note/reactor\346\250\241\345\236\213.md" @@ -18,4 +18,7 @@   - 步骤2:得到读就绪事件,执行读数据(现在由Proactor负责)   - 步骤3:将读完成事件分发给用户处理器(Proactor负责)   - 步骤4:处理数据(用户处理器负责)  -``` \ No newline at end of file +``` + +也不知道写的对不对,我觉得类似于学习设计模式这种东西,看一个符合某种模式开发的代码,比学习某一个模式的理论和特点要容易理解一点。 +对于reactor模式,我觉得muduo和redis都可以符合ractor的理念的,尤其是muduo。 \ No newline at end of file diff --git a/note/redis_cluster.md b/note/redis_cluster.md new file mode 100755 index 0000000..52f3a42 --- /dev/null +++ b/note/redis_cluster.md @@ -0,0 +1,209 @@ +# redis 集群搭建 + +## 目录 + +* [redis集群搭建](#redis集群搭建) + +* [redis主从/哨兵/集群的原理分析](#redis主从/哨兵/集群的原理分析) + +--- + +## redis集群搭建 + +1. 安装redis + ``` + sudo apt-get isntall redis-server + ``` + +2. redis启动多个实例 + ``` + # 1. redis 的配置文件 + /etc/redis/redis.conf + + # 2. redis 拷贝一份 + cp /etc/redis/redis.conf ~/redis_conf/. + ``` + +3. 修改为多分的配置文件 + ``` + $ ll + total 360K + -rwxrwxrwx 1 root root 58K Dec 7 12:20 redis_7000.conf + -rwxrwxr-x 1 harleyzhao harleyzhao 58K Dec 7 12:23 redis_7001.conf + -rwxrwxr-x 1 harleyzhao harleyzhao 58K Dec 7 12:23 redis_7002.conf + -rwxrwxr-x 1 harleyzhao harleyzhao 58K Dec 7 12:23 redis_7003.conf + -rwxrwxr-x 1 harleyzhao harleyzhao 58K Dec 7 12:24 redis_7004.conf + -rwxrwxr-x 1 harleyzhao harleyzhao 58K Dec 7 12:24 redis_7005.conf + ``` + +4. 修改配置文件 + ``` + port 7000 + #deamonize yes #后台启动 + cluster-enabled yes + cluster-config-file nodes_7000.conf + cluster-node-timeout 5000 + appendonly yes + ``` + + 提供一个实例配置文件: + + >(redis_7000.conf)[../example_code/redis_conf/redis_7000.conf] + +5. 启动单个redis实例 + ``` + sudo redis-server redis_7001.conf + ... + sudo redis-server redis_7005.conf + + $ ps -ef | grep redis + root 502 1 0 14:28 ? 00:00:00 redis-server 127.0.0.1:7000 [ + root 519 1 0 14:28 ? 00:00:00 redis-server 127.0.0.1:7001 [ + root 536 1 0 14:28 ? 00:00:00 redis-server 127.0.0.1:7002 [ + root 553 1 0 14:28 ? 00:00:00 redis-server 127.0.0.1:7003 [ + root 570 1 0 14:28 ? 00:00:00 redis-server 127.0.0.1:7004 [ + root 587 1 0 14:28 ? 00:00:00 redis-server 127.0.0.1:7005 [ + ``` + +6. 查看redis-cli + ``` + $ redis-cli -c -p 7000 + 127.0.0.1:7000> cluster info + cluster_state:fail + cluster_slots_assigned:0 + cluster_slots_ok:0 + cluster_slots_pfail:0 + cluster_slots_fail:0 + cluster_known_nodes:1 + cluster_size:0 + cluster_current_epoch:0 + cluster_my_epoch:0 + cluster_stats_messages_sent:0 + cluster_stats_messages_received:0 + 127.0.0.1:7000> exit + ``` + +7. redis-trib + ``` + sudo apt-get install ruby-full + + mkdir ~/down && cd ~/down + wget http://rubygems.org/downloads/redis-3.3.0.gem + gem install -l redis-3.3.0.gem + + # 找到redis-trib + sudo find / -name redis-trib.rb + + # redis-trib 管理集群 + $ redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 + >>> Creating cluster + >>> Performing hash slots allocation on 6 nodes... + Using 3 masters: + 127.0.0.1:7000 + 127.0.0.1:7001 + 127.0.0.1:7002 + Adding replica 127.0.0.1:7004 to 127.0.0.1:7000 + Adding replica 127.0.0.1:7005 to 127.0.0.1:7001 + Adding replica 127.0.0.1:7003 to 127.0.0.1:7002 + >>> Trying to optimize slaves allocation for anti-affinity + [WARNING] Some slaves are in the same host as their master + M: d81022ee4427a03e464008c7502e4af521abe845 127.0.0.1:7000 + slots:0-5460 (5461 slots) master + M: 5c7af37df15107e0fa4f66bd14639e3885c6548d 127.0.0.1:7001 + slots:5461-10922 (5462 slots) master + M: 7a5735b92963a2942ae94d98974816a62219cd15 127.0.0.1:7002 + slots:10923-16383 (5461 slots) master + S: 041724d3c83350f8937c754ee9e1bfe9072e39ad 127.0.0.1:7003 + replicates d81022ee4427a03e464008c7502e4af521abe845 + S: 2d0f535e8ea4364c84bf3ae150cb563a784620a2 127.0.0.1:7004 + replicates 5c7af37df15107e0fa4f66bd14639e3885c6548d + S: 69ca8f5a32e8288f71116b8d06787fa77d6daecf 127.0.0.1:7005 + replicates 7a5735b92963a2942ae94d98974816a62219cd15 + Can I set the above configuration? (type 'yes' to accept): yes + >>> Nodes configuration updated + >>> Assign a different config epoch to each node + >>> Sending CLUSTER MEET messages to join the cluster + Waiting for the cluster to join... + >>> Performing Cluster Check (using node 127.0.0.1:7000) + M: d81022ee4427a03e464008c7502e4af521abe845 127.0.0.1:7000 + slots:0-5460 (5461 slots) master + 1 additional replica(s) + M: 7a5735b92963a2942ae94d98974816a62219cd15 127.0.0.1:7002 + slots:10923-16383 (5461 slots) master + 1 additional replica(s) + S: 69ca8f5a32e8288f71116b8d06787fa77d6daecf 127.0.0.1:7005 + slots: (0 slots) slave + replicates 7a5735b92963a2942ae94d98974816a62219cd15 + S: 2d0f535e8ea4364c84bf3ae150cb563a784620a2 127.0.0.1:7004 + slots: (0 slots) slave + replicates 5c7af37df15107e0fa4f66bd14639e3885c6548d + M: 5c7af37df15107e0fa4f66bd14639e3885c6548d 127.0.0.1:7001 + slots:5461-10922 (5462 slots) master + 1 additional replica(s) + S: 041724d3c83350f8937c754ee9e1bfe9072e39ad 127.0.0.1:7003 + slots: (0 slots) slave + replicates d81022ee4427a03e464008c7502e4af521abe845 + [OK] All nodes agree about slots configuration. + >>> Check for open slots... + >>> Check slots coverage... + [OK] All 16384 slots covered. + ``` + +8. 集群搭建成功 + + 如果存入一个值,按照redis cluster哈希槽的算法: CRC16('key')%16384 = 6782。 那么就会把这个key 的存储分配到 B 上了。同样,当我连接 + (A,B,C)任何一个节点想获取'key'这个key时,也会这样的算法,然后内部跳转到B节点上获取数据 + + 设置一个key + ``` + $ redis-cli -c -p 7000 + 127.0.0.1:7000> set test_cluster "hello_7000" + OK + 127.0.0.1:7000> keys * + 1) "test_cluster" + 127.0.0.1:7000> cluster info + cluster_state:ok + cluster_slots_assigned:16384 + cluster_slots_ok:16384 + cluster_slots_pfail:0 + cluster_slots_fail:0 + cluster_known_nodes:6 + cluster_size:3 + cluster_current_epoch:6 + cluster_my_epoch:1 + cluster_stats_messages_ping_sent:4507 + cluster_stats_messages_pong_sent:4427 + cluster_stats_messages_sent:8934 + cluster_stats_messages_ping_received:4422 + cluster_stats_messages_pong_received:4507 + cluster_stats_messages_meet_received:5 + cluster_stats_messages_received:8934 + ``` + + 查找一个key + ``` + $ redis-cli -c -p 7001 + 127.0.0.1:7001> keys* + (error) ERR unknown command 'keys*' + 127.0.0.1:7001> keys * + (empty list or set) + 127.0.0.1:7001> get test_cluster + -> Redirected to slot [5056] located at 127.0.0.1:7000 + "hello_7000" + 127.0.0.1:7000> + ``` + +## redis主从/哨兵/集群的原理分析 + +1. redis-cluster client 的原理 + + http://ralphbupt.github.io/2017/03/08/redis-cluster/ + +## 参考 +0. redis 命令文档: http://redisdoc.com/topic/cluster-tutorial.html + +1. 腾讯云 : https://cloud.tencent.com/developer/article/1432088 + +2. redis-trib.rb 搭建 Redis Cluster : https://www.jianshu.com/p/6b85a004531f + +3. https://www.cnblogs.com/kevingrace/p/7910692.html \ No newline at end of file diff --git a/note/shell.md b/note/shell.md new file mode 100755 index 0000000..fc5fb91 --- /dev/null +++ b/note/shell.md @@ -0,0 +1,256 @@ +## shell脚本 + +## 目录 +* [启动行参数解析](#启动行参数解析) +* [参数调用](#参数调用) +* [执行shell命令](#执行shell命令) +* [文本比较](#文本比较) +* [获得脚本的路径和脚本名称](#获得脚本的路径和脚本名称) +* [从代码仓库里面拉取代码](#从代码仓库里面拉取代码) +* [读取配置ini文件](#读取配置ini文件) +* [打印时间](#打印时间) +* [输出重定向](#输出重定向) +* [脚本debug](#脚本debug) + +--- + +## 启动行参数解析 +使用getopts进行参数解析 +* 如果一个字母后面有一个":",表示该命令行选项后面要跟一个参数。 +* 如optsting写成"b:o:h",表示支持-b、-o、-h选项识别,-b和-o选项后面需要跟一个参数 +* 输出-b 但是又没有指定参数,就走到这里 :) +``` +while getopts "b:o:h" opt_name +do + case $opt_name in + b) echo "-b Option is recognized, argument=$OPTARG" + build + ;; + o) echo "-o Option is recognized, argument=$OPTARG" + update $OPTARG + ;; + h) echo "-h Option is recognized" + package + ;; + :) echo "$OPTARG Option need a argument" # 比如输出-b 但是又没有指定参数,就走到这里 + print_help + ;; + esac +done +``` +--- + +## 参数调用 + +* 普通的函数调用 +``` +function build() +{ + echo "building ..." +} + +build +``` + +* 函数带参数 +``` +function update() +{ + update_mode=$1 + # “STRING” 的长度为零则为真 + if [ -z "${update_mode}" ] + then + echo ">> ERROR: build mode required." + return 1 + fi + + if [[ ${update_mode} != "release" ]] && [[ ${update_mode} != "debug" ]] + then + echo ">> ERROR: invalid build mode: ${update_mode}" + return 1 + fi + + if [ ${update_mode} == "release" ] + then + echo ">>>> relese update mode ..." + fi + + if [ ${update_mode} == "debug" ] + then + echo ">>>> debug update mode ..." + fi + return 0 +} + +update debug +``` + +---- + +## 执行shell命令 + +``` +function build_svr() +{ + core=`grep -c ^processor /proc/cpuinfo` + echo ${core} + + res=`make svr` + if [ $? != 0 ] + then + echo "build svr fail" + fi + echo "build svr successfully" + echo ${res} +} +``` + +---- + +## 文本比较 +``` shell +function update() +{ + update_mode=$1 + # # “STRING” 的长度为零则为真 + if [ -z "${update_mode}" ] + then + echo ">> ERROR: build mode required." + return 1 + fi + + if [[ ${update_mode} != "release" ]] && [[ ${update_mode} != "debug" ]] + then + echo ">> ERROR: invalid build mode: ${update_mode}" + return 1 + fi + + if [ ${update_mode} == "release" ] + then + echo ">>>> relese update mode ..." + fi + + if [ ${update_mode} == "debug" ] + then + echo ">>>> debug update mode ..." + fi + return 0 +} +``` +---- + +## 获得脚本的路径和脚本名称 +``` +SCRIPT_DIR="$(cd `dirname $0`; pwd)" +SCRIPT_NAME=`basename $0` +OUTPUT_PATH=${SCRIPT_DIR}/data + +function show_path() +{ + echo ${SCRIPT_DIR} + echo ${SCRIPT_NAME} + + cd ${OUTPUT_PATH} + echo "hello" > 1.log + + cd ${SCRIPT_DIR} +} + +show_path +``` + +--------------- + +## 从代码仓库里面拉取代码 +``` +function svn_checkout() +{ + if [ ! -d ${OUTPUT_PATH} ] + then + mkdir ${OUTPUT_PATH} + echo "create dir" + fi + echo "dir created" + + rm -rf ${OUTPUT_PATH} + cd ${OUTPUT_PATH} + svn checkout ${SVN_URL} . --username ${USERNAME} --password ${PASSWORD} + cd ${SCRIPT_DIR} +} +``` + + +---------------- + +## 读取配置ini文件 +``` +SCRIPT_DIR="$(cd `dirname $0`; pwd)" +SCRIPT_NAME=`basename $0` +OUTPUT_PATH=${SCRIPT_DIR}/data +SHELL_CFG=${SCRIPT_DIR}/cfg.ini + +function load_cfg() +{ + if [ -f "${SHELL_CFG}" ] + then + source ${SHELL_CFG} + fi + + echo ${OUTPUT_CFG_PATH} +} + +load_cfg + +echo ${OUTPUT_CFG_PATH} +``` + +对应的ini文件(cfg.ini) +``` +OUTPUT_CFG_PATH=./data +``` + +---- +## 打印时间 + +``` +print_date() +{ + echo "========date========" + date +} +``` + +---- +## 输出重定向 + +``` +LOG_FILE="build.log" +ERR_FILE="build.err" +TEE="/usr/bin/tee" + +set_env() +{ + if [ ${SILENT} == 'true' ] + then + exec 1>${LOG_FILE} + exec 2>${ERR_FILE} + else + NPIPE=/tmp/$$.tmp + trap "rm -f ${NPIPE}" EXIT + mknod $NPIPE p + ${TEE} <$NPIPE ${LOG_FILE} & + exec 1>&- # &- 关闭标准输出 # n&- 表示将 n 号输出关闭 + exec 1>$NPIPE + + exec 2>${ERR_FILE} + fi +} +``` + +---- + +## 脚本debug +脚本debug神器,把每一行的脚本执行了什么都打印出来 +``` +#!/bin/sh -x +``` \ No newline at end of file diff --git "a/note/unix\347\216\257\345\242\203\351\253\230\347\272\247\347\274\226\347\250\213.md" "b/note/unix\347\216\257\345\242\203\351\253\230\347\272\247\347\274\226\347\250\213.md" old mode 100644 new mode 100755 diff --git "a/note/vscode\345\206\231c++\346\217\222\344\273\266\344\273\245\345\217\212\351\205\215\347\275\256.md" "b/note/vscode\345\206\231c++\346\217\222\344\273\266\344\273\245\345\217\212\351\205\215\347\275\256.md" old mode 100644 new mode 100755 index 789614b..30d4850 --- "a/note/vscode\345\206\231c++\346\217\222\344\273\266\344\273\245\345\217\212\351\205\215\347\275\256.md" +++ "b/note/vscode\345\206\231c++\346\217\222\344\273\266\344\273\245\345\217\212\351\205\215\347\275\256.md" @@ -1,6 +1,26 @@ # vscode 插件 -使用vscode开发c/c++,推荐的一些插件。 +## vscode 的快捷键 + +* ctrl + g 跳转到对应的行号 + +* F1 启动一些插件或者配置 + +* ctrl + p 打开某个文件 + +* ctrl + alt + k 打bookmark的mark + +* ctrl + k + ctrl + 1 折叠所有的代码 + +* ctrl + t 查找符号 + +* ctrl + ~ 控制台终端显示与隐藏 + +* alt + leftarrow + +按下F1、输入shortcuts 查看所有快捷鍵。 + +## 使用vscode开发c/c++,推荐的一些插件。 * c/c++ diff --git "a/note/\343\200\212\351\207\215\346\236\204\343\200\213\347\232\204\347\254\224\350\256\260.md" "b/note/\343\200\212\351\207\215\346\236\204\343\200\213\347\232\204\347\254\224\350\256\260.md" old mode 100644 new mode 100755 index a05ecf1..694112e --- "a/note/\343\200\212\351\207\215\346\236\204\343\200\213\347\232\204\347\254\224\350\256\260.md" +++ "b/note/\343\200\212\351\207\215\346\236\204\343\200\213\347\232\204\347\254\224\350\256\260.md" @@ -77,6 +77,9 @@ int main() * 少用switch-case (这个我目前还不是很理解) + + 后来,我似乎有点理解了,用switch-case的场景可能是一个函数尝试去做很多事情。如果是这种情况去使用swich-case的话,那就要谨慎一点了。 + --- ## 第四章-构建测试体系 diff --git "a/note/\344\270\200\350\207\264\346\200\247\345\223\210\345\270\214.md" "b/note/\344\270\200\350\207\264\346\200\247\345\223\210\345\270\214.md" new file mode 100755 index 0000000..5f051e3 --- /dev/null +++ "b/note/\344\270\200\350\207\264\346\200\247\345\223\210\345\270\214.md" @@ -0,0 +1,48 @@ +## 一致性哈希 + +为了保序和充分利用缓存,我们通常希望相同请求 key 的请求总是会被分配到同一个服务节点上,以保持请求的一致性,既有了一致性哈希的调度方式。 + +* 割环法 + + 割环法将 N 台服务节点地址哈希成 N 组整型值,该组整型即为该服务节点的所有虚拟节点,将所有虚拟节点打散在一个环上。 + + ![一致性哈希](../pic/%E4%B8%80%E8%87%B4%E6%80%A7%E5%93%88%E5%B8%8C.png) + + 请求分配过程中,对于给定的对象 key 也哈希映射成整型值,在环上搜索大于该值的第一个虚拟节点,虚拟节点对应的实际节点即为该对象需要映射到的服务节点。 + + [代码实现](../example_code/cpp/ConsistentHash.cpp) + +---- + +* Jump Consistent Hash + + 跳跃哈希 jump consistent hash是由谷歌发明的一致性哈希算法,这个算法的牛逼之处在于,相比传统的环形一致性哈希,空间复杂度更低,根本无内存占用,而且算法非常简洁。计算复杂度为O(logn) 空间复杂度为O(1)。 + + ``` + int JumpConsistentHash(unsigned long long key, int num_buckets) + { + long long b = -1, j = 0; + while (j < num_buckets) { + b = j; + key = key * 2862933555777941757ULL + 1; + j = (b + 1) * (double(1LL << 31) / double((key >> 33) + 1)); + } + return b; + } + ``` + +优点: + +1. 当桶的数量从 N − 1 增加至 N时, 有 1 / N 的映射结果发生改变。 + +缺点: + +1. 每个节点的权重相同 + +2. 仅支持在槽位尾端增加或删除节点 + +更多细节: + + https://luyuhuang.tech/2021/06/13/jump-consistent-hash.html + + https://zhuanlan.zhihu.com/p/104124045 \ No newline at end of file diff --git "a/note/\344\271\246\345\215\225_\346\212\200\346\234\257\347\261\273_\345\210\253\344\272\272\346\225\264\347\220\206\347\232\204\344\271\246\345\215\225.md" "b/note/\344\271\246\345\215\225_\346\212\200\346\234\257\347\261\273_\345\210\253\344\272\272\346\225\264\347\220\206\347\232\204\344\271\246\345\215\225.md" old mode 100644 new mode 100755 diff --git "a/note/\344\271\246\345\215\225_\346\212\200\346\234\257\347\261\273_\350\207\252\345\267\261\346\225\264\347\220\206\347\232\204.md" "b/note/\344\271\246\345\215\225_\346\212\200\346\234\257\347\261\273_\350\207\252\345\267\261\346\225\264\347\220\206\347\232\204.md" old mode 100644 new mode 100755 index 934880a..81a2363 --- "a/note/\344\271\246\345\215\225_\346\212\200\346\234\257\347\261\273_\350\207\252\345\267\261\346\225\264\347\220\206\347\232\204.md" +++ "b/note/\344\271\246\345\215\225_\346\212\200\346\234\257\347\261\273_\350\207\252\345\267\261\346\225\264\347\220\206\347\232\204.md" @@ -1,6 +1,6 @@ # 技术类书单 -## cpp 类 +### cpp 类 * 《c++ primer》 @@ -21,7 +21,7 @@ * 《程序员的自我修养》 -## linux +### linux * 《unix 环境高级编程》 @@ -32,13 +32,13 @@ * 《性能之巅》 -## 基础类 +### 基础类 * 《深入理解计算机系统》 * 《编码:隐匿在计算机软硬件背后的语言》 -## web +### web * 《大型网站技术架构核心原理与案例分析》 @@ -46,7 +46,7 @@ * 《白帽子讲web安全》 -## other +### other * 《改变未来的九大算法》 @@ -61,17 +61,17 @@ https://github.com/lizhenghn123/StudyBooks -## 刷题找工作类 +### 刷题找工作类 * 《剑指offer》 -## 其他教程 +### 其他教程 - [学习python,git等都是看的是廖雪峰的教程](https://www.liaoxuefeng.com/) -## 腾讯后台开发推荐书单 +### 腾讯后台开发推荐书单 这是我在腾讯游戏实习的时候,部门推荐的书单。 @@ -95,7 +95,7 @@ 4. 设计 - * 敏捷软件开发(BOB大叔) + * 敏捷软件开发 * 重构-改善既有代码的设计 * 设计模式(GOF) * head first设计模式 diff --git "a/note/\344\271\246\345\215\225_\351\235\236\346\212\200\346\234\257\347\261\273_\350\207\252\345\267\261\346\225\264\347\220\206\347\232\204.md" "b/note/\344\271\246\345\215\225_\351\235\236\346\212\200\346\234\257\347\261\273_\350\207\252\345\267\261\346\225\264\347\220\206\347\232\204.md" deleted file mode 100644 index e4ebcd8..0000000 --- "a/note/\344\271\246\345\215\225_\351\235\236\346\212\200\346\234\257\347\261\273_\350\207\252\345\267\261\346\225\264\347\220\206\347\232\204.md" +++ /dev/null @@ -1,13 +0,0 @@ -# 非技术类的书单 - -* 《薛兆丰经济学讲义》 - -* 《乔布斯传》 - -* 《三体》 - -* 《数学之美》 《态度》 《见识》 - - 我个人很喜欢看吴军的书,很喜欢他表达和分析问题的风格 - - diff --git "a/note/\344\271\246\345\215\225\345\222\214\345\215\232\345\256\242.md" "b/note/\344\271\246\345\215\225\345\222\214\345\215\232\345\256\242.md" new file mode 100755 index 0000000..72f2f70 --- /dev/null +++ "b/note/\344\271\246\345\215\225\345\222\214\345\215\232\345\256\242.md" @@ -0,0 +1,37 @@ +# 书单和博客 + +### 书单 + +* [技术类的书单](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/%E4%B9%A6%E5%8D%95_%E6%8A%80%E6%9C%AF%E7%B1%BB_%E8%87%AA%E5%B7%B1%E6%95%B4%E7%90%86%E7%9A%84.md) + +* [江湖上面有人整理出来的技术类书单](https://github.com/zhaozhengcoder/CoderNoteBook/blob/master/note/%E4%B9%A6%E5%8D%95_%E6%8A%80%E6%9C%AF%E7%B1%BB_%E5%88%AB%E4%BA%BA%E6%95%B4%E7%90%86%E7%9A%84%E4%B9%A6%E5%8D%95.md) + +--- + +### 博客BLOG + +一些有意思的BLOG + +* [左耳朵耗子的博客](https://coolshell.cn/) + +* [张洋的blog](http://blog.codinglabs.org/pages/about-me.html) + +* [果冻想](https://www.jellythink.com/) + +* [lifeofzjs](http://lifeofzjs.com/) + +* [tiankonguse](http://github.tiankonguse.com/) + +* [关于机器学习的算法的blog](liuyaolei.com/archives/) + +* [阮一峰](http://www.ruanyifeng.com/blog/archives.html) + +* [selfboot](https://selfboot.cn/) + +* [cizixs](https://cizixs.com/) + +* [c++的一个blog — watson2016](https://blog.csdn.net/watson2016/article/list/6) + +* [c++的一个blog — senlinzhan](http://senlinzhan.github.io/) + +* [c++做游戏开发的一个人](https://me.csdn.net/wallwind) \ No newline at end of file diff --git "a/note/\345\207\275\346\225\260\350\260\203\347\224\250\350\277\207\347\250\213.md" "b/note/\345\207\275\346\225\260\350\260\203\347\224\250\350\277\207\347\250\213.md" new file mode 100755 index 0000000..284967a --- /dev/null +++ "b/note/\345\207\275\346\225\260\350\260\203\347\224\250\350\277\207\347\250\213.md" @@ -0,0 +1,300 @@ +# 函数的调用过程 + +## 目录 + +* [函数的调用过程统](#函数的调用过程) +* [函数栈切换](#函数栈切换) +* [协程的基本原理](#协程的基本原理) +* [热更新的基本原理](#热更新的基本原理) +--- + +## 函数的调用过程 + +函数的调用过程是包含了几个步骤,分别是:参数入栈、函数跳转、保护现场、回复现场。x86的计算机体系实现的方式,利用的是栈的思想。 +里面有几个关键的变量,就是ebp(栈底指针),esp(栈顶指针)。ebp 到 esp 之间的空间,就是当前函数的上下文(对应栈帧)。 + +* 当函数调用的时候,**对应的操作就是压栈,建立新增栈帧;** + +* 当函数调用结束的时候,**对应的操作就是出栈,回复到上一级函数的栈帧;** + +--- + +介绍之前,需要注意一下,函数的栈空间是向下增长的(即低地址的方法),所以,很多汇编对应的代码都是减法。不要搞混了。 +``` +int main() +{ + int val1 = 100; + int val2 = 200; + int val3 = 300; + + printf("val1 addr %p\n", &val1); + printf("val2 addr %p\n", &val2); + printf("val3 addr %p\n", &val3); + return 0; +} + +// 地址在减少 +val1 addr 0x7fffffffe24c +val2 addr 0x7fffffffe248 +val3 addr 0x7fffffffe244 +``` + +--- +这里有一张很经典的图,看明白这张图就基本上不需要介绍了。 +* 函数的调用栈示意图: +![tu](../pic/函数调用1.png) + + +看一下对应的汇编代码的实现: +* 函数调用对应的汇编代码: +![tu](../pic/函数调用2.png) + + 通过gdb disas/rs + 函数名称 可以查看对应的汇编代码。查看汇编发现: + + 1. 在main调用add函数的时候,这里的参数是通过寄存器在传递的 + 2. 每进入一个新的函数之后,都是 push %rbp,mov %rsp,%rbp。开辟新的rbp 和 rsp + 3. 返回的返回值存放在eax中 + 4. 函数调用结束的时候,会执行retq的执行 + 它的作用是从栈里面弹出上一级函数的ebp,然后写到自己的ebp里面。然后再弹出返回地址,修改eip指针(可能还需要回复一些寄存器)。这样就回到了上一级函数(上一级的函数现场被回复了) + + 获得使用objdump可以查看汇编代码: + ``` + objdump -d ./a.out + ``` + +关于函数调用相关的汇编,看过一篇写的[很好的文章](https://mp.weixin.qq.com/s?__biz=MzI3MDQyMDE2OQ==&mid=2247484775&idx=1&sn=76334db946af962098a8f6812e15b30c&chksm=ead014c1dda79dd78db370b370678c0c33ebfe61b5da7b3c9be4ea6117e8d2ba8c6dcf9fac49&token=839941167&lang=zh_CN#rd) + +dump了一份pdf版本:[c++数调用简单的汇编介绍](../pic/函数调用简单的汇编介绍.pdf) + +--- +关于c++和汇编的一些其他东西: + +* c调用汇编的代码 + + 在c语言中,使用asm可以调用汇编: + ``` + void function(); + + void test() + { + int val = 10; + printf("val %d\n", val); + + // 比如 我们知道了函数内栈变量的空间布局规则 + // 可以利用汇编去修改某个变量的值 + // set val = 11 + asm("movl $0xb, -0x4(%rbp)"); + printf("val %d\n", val); + + // 修改地址 + long addr = function; + asm("movl $0x401156, 0x18(%rbp)"); + } + ``` + + 完成代码: + [example_code](../example_code/function/test_asm.c) + +* gdb 查看寄存器的值 + + ``` + (gdb) i register + rax 0x401197 4198807 + rbx 0x0 0 + rcx 0x7ffff7dce738 140737351837496 + rdx 0x7fffffffe398 140737488348056 + rsi 0x7fffffffe388 140737488348040 + rdi 0x1 1 + rbp 0x7fffffffe2a0 0x7fffffffe2a0 + rsp 0x7fffffffdaf0 0x7fffffffdaf0 + r8 0x7ffff7dcfce0 140737351843040 + r9 0x7ffff7dcfce0 140737351843040 + r10 0xffffffff 4294967295 + + (gdb) i registers eax + eax 0xf7811010 -142536688 + ``` + +---- + +## 函数栈切换 + +搞明白函数的调用过程,其实也就明白了函数的切换过程。那就可以利用这个机制实现函数的跳转。 + +1. 思路1:堆栈溢出攻击 + + 覆盖返回地址,实现函数跳转。 + ``` + #include + #include + #include + #include + + void fun() + { + while(1) + { + printf("Hello, I'm fun!\n"); + sleep(1); + } + } + + int foo2() + { + long a[5] = { 0 }; + + // 溢出攻击 + a[9] = fun; // 覆盖返回地址 // 为什么是a[9] 尝试不同的移动偏移去覆盖rbp的上一条地址 (不同的机器可能不太一样) + } + + int main() + { + printf("main \n"); + foo2(); + return 0; + } + ``` + + +2. 思路2:覆盖函数的地址的汇编代码,实现函数跳转 + + ``` + void fun() + { + while(1) + { + printf("Hello, I'm fun!\n"); + sleep(1); + } + } + + int foo() + { + int a[5] = { 0 }; + + // 溢出攻击 + asm("mov $0x401136,%eax"); // 0x401136 是fun的入口地址 + asm("mov %rax,0x18(%rbp)"); + } + ``` + + fun的地址可以通过查看汇编代码找到: + ![](../pic/函数调用3.png) + + 执行结果: + ![](../pic/函数调用4.png) + +3. 思路3:覆盖函数的地址首部,插入跳转到其他函数的汇编代码,实现函数跳转 + + 如果想要从函数a调到函数b,可以把函数b的栈copy覆盖过去。 + + 这真是一个有意思的方案,利用这个思路可以做很多事情。 + + ``` + // 希望跳转到的函数 + (gdb) disas/rs MyFunctionNew + Dump of assembler code for function MyFunctionNew: + 0x0000000000401334 <+0>: 55 push %rbp + 0x0000000000401335 <+1>: 48 89 e5 mov %rsp,%rbp + 0x0000000000401338 <+4>: 89 7d ec mov %edi,-0x14(%rbp) + 0x000000000040133b <+7>: 89 75 e8 mov %esi,-0x18(%rbp) + 0x000000000040133e <+10>: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%rbp) + 0x0000000000401345 <+17>: 8b 45 fc mov -0x4(%rbp),%eax + 0x0000000000401348 <+20>: 5d pop %rbp + 0x0000000000401349 <+21>: c3 retq + End of assembler dump. + ``` + + + ``` + // 希望跳转到的函数的对应的汇编代码 + char new_func[] = + { + 0x55, + 0x48, 0x89, 0xe5, + 0x89, 0x7d, 0xec, + 0x89, 0x75, 0xe8, + + 0xc7, 0x45, 0xfc, 0x0a, 0x00, 0x00, 0x00, + + 0xc7, 0x45, 0xf8, 0x01, 0x00, 0x00, 0x00, + + 0x8b, 0x45, 0xfc, + 0x5d, + 0xc3 + }; + ``` + + ``` + // 用新的代码去覆盖旧的函数的代码 + int len = sizeof(new_func); + memcpy((void*)MyFunction, (void*)new_func, len); + ``` + + 完成代码: + + [example_code](../example_code/function/test.c) + +4. set/jump的方案 + + ``` + jmp_buf env; + + int my_func(int a, int b) + { + if (b == 0) { + printf("do not allow division by 0\n"); + longjmp(env, 1); + } + return a / b; + } + + int main(int argc, char const *argv[]) + { + int res = setjmp(env); + if (res == 0) { + printf("return from setjmp\n"); + my_func(10, 0); + } else { + printf("return from longjmp: %d\n", res); + } + return 0; + } + ``` + + 完成代码: + + [example_code](../example_code/function/test_jmp.c) + +---- + +## 协程的基本原理 + +协程的本质就是函数上下文的切换,明白了函数调用和切换的过程,再看几种cpp常见的协程实现方案,就会瞬间清晰很多。 + +* 大概协程实现的几种原理: + 1. 利用libc中的ucontext系统调用实现 (比如云风实现的协程库) + 2. 使用汇编来切换上下文 (比如libco协程库) + 3. 利用C语言语法switch-case的奇淫技巧来实现 + 4. 利用setjmp 和 longjmp实现的协程 + +* 从实现的方案角度,可以分为: + 1. 共享栈协程 + 2. 非共享栈协程 + + **非共享栈** :是每个协程单独开辟一块固定大小的空间,用于存放自己的栈数据。这样带来的好处是,每次切换协程的时候,不需要对栈进行拷贝(只需要切换rbp 和 rsp,让它指向需要要被调度执行的协程的栈空间即可)。非共享栈被认为缺点的是,占用内存会更多。在实际中,栈的内存使用其实不多,如果每个栈128K内存,1w个协程才需要1G多的内存。 + + **共享栈协程** :是每个协程在要被切出的时候,开辟一块内存空间,然后把栈(rsp 到 rbp 的长度,在云风实现的库中利用dummy的变量在计算长度)拷贝到申请的内存上。这样的好处是内存的占用会合理(不会分配过多)。缺点是:协程暂停时,需要把用到的栈内存暂时保存起来,等要运行,再把保存的栈内存拷贝回协程执行的栈(有申请,拷贝和切换的成本)。 + +----- + +* ucontext协程库 + 跑题太远了,新开一篇笔记整理: + > [云风的协程库源码分析] https://www.jianshu.com/p/c4de909fee75 + +* libco 上下文切换的思路 + > libco --> colin的例子 (todo) + +## 热更新的基本原理 + +> [利用函数跳转实现程序热更新](https://www.jianshu.com/p/b7c7102119fa) diff --git "a/note/\345\210\206\345\270\203\345\274\217id\347\224\237\346\210\220.md" "b/note/\345\210\206\345\270\203\345\274\217id\347\224\237\346\210\220.md" new file mode 100755 index 0000000..e8f36cb --- /dev/null +++ "b/note/\345\210\206\345\270\203\345\274\217id\347\224\237\346\210\220.md" @@ -0,0 +1,126 @@ +# 分布式id生成 + + +## 目录 +* [集中式的唯一id生成](#集中式的唯一id生成) +* [分布式的唯一id生成](#分布式的唯一id生成) + +--- + +在很多场景中,都有需要生成唯一id的需求。这个问题抽象出来,**就是在分布式的环境下,如何生成不重复的id?**。 + +常见的几种方案,大概是两个思路去做。分别是集中式的id分配(通过一个唯一的中心节点生成id,其他进程向中心节点申请id)和分布式的id分配(进程本地生成 无需网络调用)思路。 + +--- + +## 集中式的唯一id生成 + +提供一个中心节点,其他的业务进程需要使用id的时候,想中心节点去申请。中心节点是唯一的,可以保证分配出来的id是不重复的。 + +具体实现的细节: + +1. 不同的业务可以注册不同的号码段,中心节点根据提前注册业务的号码段给他们分配出不同的id。 + + ``` + +------+-------------------+ + | type | type_seq_used_max | + +------+-------------------+ + + db中保存两个字段,一个是类型id,一个是当前类型已使用的最大id。这样重启之后,可以保存上次分配最大值。 + ``` + + 具体的字段格式可以是: + ``` + 唯一id (64位长度) + type id (8位),其他固定信息(比如区服信息)(6位),seq(50位) + ``` + + seq字段在db中记录了已经使用的最大值,每次分配的时候自增(保证不重复)。 + + 服务重启的时候,已经分配的最大值存盘。保证下次重启的时候,继续在最大值只上分配(保存重启不会重复)。 + + seq的长度是50位,2的50次方,是一个非常非常大的数,足够用非常久了。 + +2. 申请的时候,可以采用一个双buff的思想,比如业务a要申请,可以一次申请1000个可用,1000个备用。业务a拿到之后,在自己的进程上慢慢使用。当1000个用完的时候,切换到备用上。同时,再次向中心节点申请。 + + 这样的优点可以保证业务使用的时候,可以直接从当前进程的缓存里拿id,不需要异步等待。 + + 这种方案还有一个额外的好处,发号的策略不依赖于时间。对于调服务器时间这种操作,可以完全不受影响。 + +* 其他集中式的唯一id生成的方案 + + 这里还有一些其他的利用mysql主键自增,redis inc 命令维护,zk等组件实现唯一id生成的思路或方案, + + 本质上也是利用**一个唯一的中心节点去发号**,不同的方案各有利弊,也是针对不同的业务场景提供的解决办法。 + +--- + +## 分布式的唯一id生成 + +* uuid的思路 + + UUID(Universally Unique Identifier,即通用唯一标识码),uuid的格式是32位的字符串,利用mac地址和时间组成的唯一id。 + + 优点: + + 1. uuid 的思路利用的mac地址和时间来作为不重复的依据,它的优点是性能很好 + + 2. id可以本地生成,没有网络消耗。 + + 缺点: + + 1. uuid太长,是字符串的格式,存储成本高 + + 2. 暴露机器的mac地址 + + +* 雪花like算法的思路 + + 这种方案的思路是,每个进程都在自己的本地去分配id,不需要异步和通过网络去申请。不过呢,为了避免进程a和进程b生成了相同的id,要划分不同的号码区间。 + + 比如,类似于雪花算法的id生成思路,将一个64位的bit段,分为不同的区间。(时间 + 机器id + 序号)类似于这样。保证在某一个时间下,可以生成的id都是唯一的。 + + 仔细想了一下,雪花算法这几个字段的排列方式,还是很有道理的。 + + ``` + unsigned long long make_id() + { + u32 time = get_time(); + u32 machine_id = get_machine_id(); + + static u32 seq = 0; + u64 id = time < xxx | machine_id < xxxx | seq++; + return id; + } + ``` + +* 为什么时间作为最高位? + + 因为用时间作为做高位,保证的id是单调增长的。如果id是用在做数据库主键的,可以保证主键的写入是一直追加到索引的后面的。 + +* 为什么seq最为最低位? + + seq要放在最后,而且推荐写为static,这样会不停的加,id分布是均匀的。如果id用来hash = (id % 10),那可以保证hash后的结果是分布均匀的。 + 当时,如果用时间作为最后一位 或机器id作为最后一位,那么就不一定了。 + + +* 这里有可能出现一个**时钟回拨**的问题: + + 时钟回拨指的是: + 时间回拨问题是指系统在运行过程中,可能由于网络时间校准或者人工设置,导致系统时间主动或被动地跳回到过去的某个时间。 + + 美团的一个分布式id的文章提供了一个解决办法,增加了一个时钟id的字段。当现在的时间小于等于上次申请的时间的时候,时钟id++。不过这个只能解决系统没有重启的情况。(如果遇到系统重启 + 时间回拨 那问题就这个方式就没有办法了) + + 如果这里问题要解决的话,好像也是可以的。 + + 刚才提及的雪花like算法,都是从进程本地获得的;如果进程重启后,出现时间回拨(或者测试的时候,qa修改进程的时间,然后又改回去)。可以单独搞一个分配id的进程或服务器,通过网络去获得。这样只需要保证这个单独的服务时间重启后不会拨就好。 + + 这样还有一个好处,可以解决 雪花算法中机器id的字段。但是呢,问题是中间加入了通过网络去申请的异步过程。要看业务特点什么去权衡了。 + +---- + +## 参考: + +https://tech.meituan.com/2017/04/21/mt-leaf.html + +https://blog.hackerpie.com/posts/algorithms/snowflake/multiple-clocks-snowflake/ \ No newline at end of file diff --git "a/note/\345\210\206\345\270\203\345\274\217\351\224\201.md" "b/note/\345\210\206\345\270\203\345\274\217\351\224\201.md" new file mode 100755 index 0000000..0b9bf46 --- /dev/null +++ "b/note/\345\210\206\345\270\203\345\274\217\351\224\201.md" @@ -0,0 +1,132 @@ +# 分布式锁 + +## 目录 +* [基于数据库实现](#基于数据库实现) +* [使用zk作为分布式锁](#使用zk作为分布式锁) +* [使用redis作为分布式锁](#使用redis作为分布式锁) + +--- + +分布式锁是解决协调分布式系统之间,同步访问共享资源的一种方式。 + +举个例子,火车票保证不超买? + +这类问题,有很多种解决的办法。大概的思路有三种。 + +* 第一种是基于数据库实现 + +* 第二种是基于缓存系统去实现 (典型代表是使用Redis实现的锁服务) + +* 第三种是基于分布式一致性算法实现 (典型代表为Zookeeper) + +* 提供个其他思路,解决需要加锁的问题,也许更好的方式是绕过加锁的环节。比如说两个请求要同时访问一个资源,如果可以把他们**串行化**(比如放到同一个队列来处理)。当然,只是提供一个思路,这个要看业务具体的特点。 + +----- + +## 1. 基于数据库实现 + +基于数据库的实现,大概也是两个思路。第一种是悲观锁(select xxx for update),第二种是乐观锁。 + +1. 悲观锁 + + 通过数据库行锁 select for update 锁住这行数据,然后将查询和插入的 SQL 在同一个事务中提交。 + + ``` + select id from order where order_id = xxx for update + ``` + + 不过,这种方案的问题是: + + * 基于 MySQL 行锁的方式会出现交叉死锁,比如事务 1 和事务 2 分别取得了记录 1 和记录 2 的排它锁,然后事务 1 又要取得记录 2 的排它锁,事务 2 也要获取记录 1 的排它锁,那这两个事务就会因为相互锁等待,产生死锁。 + + * 当然,你可以通过“超时控制”解决交叉死锁的问题,但在高并发情况下,出现的大部分请求都会排队等待,所以“基于关系型数据库实现分布式锁”的方式在性能上存在缺陷。 + + +2. 乐观锁 + + 带个版本号 (具体细节先不展开了) + +---- + +## 2. 使用zk作为分布式锁 + +1. 在锁的目录下面,创建临时有序节点 + +2. 每个节点需要申请锁的时候,在这个目录下面创建临时节点 + +3. 在锁的目录下面,锁的序号最小的一个节点认为拿到了锁 + +4. 后面的节点 依次watch前面的节点,当前面的节点变更的时候,后面的节点被唤醒,进行step3的判断 + +举个例子: + +1) 比如某进程获得到的节点序号为 /zk_lock/003,然后所有的节点列表为[/zk_lock/001,/zk_lock/002,/zk_lock/003],则对 /zk_lock/002 这个节点添加一个事件监听器。 + +2) 如果锁释放了,会唤醒下一个序号的节点,判断是否自己的节点序号是最小。 + +3) 比如 /zk_lock/001 释放了,/lock/002 监听到时间,此时节点集合为[/zk_lock/002,/zk_lock/003],则 /lock/002 为最小序号节点,获取到锁。 + +优点: +1. 临时有序的zk节点,可以保证当进程挂掉的时候,锁还是可以被释放的。 + +2. 每个节点watch前面的节点,相当于一个订阅回调的机制,这样业务层使用起来更舒服。 + +----- + +## 3. 使用redis作为分布式锁 + + +在redis上面设置一个key作为锁 + +1. 使用set key value 作为锁的标记位,然后expire key 10s 设置key的有效期 + + 问题:这个方案的问题是,是通过两条语句执行的,不能保证原子性. + +2. `SET key value NX PX milliseconds` + + ``` + key: 资源的key,标识一种资源。 + + value: 此值必须在所有进程和所有获取锁的请求中都是唯一的。 + + NX: 该命令仅在key不存在时才设置。 + + PX milliseconds: 过期时间,单位为毫秒。 + ``` + + 这个方案是通过一条命令设置key的value,以及key的有效期,这样可以保证是一个原子的操作。 + + 释放 : + ``` + if redis.call("get",KEYS[1]) == ARGV[1] then + return redis.call("del",KEYS[1]) + else + return 0 + end + ``` + + 这种方案解决不了的问题是: + + 如果在一个redis的集群中,当在master的节点完成了这个操作,但是由于redis是异步复制的,slave的节点不指定会马上收到通知的数据。如果master立刻宕机,会导致上锁失败。 + +3. redlock 方案 + + 对于在集群中的枷锁redis给的方案是redlock,它的基本思路就是为锁准备多个独立的节点,在锁过期时间内只要超过半数获取到锁,就算成功,避免redis主从切换的时候,数据丢失。 + +----- + +## 总结 : + +总结一下,分布式锁是解决多个进程同时访问临界资源的常用方法,在分布式系统中非常普遍,常见的实现方式是基于数据库,基于 Redis。 + +- redis方案注重性能,但是不能保证安全性。 + +- redlock方案,资源成本太高,不能公用redis cluster集群,还不能绝对保证安全性,有点鸡肋。 + +- zookeeper方案,比较简单,没有时钟跳跃的问题。可靠性要比redis的高,但是性能比redis的要差 + +--- + +参考: + +https://www.cnblogs.com/yunlongn/p/14609443.html diff --git "a/note/\345\267\245\345\205\267\346\240\210.md" "b/note/\345\267\245\345\205\267\346\240\210.md" old mode 100644 new mode 100755 diff --git "a/note/\345\274\200\346\272\220\351\241\271\347\233\256.md" "b/note/\345\274\200\346\272\220\351\241\271\347\233\256.md" old mode 100644 new mode 100755 diff --git "a/note/\346\224\266\351\233\206\350\247\201\345\210\260\350\277\207\347\232\204\344\270\200\344\272\233\345\267\245\345\205\267\345\222\214\350\275\256\345\255\220.md" "b/note/\346\224\266\351\233\206\350\247\201\345\210\260\350\277\207\347\232\204\344\270\200\344\272\233\345\267\245\345\205\267\345\222\214\350\275\256\345\255\220.md" new file mode 100755 index 0000000..5f971b6 --- /dev/null +++ "b/note/\346\224\266\351\233\206\350\247\201\345\210\260\350\277\207\347\232\204\344\270\200\344\272\233\345\267\245\345\205\267\345\222\214\350\275\256\345\255\220.md" @@ -0,0 +1,11 @@ +# 收集见到过的一些小工具,代码片段或轮子 + +## 目录 + +* STL中的string没有默认的split方法 [提供一些相关的字符串split实现](https://mp.weixin.qq.com/s/LdiMuhY0IDFCP8V1dPxg-g) + +* [cpp线程池](https://mp.weixin.qq.com/s/uz85-w9ZfwRP0ZZCI7jOzQ) + +* [c98实现的线程池](../example_code/thread_pool/README.md) + +* [cpp对象池](https://mp.weixin.qq.com/s/bWe8dLs-sgoCI_5sQbeOaw) \ No newline at end of file diff --git "a/note/\346\225\260\346\215\256\345\272\223-\347\264\242\345\274\225.md" "b/note/\346\225\260\346\215\256\345\272\223-\347\264\242\345\274\225.md" old mode 100644 new mode 100755 index 944281f..cf82190 --- "a/note/\346\225\260\346\215\256\345\272\223-\347\264\242\345\274\225.md" +++ "b/note/\346\225\260\346\215\256\345\272\223-\347\264\242\345\274\225.md" @@ -31,6 +31,19 @@ 上述三种索引都是针对列的值发挥作用,但全文索引,可以针对值中的某个单词,比如一篇文章中的某个词,然而并没有什么卵用,因为只有myisam以及英文支持,并且效率让人不敢恭维,但是可以用coreseek和xunsearch等第三方应用来完成这个需求。 +### innodb的索引和myisam索引结构 + +* myisam索引 +![tu](../pic/myisam.png) + +* innodb索引 +![tu](../pic/innodb.png) + + +* innodb辅助索引结构 +![tu](../pic/innodb2.png) + + ### 创建索引的原则 1. 维度高的列创建索引 @@ -45,10 +58,137 @@ 因为加入索引之后,除了有额外的磁盘开销之外,**另外,每一次插入数据都会导致索引被修改。** +### 索引哪些情况会失效 + +1. where条件中包含or + + ``` + select * from table where a = "a" or b="b" + + 比如字段a是索引列,但是字段b并不是索引列,那么这样的写法无法命中索引 + ``` + +2. where条件中包含函数,或者where的左侧包含计算 + + ``` + select * from table where data(a) = "xxxx" -- 不会命中索引 + + select * from table where a + 10 = 100; -- 不会命中索引 + + select * from table where a = 100 - 10; -- 命中索引 + + 这个原理也很简单,如果where的条件包含函数的话,引擎在查询的时候,需要把函数和计算应用到所有的索引节点上。 + ``` + +3. 使用通配符 + + ``` + select * from table where a = "hello%" -- 命中索引 + + select * from table where a = "%hello" -- 无法命中索引 + ``` + +4. mysql判断认为全表扫描要比走索引快,会出现不走索引的情况 + ``` + select * from table where a in (xx,xxx,xxxx); + + 很多索引的教程都建议不要使用in,使用in的话,会可能无法命中索引。如果in的条件中返回的字段的区分度不大,比如有100w条记录,49w男性,49w女性,2w待定。那么 select * from table where sex in ("男","女"),这种情况全表扫描还要快于利用索引。 + ``` + +### 索引的一些潜规则 + +* 覆盖索引 +* 回表 + +### b+树索引的优点 + +* b+树和哈希索引的对比 + +这两种索引的区别的本质就是哈希表和b+树两种数据结构的区别: +哈希可以通过hash(key)快速命中要查找的记录,但是哈希的缺点是不支持范围查询。 + +* b+树和其他b树,二叉树的对比 + +1. b+树的所有叶子节点是连在一起的,对于常见的遍历和扫描操作很方便。 + +2. b+树是多叉树,所有的叶子节点到根节点的高度是一致的,查询的性能均衡,不会出现像二叉树一样,退化为一个链表。 + +3. b+树的非叶子节点不包含数据,在io的时候,可以降低io的次数。 + ### 关于联合索引 联合索引匹配的原则是最左匹配原则。 +当我们需要对多个字段查询的时候,可能会用到联合索引。联合索引的原理是一个复合key的b+树。 + +![tu](../pic/数据库索引_1.jpg) + +比如说(a,b)字段进行建立联合索引 + +这个树的的特点是: +1. 从全局上面看,a是有序的 +2. 从全局上面看,b是无序的 +3. 如果指定了a,那么b是有序的 + +搞明白了这个原理,分析sql是否可以命中索引就比较简单了。 + +``` +select * from table where a = 1; 命中 + +select * from table where a = 1 and b = 1; 命中 + +select * from table where b = 1; 不会命中,因为全局上b是无序的,需要全部扫描。 + +select * from table where b = 1 and a = 1; 命令,mysql会优化一把,改为 a=1 and b= 1; 交换一下顺序。 +``` + +在看几个例子: +``` +select * from table where a = 1 and b > 1; 命中 + +select * from table where a > 1 and b = 1; 只有a命中,b命不中。 + +因为只有指定a的值的时候,b不是有序的。这里a只是一个范围,所以,要找到b,还是需要扫描这张表的。 +``` + +问答环节: +``` +SELECT * FROM table WHERE a = 1 and b = 2 and c = 3; 如何加索引? + +(a,b,c) 和 (b,a,c) (c,b,a) 或其他顺序都可以; + +select * from table where a > 1 and b = 1 and c > 2; 如何加索引? + +(b,a) 和 (b,c) 都可以; + +select * from table where +``` + +参考: + +https://zhuanlan.zhihu.com/p/115778804 + +https://cloud.tencent.com/developer/article/1449114 + + +### like查询 使用索引 + +下面两条语句,是否可以会命中索引? +``` +select * from table where value like "abc%"; + +select * from table where value like "%abc"; +``` + +如果%写到最前面,那么就不会命中索引。这个一定会扫描所有的数据;如果%写到后面,会命中索引。区别在于%写的越后,扫描的数据越少。 + +换一个思路,也可以优化第一种情况的case。反转一下需要查询的字符串,这个就会命中。 +``` +where reverse(字段) like reverse('%abc') + +比如原字段是abcd,取反存储为dcba,查询%abc改成查cba%。 +``` + ### 写尽量可以命中索引的sql语句 @@ -78,6 +218,8 @@ CHAR 把这个大小视为值的大小,不长度不足的情况下就用空格补足。而 VARCHAR 类型把它视为最大值并且只使用存储字符串实际需要的长度(增加一个额外字节来存储字符串本身的长度)来存储值。所以短于指示器长度的 VARCHAR 类型不会被空格填补,但长于指示器的值仍然会被截短。 + 如果是固定长度的字段,比如md5哈希之后的结果,使用char会比较好。 + * 时间 date,time,year ,datetime,timestamp diff --git "a/note/\346\225\260\346\215\256\345\272\223.md" "b/note/\346\225\260\346\215\256\345\272\223.md" old mode 100644 new mode 100755 index b84ee02..556e7c1 --- "a/note/\346\225\260\346\215\256\345\272\223.md" +++ "b/note/\346\225\260\346\215\256\345\272\223.md" @@ -1,11 +1,13 @@ -# 数据库 +# 数据库系统基本概念 ## 目录 * [存储引擎](#存储引擎) * [事务](#事务) +* [分库分表](#分库分表) * [索引](#索引) -* [写高效的SQL语句](#写高效的SQL语句) +* [MVCC](#MVCC) +* [mysql调优](#mysql调优) --- @@ -19,7 +21,6 @@ 3. innodb 支持事务 - 4. 我的一个个人看法,innodb 设计的比较晚,相对于比较周全,如果没有什么特殊癖好,用innodb更好。这好像也是官方给出的建议。 * 聚簇索引和非聚簇索引 @@ -29,27 +30,68 @@ ![tu](../pic/数据库_1.jpg) + * 聚簇索引的优缺点: + + 由于聚簇索引的主键和数据是存放在一起的,当查询数据的时候,找到索引就找到了数据,避免了磁盘随机io。 + + 缺点是: + 1. 对于插入数据的场景,如果插入的数据不是顺序插入,那么就会导致页分裂。 + 2. 对于更新索引key的场景,会导致数据移动。这个也是不允许更新主键key值的原因。 + 3. 对于二级索引的查询,聚簇索引需要访问一次索引找到key,回表查询一次。 + ## 事务 * 事务的特性 - ACID + ACID 是什么意思? + + ![tu](../pic/数据库_2ACID.png) + + 其中,一致性表示的是 事务只有起始状态和结束状态可以被其他事务看见,比如说,事务是 给 A -100元,给B + 100 元。那么,不一致的情况就是只给A 减去了100元,没有给B 加上100元。 * 事务的隔离等级 - 四个隔离等级是: - 1. 未提交读 - 2. 提交读 - 3. 可重复读 - 4. 序列化 + 四个隔离等级 + + 1. 读未提交 (READ-UNCOMMITTED) + + 事务可以读到其他事务修改过(但是未提交的数据) + + 2. 读提交 (READ-COMMITTED) + + 事务可以只能读到其他事务提交过后的事务 + + 3. 可重复读 (REPEATED-READ) + + 在一个事务中,多次读取一个变量,它的数值是一样的。 + + (事务A在开始的时候,查询了一次变量a=100。然后,事务b启动,修改了一次变量a=200,然后提交。然后,事务A还没有结束,然后,继续查询了一次变量a。这个变量是多少呢? 如果隔离等级是读提交,这个a是=200;如果隔离等级是可重复读,这个a=100。因为一个事务中,读到的变量是一样的。) + + 4. 串行化 (SERIALIZABLE) + + 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。 - 解决的问题是: + 举个例子: + + * 如果事务的隔离等级是 :读未提交 + 那么,事务B将变量的值从1修改为2,事务A在v1的值=2。(事务A读到事务B修改但是未提交的东西。) + + * 如果事务的隔离等级是:读提交 + 那么,事务B将变量的值从1修改为2,事务A在v1的值=1,V2=2。(事务A读到事务B修改但是未提交的东西。) + + * 如果事务的隔离等级是: 可重复读 + 那么,事务A读到的v1=1,然后,事务b把1修改为2,然后提交。事务a在查询的时候,为了保证可重复读,那么一定要等于v2=1。(保证一个事务中读到的变量是一样的) + + * 如果事务的隔离等级是:串行化 + 那么事务a查询的时候,加上读锁。事务b修改的时候,试图加写锁。然后被block。等待事务a结束,释放读锁,然后事务b继续执行。 + + 隔离等级试图解决下面的几个问题: 1. 脏读 (读未提交的情况下,会出现脏读) - 脏读指的是:一个事务插入一条数据,然后再rollback。另外一个是事务分别再插入数据之后和rollback之后查询两次,读到的数据是不一样的。 + 脏读指的是:一个事务执行语句a插入一条数据,且并没有提交,然后再执行另外一条语句b修改回去。另外一个是事务分别语句a和语句b执行之后查询两次,读到的数据是不一样的。 2. 不可重复读 @@ -62,50 +104,253 @@ (可重复读的情况下,会出现幻读的情况) - 在一个事务中,第一次查询某条记录,发现没有,但是,当试图更新这条不存在的记录时,竟然能成功,并且,再次读取同一条记录,它就神奇地出现了。 + 在一个事务a,第一次查询某条记录,发现没有。这个时候,事务b插入一个记录。当事务a再次查询的时候,发现记录数量和上次不同。 + + 不可重复读是读取了其他事务更改的数据,针对update操作。幻读是读取了其他事务新增的数据,针对insert和delete操作。 + +* 常用数据库的隔离级别: + MySQL的隔离级别是**可重复读(第三级别的等级)** mysql的级别要更高一点哎 ~ +* 参考: - 关于事务,廖雪峰的这个教程写的很好 [廖雪峰-事务](https://www.liaoxuefeng.com/wiki/001508284671805d39d23243d884b8b99f440bfae87b0f4000/0015091672511496641de7eeea04f67bf55ccf22e35e428000) + [廖雪峰-事务](https://www.liaoxuefeng.com/wiki/001508284671805d39d23243d884b8b99f440bfae87b0f4000/0015091672511496641de7eeea04f67bf55ccf22e35e428000) +## 分库分表 + +什么时候分库,什么时候分表? + +基本的思路是谁是热点拆分谁,如果有一张表,它的数据记录很多,大量的查询和修改都落在这张表上,那可以分表;如果是数据库的查询QPS过高,或者是连接数过高,那么可以分库。 + + * 分表但没有分库 : 表的数据记录过多,读写遇到瓶颈。 + (数据量太多 读的时候 遇到扫描全表的case,就会很慢) + (遇到表锁的case,写入的事务会block其他事务,导致写入慢) + + * 分库但没分表 + 单个数据库的连接过多,qps太高 - 在MySQL中,如果使用InnoDB,**默认的隔离级别是Repeatable Read。** ## 索引 - [数据库索引](./数据库-索引.md) -## 写高效的SQL语句 +## MVCC + +* 什么是mvcc? + + 多版本并发控制 (multi version concurrency control), mvcc 的目的是解决多个事务并发控制。(这本质上也是一种乐观的锁,如果采用悲观的锁,那就是每个事务不允许并行,全部串行执行,这样一定不会出现任何事务隔离等级的问题。 + +* mvcc 实现的原理 + + mvcc给每一行记录(包括被删除的记录)都增加几个隐藏字段,分别是修改的事务trx_id, undo_log_ptr 指针(指向前面的修改记录),是否删除的标记。 + + 通过这个几个隐藏字段携带的信息,innodb就知道这条记录是被那个事务id修改或删除的,以及这条记录在变更记录(undo log)。 + + 理解起来可以认为是通过在每行记录后面保存两个隐藏的列来实现的,这两个列,分别保存了这个行的创建时间,一个保存的是行的删除时间。这里存储的并不是实际的时间值,而是系统版本号(可以理解为事务的ID),每开始一个新的事务,系统版本号就会自动递增,事务开始时刻的系统版本号会作为事务的ID. + + mvcc工作在读提交和不可重复读这两种事务的隔离等级下。 + +* mvcc 解决的问题? + + mvcc工作在读提交和不可重复读这两种事务的隔离等级下,可以解决脏读和不可重复读的问题。 + 那问题来了,mvcc是否可以解决幻读? + - [数据库mvcc](./数据库_mvcc.md) + +## MYSQL的日志 + +redo log : + + mysql在执行一个修改数据的sql事务之前,为了保证事务的原子性和持久性,会采用log先行的方案。先把操作通过redo log记录下来,然后再去真正的修改数据。如果修改数据的中途,mysql重启或物理机重启,那mysql还是可以根据已经落到磁盘上面的redo log 继续完成这个事务。 + + 例如某一事务的事务序号为T1,其对数据X进行修改,设X的原值是5,修改后的值为15,那么Redo日志为x=15,redo是物理日志。 + +undo log: + + undo log就是mvcc中每条记录隐藏字段中的undo指针,指向这条记录的上一个历史版本。这样如果mysql需要回滚的话,可以利用undo,轻松的跳到某个版本。 + + +redo 和 undo log记录的流程: +``` +假设有A、B两个数据,值分别是 1 和 2,在一个事务中先后把A设置为3,B设置为4。 + +1.事务开始 + +2.记录A=1到undo log buffer + +3.修改A=3 + +4.记录A=3到redo log buffer + +5.记录B=2到undo log buffer + +6.修改B=4 + +7.记录B=4到redo log buffer + +8.到log buffer全部刷入到磁盘中后才提交数据 + +这里有个点,log buffer 刷入到磁盘,并不是最后要提交事物了才来一次性全部刷入到磁盘。log buffer刷入到log file是在事务进行的时候就逐步在做了。 +``` + +逻辑日志和物理日志的区别: + + 在mysql的日志中,经常提到的一个概念是逻辑日志和物理日志。逻辑日志指的是,像是sql语句一样的操作日志。而物理日志可以理解为数据页的数据变化日志,更像是undo log。 + + redo log 和 undo log一般被认为是物理日志,也有一种说法是(物理+逻辑混合日志 : https://spongecaptain.cool/post/database/logicalandphicallog/), binlog是逻辑日志。 + +为什么是binlog? + + 类似于undo log,mysql把修改自己数据的sql语句记录下来,形成的日志。binlog日志只用于归档,只依靠binlog是没有crash-safe能力的。 + + binlog的使用场景更多的是,用于主从同步 (slave节点收到master节点同步的binlog数据,然后进行重放),其次使用mysqlbinlog工具来恢复数据. + + +## 几种主键方案 + +1. 使用id自增 + + 自增的id好处是可以保证顺序插入,对于是聚簇索引的引擎,顺序的插入可以保证数据是顺序的写入,避免页分裂。 + + 缺点是: + + 当需要合并表的时候,就比较痛苦了,需要额外处理id。其次,如果是要水平分表的话,不同表的id自增要考虑是否有可能重复。 + +2. 使用uuid + + uuid的优点是不会是重复的,合表的时候,不需要关心重复的问题。 + + 缺点是: + + 但是uuid是字符串的格式,相对于数字类型的话,需要的存储的空间比较大, 且由于字符串的类型比较运算的成本是高于整数的。另外,由于uuid不是顺序的,插入的时候,不能保证数据是顺序写入的。 + +3. 使用其他业务层定义的唯一id + + +## mysql的锁 + +mysql的锁分别共享锁和排他锁。排他锁中按照锁的粒度,分为行锁和表锁。表锁会锁定整张表并且阻塞其他用户对该表的所有读写操作,比如**alter修改表结构的时候会锁表**。行锁又可以分为乐观锁和悲观锁,悲观锁可以通过for update实现,乐观锁则通过版本号实现。 + +* 记录锁、间隙锁,临键锁 + + 记录锁 + ``` + select * from table where a = "xxx" for update; + ``` + + 间隙锁 + ``` + select * from table where a between 0 and 100; + + // 锁定0~100的区间,并且不包括0和100 + ``` + + 临键锁 + 在默认情况下,mysql的事务隔离级别是可重复读,并且innodb_locks_unsafe_for_binlog参数为0,这时默认采用next-key locks。所谓Next-Key Locks,就是Record lock和gap lock的结合,即除了锁住记录本身,还要再锁住索引之间的间隙。 + + https://zhuanlan.zhihu.com/p/48269420 + +* for update 操作什么时候会是行锁,什么时候会是表锁? + + 1. 如果明确指定主键的话,变成行锁。 + + select * from table where id = "xxx" for update; + + 2. 如果指定的不是主键,不会是行锁。mysql会锁定一个区间。(变成间隙锁) + + select * from table where name = "xxx" for update; // name不是主键 + +## mysql调优 + +* 执行计划 explain + + 使用方法 explain + sql + + 里面的关键字段是type字段,type的不同输出表示了不同的执行情况。 + + ``` + const > eq_ref > ref > index > all + + 1. const, eq_ref, ref 走了唯一索引,表示很快找到了数据 + + 2. index 表示值遍历了索引树,就找到了数据 + + 3. all 全表遍历 + ``` + +* 慢查询日志 + + long_query_time 的默认值为10,意思是运行10秒以上的语句会被记录到日志中。 + +## 其他 + +* in 和 exsit 的区别 + + https://www.jianshu.com/p/f212527d76ff + +* binlog记录的几种方案 + + 1. 同步sql操作 + 这种方案的缺点是对于同步关于时间相关的sql,就会问题。比如insert * from table where a = datetime(); + + 2. 同步数据状态 + 同步数据值的变成,缺点是会产生大量的日志记录。但是可以避免上面提到的问题。 + + 3. mix方案 + 就是两种方案混合起来。 + +* count(1) 和 count(*), count(列名) 的区别 + + 1. count(1) 的执行效率是约等于 count(*) + + 2. count(列名) 查询到这个字段非空的记录数 + + https://blog.csdn.net/iFuMI/article/details/77920767 + +* 批处理的思想 + + 1. 大量插入数据的时候 + ``` + insert into T values(1,2) + insert into T values(3,4) + insert into T values(5,6) + + -- 下面的批量插入的效率会更高 + insert intO T values(1,2) (3,4) (5,6) + ``` + + 2. 大量的记录要删除 + + 先删除索引,在删除记录 -* explain +* 水平分表的好处 -## SQL的教程 + 1. 将不同的记录行分散到不同的表中,避免表锁相互竞争。 -- [SQL教程](https://www.liaoxuefeng.com/wiki/001508284671805d39d23243d884b8b99f440bfae87b0f4000) +* 垂直分表的好处 -* 看完廖雪峰的教程可以思考几个问题: + 1. 将长度的很多的字段拆分出去 / 将不常用的字段拆分出去 - * 数据库的主键应该如何设置?什么样的列适合做主键? + 2. 将常用的查询字段组合放到一张表中 - **主键有两个特征,第一就是不可以重复,第二是不可以修改。** + 将热门和冷门的查询拆分到不同的地方,避免io竞争。 - **一般不适用业务逻辑的字段设置为主键,主键一般会新设置一列,它的属性是自增。** +* 事务提交log的刷新控制 - 因为,业务逻辑可能会更改,如果用身份证的id做主键,比如有一天身份证的位数不够了,需要修改,这样就比较麻烦了。 + 在写redo_log的时候先把数据写到redo_log缓冲区,然后异步写入磁盘,很显然,极端情况下会有丢失数据的可能。 - * 外键是什么?需要设置外键吗?加入外键的优点和缺点 + 控制这个刷盘策略的的参数叫做innodb_flush_log_at_trx_commit +这个参数有3个值:0|1|2,**默认的话是1。** - **外键是数据库的一种约束**,但是这样往往可能会造成效率上面的问题。另外一种方式就是由上层的业务层这样约束的可靠性,而数据库不设置外键。 + 0. 代表提交事务时不会写入磁盘,这样的话性能当然最好,但是在Mysql宕机的情况会丢失上一秒的事务的数据。 - * 加入索引的优点和缺点 + 1. 代表提交事务一定会进行一次刷盘,同步当然性能最差,但是也最安全。 - 1. 加入索引可以提交查询的效率,但是插入数据和删除数据时,同样需要修改索引。同时,设置索引还会有空间的开销。 + 2. 代表写入文件系统的缓存,不进行刷盘。这个选项性能略差于1,Mysql宕机的话对数据没有任何影响,只有在操作系统宕机才会丢失数据,这种情况下默认Mysql每秒会执行一次刷盘。 - 2. 索引要有区分度。男女性别这样的就不适合做索引 - * 索引和主键的区别 - 1. 由于主键的设置在没有意义的字段上面,这个时候就可以给经常查询的业务字段上面设置唯一索引。来提高查询效率。 +* 一条sql语句的执行流程 + ![tu](../pic/mysql.png) \ No newline at end of file diff --git "a/note/\346\225\260\346\215\256\345\272\223_mvcc.md" "b/note/\346\225\260\346\215\256\345\272\223_mvcc.md" new file mode 100755 index 0000000..c9d7ac7 --- /dev/null +++ "b/note/\346\225\260\346\215\256\345\272\223_mvcc.md" @@ -0,0 +1,90 @@ +# 数据库MVCC机制 + +## 目录 + +* [mvcc的具体实现原理](#mvcc的具体实现原理) + +* [mvcc是否可以解决幻读?](#mvcc是否可以解决幻读) + +--- + +## mvcc的具体实现原理? + +* mvcc的两种读模式 +1. 当前读 + + 读最新版本是数据,主要应用于更新操作。 + + ``` + select * from table where xxx lock in share mode, + select * from table where xxx for update, + update table set.... + insert into table (xxx,xxx) values (xxx,xxx) + delete from table where id = xxx + ``` + +2. 快照读 + + 比如开启一个select查询的事务的时候,读取的只是当前事务的可见版本. + +* mvcc实现的原理 + + 每行记录携带几个隐藏字段 + + |isDelete |DB_TRX_ID |DB_ROLL_PTR| + | ---- | ---- | ---- | + |true/false| 事务id |回滚指针 | + + 示意图如下: + ![tu](../pic/mvcc.png) + +* mvcc如何解决脏读,不可重复读? + + todo + +## mvcc是否可以解决幻读? + +那么说RR模式下利用MVCC可以解决一定程度上的幻读,但是MySQL没有使用,利用了GAP锁来保证了严格的幻读,其实也就是串行化的一种实现方式吧吗。 + +如下面的例子,有两个事务,在RR隔离级别下, select是没有幻读的,但select for update却会产生幻读。因为select是读,通过时间戳读快照,事务2读不到事务1的写入。**而select for update被认为是写,是可以更新已提交数据的,所以读到的是最新版本,事务2可以读到事务1的写入。** + +``` +事务1 事务2 + +mysql> start transaction; mysql> start transaction; +Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) + + + mysql> select * from t; + Empty set (0.00 sec) +mysql> insert into t values(1); +Query OK, 1 row affected (0.00 sec) +mysql> commit; +Query OK, 0 rows affected (0.01 sec) + // no phantom + mysql> select * from t; + Empty set (0.00 sec) + + // phantom + mysql> select * from t for update; + +------+ + | c | + +------+ + | 1 | + +------+ + 1 row in set (0.00 sec) + // update committed row + mysql> update t set c=2; + Query OK, 0 rows affected (0.00 sec) + Rows matched: 1 Changed: 0 Warnings: 0 + + mysql> commit; + Query OK, 0 rows affected (0.01 sec) +``` + + +--- + +## 参考 + +1. https://www.zhihu.com/question/334408495/answer/745098902 \ No newline at end of file diff --git "a/note/\346\266\210\346\201\257\351\230\237\345\210\227.md" "b/note/\346\266\210\346\201\257\351\230\237\345\210\227.md" new file mode 100755 index 0000000..aeb2f42 --- /dev/null +++ "b/note/\346\266\210\346\201\257\351\230\237\345\210\227.md" @@ -0,0 +1,133 @@ +# 消息队列 + +## 目录 + +* [消息重复](#消息重复) +* [消息丢失](#消息丢失) +* [消息积压](#消息积压) +* [消息顺序消费](#消息顺序消费) +* [消息队列是如何实现分布式事务](#消息队列是如何实现分布式事务) + +--- + +## 消息重复 + +幂等性设计 + +- 使用唯一id; +- 对于处理过的消息进行保存,收到消息后,根据消息的唯一id更新查询,判断消息是否处理过; + +--- + +## 消息丢失 + +看到过一些方案,基本的思路都是基于消息确认机制。 + +首先,是消息丢失会丢在哪些可能的环节? + +1. 发送方 到 消息队列 之间出问题 + +2. 消息队列内部出问题,比如持久化出问题 + +3. 消费方消费的时候出问题 + +这里要结合使用的消息队列来考虑下了: + +* 发送方调用向消息队列发送的接口,是否支持ack机制。如果发送失败了,可以尝试重试。(重试的话,需要保证消费的消息是支持防止重复的) + +* 消息队列现在已经比较成熟了,一般不会出现内部丢消息。step2可以先忽略。(或者是使用姿势不对,比如需要重启,当时没有配置持久化;) + +----- + +整理下看到过的一些思路: + +方案零: + +* 利用消息队列的有序性来验证是否有消息丢失。原理非常简单,在发送端,给每个发出的消息附加一个连续递增的序号,然后在接受端来检查这个序号的连续性。 + +方案一: + +* 发送方发送消息之后,挂一个timer,如果在timer到期之后,还没有收到rsp,那就认为出现的了超时。超时有两种可能,第一种是消息在路上丢掉了,第二种是收消息的一方挂了,或者是消息堆积了,没有来得及处理。 + +方案二: (这个也是对账的一个基本思路) + +* 发送方在发送的时候,在db中插入一条记录;消息的接收方在收到消息之后,从db查询到这条记录,然后更新db的状态位。 + + 这样做后,即使出现了消息丢失,也可以通过定时任务扫描出一段时间内未完成的消息,进行重新投递. + + +----- + +## 消息积压 + +发送方太快,收消息方太慢。速度不匹配。 + +1. 发送方降低速度; +2. 收消息方的平滑配置不合理,处理的太慢; +3. 收消息方 多开实例,优化性能热点,加快消息消费 等 + +------ + +## 消息顺序消费 + +消息a要在消息b之前被消费? +(比如,在游戏中,创建新地图的消息需要在 玩家进入新地图之前被处理; +或者,在电商中,用户下单后,扣款的消息要在发货的消息之后被处理) + +大概的思路是: + +1. 让消息a和消息b发到同一个queue中,串行化处理。 + +2. 让消息a和消息b走同一条消息转发的链路 + +---- + +## 消息队列是如何实现分布式事务 + +分布式事务是一个后台开发的比较头疼的问题。在实践中,有很多这样的场景。比如用户某个操作,需要在进程a上扣10元,需要在进程b发上奖励积分。 + +如果顺序执行的话,很有可能在a上扣除10元成功后,在b上发送失败。失败的原因会有很多种,比如积分达到上限,或 超时(这种最坑 从调用方的角度,甚至不知道是失败还是成功,如果冒然重试的话,有可能出现多发)。 + +如果从整体上看的话,当然是系统这个跨进程的操作本身是原子的,要不都成功,要不都失败。业内有些方案来解决这个问题,但是这些方案不能照抄,要考虑下是否可以结合自己的业务落地。 + +通用的解决方案的核心思想就是2pc。将一个事务分为协调者,和执行者。同时,分成两个阶段,准备阶段(check阶段)和提交阶段(ack阶段)。当执行一个事务的时候,协调者通知执行者,开始执行准备阶段。 + +结合我们刚才的那个例子,具体步骤就是: + +1. 在进程a上查看用户是否可以成功扣除10元,但是不会正在的扣除,只是check; + +2. 在进程b上查看用户是否可以成功加积分。(同样也是 不会真的加,只是check) + +如果都check成功后,进入下一步,执行阶段。结合上面的例子,具体的步骤是: + +1. 进程a开始扣10元 + +2. 进程b开始发积分 + +看起来很完美,一切顺利。不过对于很多游戏的后台来说,有个比较困难的问题,游戏里面要修改角色的数据,为了性能是不会是直接修改db的,而是修改缓存。通过write back的机制,再将缓存的数据写入到db。 + +那这样问题就来了,这里并没有一个很好的机制去“锁定资源”。比如,当我们check的时候,角色身上有20元,可以check扣款成功。当时在异步的过程中,这里有可能会有其他的请求进来,把给角色扣了15元。甚至角色都有可能传送走了,或者是下线。对于这种业务的后台来说,很难去锁定资源(锁定角色 或者说是锁定角色身上的这10元)。 + +因此,顺着这个思路往下想解决办法,可能会有两种。分别是: + +1. 克服些困难,去给他锁上。 + +2. 在check的时候,先与扣除,如果后面失败了,在补发。 + +* 方案1的问题是: + + 比如在执行这个分布式的事务中,我们锁定了角色,不允许它传送,不允许下线,不允许其他业务去给他扣钱。 + + 那可能会带来很多问题,如果这个分布式事务超时了,正常情况下最多锁定50毫秒事务就执行完毕了;但是,超时的时候,锁定了30秒,还没收到解锁的rsp。那这种会block其他非常多的业务。其他的业务怎么去补? + + 比如其他的业务是玩法结束,踢人,地图销毁。那这个带锁的角色,要怎么办?卡在里面30秒。这种方案耦合了太多的业务逻辑,实现起来有很多坑,非常复杂。 + +* 方案2的问题是: + + 如果失败要补发的时候,角色下线了,或者是传送走了,怎么办? + + 这里虽然是问题,当时不会很大。可以提供一个通用的补偿机制,比如发离线奖励邮件等。或者是离线消息,下次登录的时候补偿等。 + + 除此之外,这里还要考虑玩家主动获利的场景。刚才的例子正好玩家不会主动获利,如果事务是先给玩家发10元,再扣除一个道具。 + + 那么,肯定会有玩家卡bug,比如在获得10元奖励后,立即下线。这样就扣不到自己的道具了。所以,再设计分布式事务的时候,需要考虑不要让玩家去主动获利。 \ No newline at end of file diff --git "a/note/\347\263\273\347\273\237\350\256\276\350\256\241.md" "b/note/\347\263\273\347\273\237\350\256\276\350\256\241.md" new file mode 100755 index 0000000..2e563c3 --- /dev/null +++ "b/note/\347\263\273\347\273\237\350\256\276\350\256\241.md" @@ -0,0 +1,79 @@ + +# 系统设计 + +系统设计需要考虑的三点: + +* 高性能 + +* 高可用 + +* 可扩展 + +----- + +## 高性能 + +性能优化首先要有一个完善的监控体系来度量性能指标。 + +比如 +* 机器层面的 cpu,内存,io,网络等指标; + +* 应用层面的 请求的平均响应时间(处理时间) + + +性能优化的“八二原则”, +大概的意思就是,少量的热点逻辑 消耗的大量的性能。所以,性能优化的第一部就是定位到热点,然后结合业务去优化和取舍(时间换空间,空间换时间,限流,降级,平滑等) + + +大部分的接口的性能都遵守这种图: +![](../pic/%E7%B3%BB%E7%BB%9F%E8%AE%BE%E8%AE%A11.png) + +---- + +## 高可用 + +1. 如何量化高可用性,评价指标是什么? + + GOOGLE SRE 里面提及了很多指标,大概就是系统是几个9,比如99%,99.9%, 99.99% 等。 + +2. 设计系统的时候,需要在可靠性方面 注意什么? (design for failure) + + 在设计系统的时候,把发生故障作为一个重要的考虑点,预先考虑如何自动化地发现故障,发生故障之后要如何解决。 + + 当然,除了要有未雨绸缪外,我们还需要掌握一些具体的优化方法,比如 failover(故障转移)、超时控制以及降级和限流。 + + * 故障转移 + + 一个节点挂了,可以切换到其他的节点,或者可以重新拉起,或者有重试机制等。 + + 最广泛的故障检测机制是“心跳”,一个很经典的问题,就是系统的超时时间要设为多少? + + 很多时候都是拍脑门,随便定一个。 + + GOOGLE SRE 里面也提到这个事,比较科学的办法是,可以看下这台机器(或者这个接口)正常情况下,一个请求的响应时间是多少,拉出来一个分布图,大于99%或者是超过个比例 作为参考。 + + * 服务降级 + + 当机器进入一个危险状态,丢弃掉或者拒绝掉一些不重要的服务,保证核心功能正常。 + + * 限流 (平滑队列)等 + + 请求进行限速来保护系统 + +------ + +### 可扩展性 + +我理解,可扩展性是希望可以通过平行扩展(加机器的方式,而不是提供单台机器性能的方式)去提高性能的性能。或者是提供系统的可用性。 + +不过,这个话题更多的是要结合业务的特性去考虑,比如是否是有状态服务或无状态服务。如果是无状态的服务,那问题就会好很多。 + +尝试从几个方面去思考,比如: + +1. 从数据的层面 + + 分库分表,水平拆分,垂直拆分 + +2. 从应用的层面 + + 按照有无状态,业务的功能(类似微服务的思想),进程的重要性 等角度去拆分 \ No newline at end of file diff --git "a/note/\347\263\273\347\273\237\350\256\276\350\256\241\347\261\273\347\232\204\351\227\256\351\242\230.md" "b/note/\347\263\273\347\273\237\350\256\276\350\256\241\347\261\273\347\232\204\351\227\256\351\242\230.md" old mode 100644 new mode 100755 diff --git "a/note/\347\272\277\347\250\213\345\220\214\346\255\245.md" "b/note/\347\272\277\347\250\213\345\220\214\346\255\245.md" old mode 100644 new mode 100755 diff --git "a/note/\347\274\223\345\255\230\347\263\273\347\273\237.md" "b/note/\347\274\223\345\255\230\347\263\273\347\273\237.md" new file mode 100755 index 0000000..fbf43dd --- /dev/null +++ "b/note/\347\274\223\345\255\230\347\263\273\347\273\237.md" @@ -0,0 +1,3 @@ +# 缓存系统 + +https://www.jianshu.com/p/057da7850c93 \ No newline at end of file diff --git "a/note/\347\274\226\347\240\201\351\234\200\350\246\201\346\263\250\346\204\217\347\232\204\351\227\256\351\242\230.md" "b/note/\347\274\226\347\240\201\351\234\200\350\246\201\346\263\250\346\204\217\347\232\204\351\227\256\351\242\230.md" old mode 100644 new mode 100755 index ddec79f..a85f2d9 --- "a/note/\347\274\226\347\240\201\351\234\200\350\246\201\346\263\250\346\204\217\347\232\204\351\227\256\351\242\230.md" +++ "b/note/\347\274\226\347\240\201\351\234\200\350\246\201\346\263\250\346\204\217\347\232\204\351\227\256\351\242\230.md" @@ -76,4 +76,26 @@ { memset(&rt, 0, sizeof(rt)); } + ``` + +* 循环语句记得要留意边界条件 + ``` + int target_arr[len]; + int target_idx = 0; + for (int i = 0; i < count; i++) + { + target_arr[target_idx] = i; + + + target_idx++; + } + ``` + +* 条件语句要检查不同的分支 + ``` + if (val达到上限) + { + val = 上限 + } + val = val + 100 // fix me 应该走不同的分支,漏掉else了 ``` \ No newline at end of file diff --git "a/note/\347\274\226\350\257\221,\351\223\276\346\216\245\344\270\216\350\243\205\350\275\275.md" "b/note/\347\274\226\350\257\221,\351\223\276\346\216\245\344\270\216\350\243\205\350\275\275.md" old mode 100644 new mode 100755 index f833f35..10657da --- "a/note/\347\274\226\350\257\221,\351\223\276\346\216\245\344\270\216\350\243\205\350\275\275.md" +++ "b/note/\347\274\226\350\257\221,\351\223\276\346\216\245\344\270\216\350\243\205\350\275\275.md" @@ -2,6 +2,10 @@ ## 目录 +* [编译](#编译) + * [编译](#编译) + * [构建工具](#构建工具) + * [静态库](#静态库) * [制作一个静态库](#制作一个静态库) * [链接静态库](#链接静态库) @@ -13,6 +17,48 @@ --- +## 编译 + +### 编译一个文件的流程 + +把一个.cpp文件编译成为可执行的文件,按照教科书上面的流程是: + + 预处理 --> 汇编代码 --> 链接 --> 可执行的机器码 + +如果是用g++写的话: + + g++ main.cpp # 这样一步就生成了a.out 文件 + +如果需要多个文件编译的话: + + g++ mian.cpp func.cpp + + # or + g++ -c func.cpp + g++ main.cpp func.o + + # or + g++ 的 -I -L 选项,可以include相应的头文件和库文件(对于大型项目) + + +初学c++的时候,被这些困扰了很久,为了搞明白,写了很多笔记类的blog。 + +* Linux下 C++代码编译和链接文件的具体过程和分析: +https://www.jianshu.com/p/c682a5a23288 + +* LINUX下默认搜索头文件及库文件的路径: +https://www.jianshu.com/p/3eb25114576e + +* 在linux下使用gcc/g++编译多个.h .c 文件: +https://www.jianshu.com/p/e5c6a255076b + +### Make构建工具 + + make + # https://www.jianshu.com/p/0107cae15e5a + + make 自动推导 + # https://www.jianshu.com/p/27070bbcba4d ## 静态库 @@ -155,6 +201,40 @@ g++ main.cc -L ./lib/ -ldynamicprint export LD_LIBRARY_PATH ``` +* 使用rpath将动态库的路径指定到编译的生成的可执行文件中 + ``` + dependencies_include_path=/data/home/your_path + dependencies_lib_path=/data/home/your_lib + + // -rpath 执行lua库的位置 + g++ -g -I${dependencies_include_path}/lua-5.1.4/src -L ${dependencies_lib_path} -llua -Wl,-rpath=${dependencies_lib_path} test.cpp -o test + ``` + + ``` + // 编译的时候 如果不通过-rpath 指定的话 ldd查看的话,是找不到liblua的 + ldd test5 + linux-vdso.so.1 => (0x00007ffff7ffa000) + /$LIB/libonion.so => /lib64/libonion.so (0x00007ffff7bd5000) + liblua.so => not found + libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007ffff78cd000) + libm.so.6 => /lib64/libm.so.6 (0x00007ffff75cb000) + libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007ffff73b5000) + libc.so.6 => /lib64/libc.so.6 (0x00007ffff6fe7000) + libdl.so.2 => /lib64/libdl.so.2 (0x00007ffff6de3000) + /lib64/ld-linux-x86-64.so.2 (0x00007ffff7ddb000) + + // 编译的时候,加上rpath + ldd test5 + linux-vdso.so.1 => (0x00007ffff7ffa000) + /$LIB/libonion.so => /lib64/libonion.so (0x00007ffff7bd5000) + liblua.so => /lib/liblua.so (0x00007ffff7ebf000) + libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007ffff78cd000) + libm.so.6 => /lib64/libm.so.6 (0x00007ffff75cb000) + libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007ffff73b5000) + libc.so.6 => /lib64/libc.so.6 (0x00007ffff6fe7000) + libdl.so.2 => /lib64/libdl.so.2 (0x00007ffff6de3000) + /lib64/ld-linux-x86-64.so.2 (0x00007ffff7ddb000) + ``` * 补充 diff --git "a/note/\350\256\276\350\256\241\346\250\241\345\274\217.md" "b/note/\350\256\276\350\256\241\346\250\241\345\274\217.md" old mode 100644 new mode 100755 index 6d421ec..687daf4 --- "a/note/\350\256\276\350\256\241\346\250\241\345\274\217.md" +++ "b/note/\350\256\276\350\256\241\346\250\241\345\274\217.md" @@ -1,21 +1,53 @@ -# 设计模式 +## 设计模式 -## 目录 -* [观察者模式](#观察者模式) +一个非常强的分享设计模式的网站,居然还tm支持了中文。 +https://refactoringguru.cn/ +---- ---- +>[《重构》的笔记](./《重构》的笔记.md) -## 观察者模式 +>[设计模型的几个原则](./设计模式的基本原则.md) -## 状态机模型 +#### 1. 创建型模式 +>[单例模式](./design_pattern/note/4单例模式.md) -## 单例模式 +>[工厂模式](./design_pattern/note/3工厂模式.md) -## 装饰器模式 +#### 2. 结构型模式 ---- -## 参考: -- [设计模型](https://design-patterns.readthedocs.io/zh_CN/latest/index.html) \ No newline at end of file +结构型模式(Structural Pattern)描述如何将类或者对 象结合在一起形成更大的结构,就像搭积木,可以通过 简单积木的组合形成复杂的、功能更为强大的结构。 + +>[装饰器模式](./design_pattern/note/10装饰器模式.md) + +>[facade模式](./design_pattern/note/12门面fecade模式.md) + +>[proxy模式](./design_pattern/note/6代理模式.md) + +>[adapter模式](./design_pattern/note/7适配器模式.md) + +>[享元模式](./design_pattern/note/5享元模式.md) + +#### 3. 行为型模式 + +行为型模式(Behavioral Pattern)是对在不同的对象之间划分责任和算法的抽象化。 + +>[模板方法模式](./design_pattern/note/0模板模式.md) + +>[策略模式](./design_pattern/note/1策略模式.md) + +>[观察者模式](./design_pattern/note/2观察者模式.md) + +>[责任链模式](./design_pattern/note/9责任链模式.md) + +#### 参考: + +gof 设计模式 + +https://www.liaoxuefeng.com/wiki/1252599548343744/1264742167474528 + +https://github.com/rhyspang/CPP-Design-Patterns + +https://design-patterns.readthedocs.io/zh_CN/latest/index.html \ No newline at end of file diff --git "a/note/\350\256\276\350\256\241\346\250\241\345\274\217\347\232\204\345\237\272\346\234\254\345\216\237\345\210\231.md" "b/note/\350\256\276\350\256\241\346\250\241\345\274\217\347\232\204\345\237\272\346\234\254\345\216\237\345\210\231.md" old mode 100644 new mode 100755 diff --git "a/pic/Linux\346\200\247\350\203\275\345\210\206\346\236\2202.jpg" "b/pic/Linux\346\200\247\350\203\275\345\210\206\346\236\2202.jpg" old mode 100644 new mode 100755 diff --git "a/pic/Linux\346\200\247\350\203\275\345\210\206\346\236\2203.jpg" "b/pic/Linux\346\200\247\350\203\275\345\210\206\346\236\2203.jpg" old mode 100644 new mode 100755 diff --git "a/pic/Linux\346\200\247\350\203\275\345\210\206\346\236\2204.jpg" "b/pic/Linux\346\200\247\350\203\275\345\210\206\346\236\2204.jpg" old mode 100644 new mode 100755 diff --git "a/pic/apue\347\254\224\350\256\260.jpg" "b/pic/apue\347\254\224\350\256\260.jpg" old mode 100644 new mode 100755 diff --git a/pic/brk1.png b/pic/brk1.png new file mode 100755 index 0000000..9d6b5c5 Binary files /dev/null and b/pic/brk1.png differ diff --git a/pic/docker_1.png b/pic/docker_1.png new file mode 100755 index 0000000..e346ff6 Binary files /dev/null and b/pic/docker_1.png differ diff --git a/pic/docker_pic.PNG b/pic/docker_pic.PNG old mode 100644 new mode 100755 diff --git a/pic/git_1.JPG b/pic/git_1.JPG old mode 100644 new mode 100755 diff --git a/pic/git_2.JPG b/pic/git_2.JPG old mode 100644 new mode 100755 diff --git a/pic/git_3.JPG b/pic/git_3.JPG old mode 100644 new mode 100755 diff --git a/pic/git_4.png b/pic/git_4.png old mode 100644 new mode 100755 diff --git a/pic/git_5.png b/pic/git_5.png old mode 100644 new mode 100755 diff --git a/pic/git_6.JPG b/pic/git_6.JPG old mode 100644 new mode 100755 diff --git a/pic/innodb.png b/pic/innodb.png new file mode 100755 index 0000000..0b87786 Binary files /dev/null and b/pic/innodb.png differ diff --git a/pic/innodb2.png b/pic/innodb2.png new file mode 100755 index 0000000..33a02e7 Binary files /dev/null and b/pic/innodb2.png differ diff --git "a/pic/linux\346\200\247\350\203\275\345\210\206\346\236\2201.PNG" "b/pic/linux\346\200\247\350\203\275\345\210\206\346\236\2201.PNG" old mode 100644 new mode 100755 diff --git a/pic/make_pic1.png b/pic/make_pic1.png new file mode 100755 index 0000000..f8d8a60 Binary files /dev/null and b/pic/make_pic1.png differ diff --git a/pic/malloc.png b/pic/malloc.png new file mode 100755 index 0000000..1430717 Binary files /dev/null and b/pic/malloc.png differ diff --git a/pic/malloc2.png b/pic/malloc2.png new file mode 100755 index 0000000..d3c0541 Binary files /dev/null and b/pic/malloc2.png differ diff --git a/pic/malloc3.png b/pic/malloc3.png new file mode 100755 index 0000000..74603b9 Binary files /dev/null and b/pic/malloc3.png differ diff --git a/pic/mvcc.png b/pic/mvcc.png new file mode 100755 index 0000000..4c5bd93 Binary files /dev/null and b/pic/mvcc.png differ diff --git a/pic/myisam.png b/pic/myisam.png new file mode 100755 index 0000000..2a401f2 Binary files /dev/null and b/pic/myisam.png differ diff --git a/pic/mysql.png b/pic/mysql.png new file mode 100755 index 0000000..df35187 Binary files /dev/null and b/pic/mysql.png differ diff --git a/pic/perf.png b/pic/perf.png old mode 100644 new mode 100755 diff --git a/pic/px_pic1.png b/pic/px_pic1.png new file mode 100755 index 0000000..85127e9 Binary files /dev/null and b/pic/px_pic1.png differ diff --git a/pic/px_pic2.png b/pic/px_pic2.png new file mode 100755 index 0000000..6fedb24 Binary files /dev/null and b/pic/px_pic2.png differ diff --git a/pic/px_pic3.png b/pic/px_pic3.png new file mode 100755 index 0000000..78e68e8 Binary files /dev/null and b/pic/px_pic3.png differ diff --git a/pic/rate_limit_1.png b/pic/rate_limit_1.png new file mode 100755 index 0000000..0aabfdf Binary files /dev/null and b/pic/rate_limit_1.png differ diff --git a/pic/rate_limit_2.png b/pic/rate_limit_2.png new file mode 100755 index 0000000..679167c Binary files /dev/null and b/pic/rate_limit_2.png differ diff --git a/pic/tcp1.PNG b/pic/tcp1.PNG old mode 100644 new mode 100755 diff --git a/pic/tcp2.PNG b/pic/tcp2.PNG old mode 100644 new mode 100755 diff --git a/pic/tcp3.PNG b/pic/tcp3.PNG new file mode 100755 index 0000000..82266c9 Binary files /dev/null and b/pic/tcp3.PNG differ diff --git a/pic/uml_aggregation.png b/pic/uml_aggregation.png old mode 100644 new mode 100755 diff --git a/pic/uml_assocation.png b/pic/uml_assocation.png old mode 100644 new mode 100755 diff --git a/pic/uml_composition.png b/pic/uml_composition.png old mode 100644 new mode 100755 diff --git a/pic/uml_dependency.png b/pic/uml_dependency.png old mode 100644 new mode 100755 diff --git a/pic/uml_inhert.png b/pic/uml_inhert.png old mode 100644 new mode 100755 diff --git "a/pic/\344\270\200\350\207\264\346\200\247\345\223\210\345\270\214.png" "b/pic/\344\270\200\350\207\264\346\200\247\345\223\210\345\270\214.png" new file mode 100755 index 0000000..a6d9dda Binary files /dev/null and "b/pic/\344\270\200\350\207\264\346\200\247\345\223\210\345\270\214.png" differ diff --git "a/pic/\345\206\205\345\255\230_1.png" "b/pic/\345\206\205\345\255\230_1.png" new file mode 100755 index 0000000..b30027d Binary files /dev/null and "b/pic/\345\206\205\345\255\230_1.png" differ diff --git "a/pic/\345\207\275\346\225\260\350\260\203\347\224\2501.png" "b/pic/\345\207\275\346\225\260\350\260\203\347\224\2501.png" new file mode 100755 index 0000000..62b5012 Binary files /dev/null and "b/pic/\345\207\275\346\225\260\350\260\203\347\224\2501.png" differ diff --git "a/pic/\345\207\275\346\225\260\350\260\203\347\224\2502.png" "b/pic/\345\207\275\346\225\260\350\260\203\347\224\2502.png" new file mode 100755 index 0000000..333de34 Binary files /dev/null and "b/pic/\345\207\275\346\225\260\350\260\203\347\224\2502.png" differ diff --git "a/pic/\345\207\275\346\225\260\350\260\203\347\224\2503.png" "b/pic/\345\207\275\346\225\260\350\260\203\347\224\2503.png" new file mode 100755 index 0000000..1f035f2 Binary files /dev/null and "b/pic/\345\207\275\346\225\260\350\260\203\347\224\2503.png" differ diff --git "a/pic/\345\207\275\346\225\260\350\260\203\347\224\2504.png" "b/pic/\345\207\275\346\225\260\350\260\203\347\224\2504.png" new file mode 100755 index 0000000..995e39a Binary files /dev/null and "b/pic/\345\207\275\346\225\260\350\260\203\347\224\2504.png" differ diff --git "a/pic/\345\207\275\346\225\260\350\260\203\347\224\250\347\256\200\345\215\225\347\232\204\346\261\207\347\274\226\344\273\213\347\273\215.pdf" "b/pic/\345\207\275\346\225\260\350\260\203\347\224\250\347\256\200\345\215\225\347\232\204\346\261\207\347\274\226\344\273\213\347\273\215.pdf" new file mode 100755 index 0000000..84c5421 Binary files /dev/null and "b/pic/\345\207\275\346\225\260\350\260\203\347\224\250\347\256\200\345\215\225\347\232\204\346\261\207\347\274\226\344\273\213\347\273\215.pdf" differ diff --git "a/pic/\345\244\232\346\200\201\345\222\214\350\231\232\345\207\275\346\225\260_1.jpg" "b/pic/\345\244\232\346\200\201\345\222\214\350\231\232\345\207\275\346\225\260_1.jpg" old mode 100644 new mode 100755 diff --git "a/pic/\345\244\232\346\200\201\345\222\214\350\231\232\345\207\275\346\225\260_2.jpg" "b/pic/\345\244\232\346\200\201\345\222\214\350\231\232\345\207\275\346\225\260_2.jpg" old mode 100644 new mode 100755 diff --git "a/pic/\345\267\245\345\205\267\346\240\210_1.png" "b/pic/\345\267\245\345\205\267\346\240\210_1.png" old mode 100644 new mode 100755 diff --git "a/pic/\345\267\245\345\205\267\346\240\210_2.png" "b/pic/\345\267\245\345\205\267\346\240\210_2.png" old mode 100644 new mode 100755 diff --git "a/pic/\345\267\245\345\205\267\346\240\210_3.png" "b/pic/\345\267\245\345\205\267\346\240\210_3.png" old mode 100644 new mode 100755 diff --git "a/pic/\345\267\245\345\205\267\346\240\210_4.png" "b/pic/\345\267\245\345\205\267\346\240\210_4.png" old mode 100644 new mode 100755 diff --git "a/pic/\345\267\245\345\205\267\346\240\210_5.png" "b/pic/\345\267\245\345\205\267\346\240\210_5.png" old mode 100644 new mode 100755 diff --git "a/pic/\345\267\245\345\205\267\346\240\210_6.png" "b/pic/\345\267\245\345\205\267\346\240\210_6.png" old mode 100644 new mode 100755 diff --git "a/pic/\345\267\245\345\205\267\346\240\210_7.png" "b/pic/\345\267\245\345\205\267\346\240\210_7.png" old mode 100644 new mode 100755 diff --git "a/pic/\346\225\260\346\215\256\345\272\223_1.jpg" "b/pic/\346\225\260\346\215\256\345\272\223_1.jpg" old mode 100644 new mode 100755 diff --git "a/pic/\346\225\260\346\215\256\345\272\223_2ACID.png" "b/pic/\346\225\260\346\215\256\345\272\223_2ACID.png" new file mode 100755 index 0000000..24709c8 Binary files /dev/null and "b/pic/\346\225\260\346\215\256\345\272\223_2ACID.png" differ diff --git "a/pic/\346\225\260\346\215\256\345\272\223_3\351\232\224\347\246\273\347\255\211\347\272\247.png" "b/pic/\346\225\260\346\215\256\345\272\223_3\351\232\224\347\246\273\347\255\211\347\272\247.png" new file mode 100755 index 0000000..d14dc0b Binary files /dev/null and "b/pic/\346\225\260\346\215\256\345\272\223_3\351\232\224\347\246\273\347\255\211\347\272\247.png" differ diff --git "a/pic/\346\225\260\346\215\256\345\272\223\347\264\242\345\274\225_1.jpg" "b/pic/\346\225\260\346\215\256\345\272\223\347\264\242\345\274\225_1.jpg" new file mode 100755 index 0000000..22e2677 Binary files /dev/null and "b/pic/\346\225\260\346\215\256\345\272\223\347\264\242\345\274\225_1.jpg" differ diff --git "a/pic/\347\263\273\347\273\237\350\256\276\350\256\2411.png" "b/pic/\347\263\273\347\273\237\350\256\276\350\256\2411.png" new file mode 100755 index 0000000..19fdbfc Binary files /dev/null and "b/pic/\347\263\273\347\273\237\350\256\276\350\256\2411.png" differ