tiany7带我搞RPC

目前需要学习的东西有四个:git、bazel、mobaxterm、protocol-buffer。

详解varint编码原理

protobuf+RPC技术

笔记区

日志

除了基础调用信息,日志打印的是函数的执行情况,比如在哪个文件的哪个函数的某一个地方变量的值是多少。

就跟算法竞赛debug差不多,放个cout看看输出正不正常,然后注释掉。

linux常用命令

想找文件的关键词就$cat 文件| grep 关键词打印出现关键词的行,统计出现多少次就在后面加| wc -l,不想查找某一个关键词就grep -v显示不包含匹配文本的所有行。

git简单使用手册

表格说明

基本操作

行为 命令 备注
初始化 init 在本地的当前目录里初始化git仓库。
clone git地址 从git地址拷贝仓库到本地。
查看当前状态 status 查看当前仓库的状态。
查看不同 diff 查看当前状态和最新的commit之间不同的地方
添加文件 add -A
提交 commit -m “提交信息” 提交信息要能体现改了什么
查看提交记录 log 查看当前版本及之前的commit记录
版本回退 reset –hard 版本号 回退到指定版本号的版本,该版本之后的修改都被删除。同时也是通过这个命令回到最新版本。需要reflog配合

使用 SSH 连接到github

插图小说

关联远程库:$ git remote add origin git@server-name:path/repo-name.git。习惯命名为origin

从远程库克隆:$ git clone git库地址

在这里插入图片描述

查看远程库信息:$ git remote -v

在这里插入图片描述

根据名字解绑远程库:$ git remote rm origin

查看所有分支:$ git branch -a

从远程仓库同步:$ git pull origin main --allow-unrelated-histories

在这里插入图片描述

将本地分支推送到主干:$ git push -u origin masterpush前记得add -A并且commit

在这里插入图片描述

日志工具

要求对所有打印对象都有插入操作定义,用于输出基本类型数据,已经实现了对部分STL的定义。

C++箴言:理解typename的两个含义 nested dependent name(嵌套依赖名字) - dzqdevin - 博客园 (cnblogs.com)

modifyArgLog类

将当前要输出的对象模板引用绑定到ref上,并且从namelist取出当前对象的名字。

重载<<运算符,输出对象名称及其本身。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
template<typename T>
class modifyArgLog
{
public:
modifyArgLog(T const& r, vector<string> &nameList) : ref(r)
{
name = nameList[0];
nameList.erase(nameList.begin());
}
friend ostream& operator<< (ostream & os, const modifyArgLog<T> &s) {
if (s.name.find('\"') != string::npos)
return os <<s.name<<", ";
return os << s.name << " = " << s.ref <<", ";
}
private:
T const& ref;
string name;
};

testLog函数

dir:文件的名字,通过__FILE__得到

func:调用的函数名,通过__FUNCTION__得到

lineno:函数所在行数,通过__LINE__得到

name:一整个string形式的参数列表

Args && … args:使用宏替换获得的多个参数,每一个都是通用引用,可以绑定任何东西

本身打印调用信息,并且分解参数名到vector,运用左折叠逐个打印参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
template<typename ...Args>
void testLog(stringstream & os, const char* dir, const char* func, int lineno, string name, Args && ...args)
{
os<< dir<<":"<< func <<"()" << " at row " << lineno << ": ";

// name是XLOG参数的string形式
// 运用正则表达式将传入的变长参数名解析分割到vector中
regex re { "\\s{0,},\\s{0,}" };
vector<string> nameList = vector<string> {
sregex_token_iterator(name.begin(), name.end(), re, -1), sregex_token_iterator() };

// 运用折叠表达式将变长参数输出
(os << ... << modifyArgLog(args, nameList)) << endl;
}

工具包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
class util_methods{
public:
string GetLogFileName(){
time_t timep;
struct tm *p;
time(&timep);
p = localtime(&timep);
string iFileName = to_string(1900 + p->tm_year) + (to_string(1+ p->tm_mon).length() > 1 ? to_string(1+ p->tm_mon) : "0" + to_string(1+ p->tm_mon));
iFileName += ((to_string((p->tm_mday)).length() > 1) ? to_string(p->tm_mday) : ("0" + to_string(p->tm_mday)));
iFileName += ((to_string((p->tm_hour - 2 - 3 + 24) % 24).length() > 1) ? to_string((p->tm_hour - 2 - 3 + 24) % 24) : ("0" + to_string((p->tm_hour - 2 - 3 + 24) % 24)));
return "log" + iFileName + ".txt";
};


string GetTimeMs(){
string defaultTime = "19700101000000000";
try
{
struct timeval curTime;
gettimeofday(&curTime, NULL);
int milli = curTime.tv_usec / 1000;

char buffer[80] = {0};
struct tm nowTime;//linux获取系统时间
//localtime_r(&curTime.tv_sec, &nowTime);//把得到的值存入临时分配的内存中,线程安全
localtime_s(&nowTime,(const time_t*)&curTime.tv_sec);//win下
nowTime.tm_hour += 24 - 5;
nowTime.tm_hour %= 24; // 做时区转换用
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S:", &nowTime);

char currentTime[84] = {0};
snprintf(currentTime, sizeof(currentTime), "%s%03d", buffer, milli);

return currentTime;
}
catch(const std::exception& e)
{
return defaultTime;
}
catch (...)
{
return defaultTime;
}

};
void executeCMD(const char *cmd, char *result)
{
char buf_ps[20];
char ps[20] = {0};
FILE *ptr;
strcpy(ps, cmd);
if((ptr = popen(ps, "r")) != NULL)
{
while(fgets(buf_ps, 20, ptr)!=NULL)
{
strcat(result, buf_ps);
break;
}
pclose(ptr);
ptr = nullptr;
return;
}
else
{
printf("popen %s error\n", ps);
}
};
// void executeWrite(const char *cmd)
// {
// char ps[30] = {0};
// FILE *ptr;
// strcpy(ps, cmd);
// assert((ptr=popen(ps, "w")) != NULL);
// };
};

XLOG函数

args...代表可变参数宏,#args为变量名,##args为变量。

为了可以省略参数,使用”##”对token进行连接,如果可变参数被忽略或为空,“##”操作将使预处理器去除掉它前面的那个逗号,避免报错。

do {…}while(0) 防止宏展开后,代码出问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#define XLOG( args...) do{ \
auto res = system("sudo find /home/ubuntu/Cloud-Computing/log/error/*.txt | wc -l"); \
int num = atoi(to_string(res).c_str()); \
if (num > 20){ \
string cmd; \
cmd += "find /home/ubuntu/Cloud-Computing/log/error/ -name '*.txt' | xargs tar -zcvf ";\
cmd += util_methods().GetLogFileName().substr(3, 10) + ".tar.gz"; \
system(cmd.c_str()); \
system("mv *tar.gz /home/ubuntu/Cloud-Computing/log/error/"); \
system("rm -fr /home/ubuntu/Cloud-Computing/log/error/*.txt"); \
} \
stringstream str; \
str<<util_methods().GetTimeMs()<<" "; \
str<<std::this_thread::get_id()<<" "<<"\033[1m\033[32m"; \
str<<"XLOG "; \
testLog(str, __FILE__, __func__,__LINE__ , #args, ##args); \
ofstream outfile; \
std::string oFileName = ("/home/ubuntu/Cloud-Computing/log/error/"+ util_methods().GetLogFileName()); \
outfile.open(oFileName.c_str(), ios_base::app); \
str<<"\033[0m;"; \
outfile<<str.str(); \
outfile.close();\
}while(0)

整体代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270

#include <bits/stdc++.h>

#include <sys/time.h>
#include <stdlib.h>
#ifndef TESTENV_FASTLOG_H
#define TESTENV_FASTLOG_H

using namespace std;

template<typename T>
class modifyArgLog
{
public:
modifyArgLog(T const& r, vector<string> &nameList) : ref(r)
{
name = nameList[0];
nameList.erase(nameList.begin());
}

friend ostream& operator<< (ostream & os, const modifyArgLog<T> &s) {
if (s.name.find('\"') != string::npos)
return os <<s.name<<", ";
return os << s.name << " = " << s.ref <<", ";
}
private:
T const& ref;
string name;
};

template<typename ...Args>
void testLog(stringstream & os, const char* dir, const char* func, int lineno, string name, Args && ...args)
{
os<< dir<<":"<< func <<"()" << " at row " << lineno << ": ";

// name是XLOG参数的string形式
// 运用正则表达式将传入的变长参数名解析分割到vector中
regex re { "\\s{0,},\\s{0,}" };
vector<string> nameList = vector<string> {
sregex_token_iterator(name.begin(), name.end(), re, -1), sregex_token_iterator() };

// 运用折叠表达式将变长参数输出
(os << ... << modifyArgLog(args, nameList)) << endl;
}
template <typename T>
std::ostream & operator <<(std::ostream &os,
const std::map<std::string, T> &m)
{
os<<"{";
for (const auto &p : m)
{
os << p.first << ": ";
for (auto x : p.second) os << x << ' ';
os << std::endl;
}
os<<"}";
return os;
}

template < typename F, typename S >
ostream& operator << ( ostream& os, const pair< F, S > & p ) {
return os << "(" << p.first << ", " << p.second << ")";
}

template < typename T >
ostream &operator << ( ostream & os, const vector< T > &v ) {
os << "{";
typename vector< T > :: const_iterator it;
for( it = v.begin(); it != v.end(); it++ ) {
if( it != v.begin() ) os << ", ";
os << *it;
}
return os << "}";
}

template < typename T >
ostream &operator << ( ostream & os, const set< T > &v ) {
os << "[";
typename set< T > :: const_iterator it;
for ( it = v.begin(); it != v.end(); it++ ) {
if( it != v.begin() ) os << ", ";
os << *it;
}
return os << "]";
}

template < typename F, typename S >
ostream &operator << ( ostream & os, const map< F, S > &v ) {
os << "[";
typename map< F , S >::const_iterator it;
for( it = v.begin(); it != v.end(); it++ ) {
if( it != v.begin() ) os << ", ";
os << "<"<<it -> first << " , " << it -> second<<">" ;
}
return os << "]";
}
class util_methods{
public:
string GetLogFileName(){
time_t timep;
struct tm *p;
time(&timep);
p = localtime(&timep);
string iFileName = to_string(1900 + p->tm_year) + (to_string(1+ p->tm_mon).length() > 1 ? to_string(1+ p->tm_mon) : "0" + to_string(1+ p->tm_mon));
iFileName += ((to_string((p->tm_mday)).length() > 1) ? to_string(p->tm_mday) : ("0" + to_string(p->tm_mday)));
iFileName += ((to_string((p->tm_hour - 2 - 3 + 24) % 24).length() > 1) ? to_string((p->tm_hour - 2 - 3 + 24) % 24) : ("0" + to_string((p->tm_hour - 2 - 3 + 24) % 24)));
return "log" + iFileName + ".txt";
};


string GetTimeMs(){
string defaultTime = "19700101000000000";
try
{
struct timeval curTime;
gettimeofday(&curTime, NULL);
int milli = curTime.tv_usec / 1000;

char buffer[80] = {0};
struct tm nowTime;
localtime_r(&curTime.tv_sec, &nowTime);//把得到的值存入临时分配的内存中,线程安全
nowTime.tm_hour += 24 - 5;
nowTime.tm_hour %= 24; // 做时区转换用
strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S:", &nowTime);

char currentTime[84] = {0};
snprintf(currentTime, sizeof(currentTime), "%s%03d", buffer, milli);

return currentTime;
}
catch(const std::exception& e)
{
return defaultTime;
}
catch (...)
{
return defaultTime;
}

};
void executeCMD(const char *cmd, char *result)
{
char buf_ps[20];
char ps[20] = {0};
FILE *ptr;
strcpy(ps, cmd);
if((ptr = popen(ps, "r")) != NULL)
{
while(fgets(buf_ps, 20, ptr)!=NULL)
{
strcat(result, buf_ps);
break;
}
pclose(ptr);
ptr = nullptr;
return;
}
else
{
printf("popen %s error\n", ps);
}
};
// void executeWrite(const char *cmd)
// {
// char ps[30] = {0};
// FILE *ptr;
// strcpy(ps, cmd);
// assert((ptr=popen(ps, "w")) != NULL);
// };
};
// 编译器定义的一个局部静态变量,用于存放函数的名字
// __FUNCTION__ :函数名
// __TIME__ :文件运行的时间
// __LINE__ :所在行数
// __FILE__:文件的名字
// XLOG可以在函数中快速打印变量的值,方便定位信息
// #args为变量名
// 如果可变参数被忽略或为空,“##”操作将使预处理器去除掉它前面的那个逗号,避免报错
#define XLOG( args...) do{ \
auto res = system("sudo find /home/ubuntu/Cloud-Computing/log/error/*.txt | wc -l"); \
int num = atoi(to_string(res).c_str()); \
if (num > 20){ \
string cmd; \
cmd += "find /home/ubuntu/Cloud-Computing/log/error/ -name '*.txt' | xargs tar -zcvf ";\
cmd += util_methods().GetLogFileName().substr(3, 10) + ".tar.gz"; \
system(cmd.c_str()); \
system("mv *tar.gz /home/ubuntu/Cloud-Computing/log/error/"); \
system("rm -fr /home/ubuntu/Cloud-Computing/log/error/*.txt"); \
} \
stringstream str; \
str<<util_methods().GetTimeMs()<<" "; \
str<<std::this_thread::get_id()<<" "<<"\033[1m\033[32m"; \
str<<"XLOG "; \
testLog(str, __FILE__, __func__,__LINE__ , #args, ##args); \
ofstream outfile; \
std::string oFileName = ("/home/ubuntu/Cloud-Computing/log/error/"+ util_methods().GetLogFileName()); \
outfile.open(oFileName.c_str(), ios_base::app); \
str<<"\033[0m;"; \
outfile<<str.str(); \
outfile.close();\
}while(0)
#define XLOG_ERR( args...) do{ \
auto res = system("sudo find /home/ubuntu/Cloud-Computing/log/error/*.txt | wc -l"); \
int num = atoi(to_string(res).c_str()); \
if (num > 20){ \
string cmd; \
cmd += "find /home/ubuntu/Cloud-Computing/log/error/ -name '*.txt' | xargs tar -zcvf ";\
cmd += util_methods().GetLogFileName().substr(3, 10) + ".tar.gz"; \
system(cmd.c_str()); \
system("mv *tar.gz /home/ubuntu/Cloud-Computing/log/error/"); \
system("rm -fr /home/ubuntu/Cloud-Computing/log/error/*.txt"); \
} \
stringstream str; \
str<<util_methods().GetTimeMs()<<" "; \
str<<std::this_thread::get_id()<<" "<<"\033[31m"; \
str<<"XLOG_ERR "; \
testLog(str, __FILE__, __func__,__LINE__ , #args, ##args); \
ofstream outfile; \
std::string oFileName = ("/home/ubuntu/Cloud-Computing/log/error/"+ util_methods().GetLogFileName()); \
outfile.open(oFileName.c_str(), ios_base::app); \
str<<"\033[0m;"; \
outfile<<str.str(); \
outfile.close();\
}while(0)
#define LOG( args...) do{ \
auto res = system("sudo find /home/ubuntu/Cloud-Computing/log/error/*.txt | wc -l"); \
int num = atoi(to_string(res).c_str()); \
if (num > 20){ \
string cmd; \
cmd += "find /home/ubuntu/Cloud-Computing/log/error/ -name '*.txt' | xargs tar -zcvf ";\
cmd += util_methods().GetLogFileName().substr(3, 10) + ".tar.gz"; \
system(cmd.c_str()); \
system("mv *tar.gz /home/ubuntu/Cloud-Computing/log/error/"); \
system("rm -fr /home/ubuntu/Cloud-Computing/log/error/*.txt"); \
} \
stringstream str; \
str<<util_methods().GetTimeMs()<<" "; \
str<<std::this_thread::get_id()<<" "; \
str<<"LOG "; \
testLog(str, __FILE__, __func__,__LINE__ , #args, ##args); \
ofstream outfile; \
std::string oFileName = ("/home/ubuntu/Cloud-Computing/log/error/"+ util_methods().GetLogFileName()); \
outfile.open(oFileName.c_str(), ios_base::app); \
outfile<<str.str(); \
outfile.close();\
}while(0)
#define XLOG_LER( args...) do{ \
auto res = system("sudo find /home/ubuntu/Cloud-Computing/log/error/*.txt | wc -l"); \
int num = atoi(to_string(res).c_str()); \
if (num > 20){ \
string cmd; \
cmd += "find /home/ubuntu/Cloud-Computing/log/error/ -name '*.txt' | xargs tar -zcvf ";\
cmd += util_methods().GetLogFileName().substr(3, 10) + ".tar.gz"; \
system(cmd.c_str()); \
system("mv *tar.gz /home/ubuntu/Cloud-Computing/log/error/"); \
system("rm -fr /home/ubuntu/Cloud-Computing/log/error/*.txt"); \
} \
stringstream str; \
str<<util_methods().GetTimeMs()<<" "; \
str<<std::this_thread::get_id()<<" "<<"\033[1m\033[33m"; \
str<<"XLOG_LER "; \
testLog(str, __FILE__, __func__,__LINE__ , #args, ##args); \
ofstream outfile; \
std::string oFileName = ("/home/ubuntu/Cloud-Computing/log/error/"+ util_methods().GetLogFileName()); \
outfile.open(oFileName.c_str(), ios_base::app); \
str<<"\033[0m;"; \
outfile<<str.str(); \
outfile.close();\
}while(0)
#endif //TESTENV_FASTLOG_H