├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── api ├── CacheLayer.md ├── README.md ├── cpp │ ├── elbApi │ │ ├── Makefile │ │ ├── StaticRoute.h │ │ ├── cacheLayer.cc │ │ ├── cacheLayer.h │ │ ├── elbApi.cc │ │ └── elbApi.h │ └── example │ │ ├── Makefile │ │ ├── example.cc │ │ ├── qpstest.cc │ │ ├── simulator.cc │ │ ├── testcache.cc │ │ └── timotest.cc ├── java │ └── NOTEMPTY └── python │ ├── elbApi │ ├── CacheLayer.py │ ├── Makefile │ ├── StaticRoute.py │ ├── __init__.py │ ├── elbClient.py │ └── elb_pb2.py │ ├── example.py │ ├── testcache.py │ └── timotest.py ├── common ├── base │ ├── include │ │ ├── Singleton.h │ │ ├── log.h │ │ ├── logo.h │ │ └── util.h │ └── src │ │ └── log.cc ├── mysql-connector-c │ ├── include │ │ ├── big_endian.h │ │ ├── binary_log_types.h │ │ ├── byte_order_generic.h │ │ ├── byte_order_generic_x86.h │ │ ├── decimal.h │ │ ├── errmsg.h │ │ ├── keycache.h │ │ ├── little_endian.h │ │ ├── m_ctype.h │ │ ├── m_string.h │ │ ├── my_alloc.h │ │ ├── my_byteorder.h │ │ ├── my_command.h │ │ ├── my_compiler.h │ │ ├── my_config.h │ │ ├── my_dbug.h │ │ ├── my_dir.h │ │ ├── my_getopt.h │ │ ├── my_global.h │ │ ├── my_list.h │ │ ├── my_sys.h │ │ ├── my_thread.h │ │ ├── my_thread_local.h │ │ ├── my_xml.h │ │ ├── mysql.h │ │ ├── mysql │ │ │ ├── client_authentication.h │ │ │ ├── client_plugin.h │ │ │ ├── client_plugin.h.pp │ │ │ ├── get_password.h │ │ │ ├── mysql_lex_string.h │ │ │ ├── plugin_auth_common.h │ │ │ ├── plugin_trace.h │ │ │ ├── psi │ │ │ │ ├── mysql_file.h │ │ │ │ ├── mysql_idle.h │ │ │ │ ├── mysql_mdl.h │ │ │ │ ├── mysql_memory.h │ │ │ │ ├── mysql_ps.h │ │ │ │ ├── mysql_socket.h │ │ │ │ ├── mysql_sp.h │ │ │ │ ├── mysql_stage.h │ │ │ │ ├── mysql_statement.h │ │ │ │ ├── mysql_table.h │ │ │ │ ├── mysql_thread.h │ │ │ │ ├── mysql_transaction.h │ │ │ │ ├── psi.h │ │ │ │ ├── psi_base.h │ │ │ │ └── psi_memory.h │ │ │ ├── service_my_snprintf.h │ │ │ └── service_mysql_alloc.h │ │ ├── mysql_com.h │ │ ├── mysql_com_server.h │ │ ├── mysql_embed.h │ │ ├── mysql_time.h │ │ ├── mysql_version.h │ │ ├── mysqld_ername.h │ │ ├── mysqld_error.h │ │ ├── sql_common.h │ │ ├── sql_state.h │ │ ├── sslopt-case.h │ │ ├── sslopt-longopts.h │ │ ├── sslopt-vars.h │ │ ├── thr_cond.h │ │ ├── thr_mutex.h │ │ ├── thr_rwlock.h │ │ └── typelib.h │ └── lib │ │ ├── libmysqlclient.a │ │ ├── libmysqlclient.so │ │ ├── libmysqlclient.so.18 │ │ └── libmysqlclient.so.18.4. ├── proto │ ├── Makefile │ ├── elb.pb.cc │ ├── elb.pb.h │ └── elb.proto ├── protobuf │ └── lib │ │ └── libprotobuf.a └── sql │ └── dnsserver.sql ├── dnsserver ├── Makefile ├── README.md ├── conf │ └── dnsserver.ini ├── include │ ├── Route.h │ ├── Server.h │ └── SubscribeList.h ├── pictures │ └── DnsServer-Arch.png ├── src │ ├── Route.cc │ ├── Server.cc │ └── SubscribeList.cc └── test │ ├── Makefile │ └── benchmark.cc ├── lbagent ├── Makefile ├── Optimization-log.md ├── README.md ├── conf │ └── lbagent.ini ├── include │ ├── HeartBeat.h │ ├── RouteLb.h │ └── Server.h ├── pictures │ ├── LB.png │ └── Lbagent-Arch.png ├── src │ ├── AgentServer.cc │ ├── DssClient.cc │ ├── RouteLb.cc │ ├── RptClient.cc │ └── Server.cc └── tool │ ├── Makefile │ ├── getroute │ └── getroute.cc ├── mod-manager └── ModOperator.py ├── pictures └── arch.png └── reporter ├── Makefile ├── README.md ├── conf └── reporter.ini ├── include ├── CallStatis.h └── Server.h ├── pictures └── Reporter-Arch.png ├── src ├── CallStatis.cc └── Server.cc └── test ├── Makefile └── rptClient.cc /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.a 3 | *.d 4 | *.prog 5 | *.pyc 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "common/Easy-Reactor"] 2 | path = common/Easy-Reactor 3 | url = https://github.com/LeechanX/Easy-Reactor.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 leechanx 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Easy Load Balancer 2 | 3 | ELB(Easy Load Balance)是一个简单、易用、高性能的服务间远程调用管理、调度、负载系统 4 | 5 | 此系统的闭源版本已经在我司300+台服务器、2000+个远程服务上自2017年4月稳定运行至今 6 | 7 | **PS:** 本系统各组件的网络框架直接采用了我做的另一个项目:[高性能C++多线程Reactor网络服务框架:Easy-Reactor][1],以顺便检验Easy-Reactor项目的性能和可用性。ELB系统开发完成后,事实证明系统性能还是很好的:-D (如:组件LB Agent QPS `50+W/s`,组件dnsserver QPS 3线程时`25+W/s`、5线程时`39+W/s`,具体各组件的性能测试见各组件的README) 8 | 9 | [1]: https://github.com/LeechanX/Easy-Reactor 10 | 11 | ### 介绍 12 | 13 | 对于一个部门的后台,为增强灵活性,一个服务可以被抽象为命令字:`modid+cmdid`的组合,称为**一个模块**,而这个服务往往有多个服务节点,其所有服务节点的地址集合被称为这个模块下的**路由**,节点地址简称为节点 14 | 15 | - `modid`:标识业务的大类,如:“直播列表相关” 16 | - `cmdid`:标识具体服务内容,如:“批量获取直播列表” 17 | 18 | 业务代码利用modid,cmdid,就可以调用对应的远程服务 19 | 20 | 一个ELB系统包含一个dnsserver,一个reporter,以及部署于每个服务器的Lbagent,业务代码通过API与ELB系统进行交互 21 | 22 | **API** :根据自身需要的`modid,cmdid`,向ELB系统获取节点、汇报节点调用结果;提供`C++`、`Java`、`Python`接口 23 | 24 | **LB agent**:运行于每个服务器上,负责为此服务器上的业务提供节点获取、节点状态汇报、路由管理、负载调度等核心功能 25 | 26 | **dnsserver** : 运行于一台服务器上(也可以用LVS部署多实例防单点),负责`modid,cmdid`到节点路由的转换 27 | 28 | **reporter** : 运行于dnsserver同机服务器上,负责收集各`modid,cmdid`下各节点调用状况,可用于观察、报警 29 | 30 | `modid,cmdid`数据由`Mysql`管理,具体SQL脚本在`common/sql`路径下 31 | 至于`modid,cmdid`的注册、删除可以利用Web端操作MySQL(但由于个人能力有限,Web没有写) 32 | 33 | 34 | ### 总体架构 35 | 36 | ![arch](pictures/arch.png) 37 | 如图,每个服务器(虚线)部署了一台LB Agent,以及多个业务服务 38 | 39 | 1. 开发者在Web端注册、删除、修改`modid,cmdid`的路由信息,信息被写入到MySQL数据库; 40 | 2. 服务器上每个业务biz都把持着自己需要通信的远程服务标识`modid+cmdid`,每个biz都向本机LB Agent获取远程节点,进而可以和远程目标服务通信,此外biz会汇报本次的节点调用结果给LB Agent; 41 | 3. LB Agent负责路由管理、负载均衡等核心任务,并周期性向dnsserver获取最新的路由信息,周期性把各`modid,cmdid`的各节点一段时间内的调用结果传给reporter 42 | 4. dnsserver监控MySQL,周期性将最新路由信息加载出来; 43 | 5. reporter将各`modid,cmdid`的各节点一段时间内的调用结果写回到MySQL,方便Web端查看、报警 44 | 45 | 46 | ### 各组件架构原理介绍 47 | **DNS Server: [dnsserver readme][2]** 48 | 49 | [2]: https://github.com/LeechanX/Easy-Load-Balancer/blob/master/dnsserver/README.md 50 | 51 | **LB Agent(含过载发现、调度等负载均衡算法内容介绍): [lb agent readme][3]** 52 | 53 | [3]: https://github.com/LeechanX/Easy-Load-Balancer/blob/master/lbagent/README.md 54 | 55 | **Reporter: [reporter readme][4]** 56 | 57 | [4]: https://github.com/LeechanX/Easy-Load-Balancer/blob/master/reporter/README.md 58 | 59 | **API: [API readme][5]** 60 | 61 | [5]: https://github.com/LeechanX/Easy-Load-Balancer/blob/master/api/README.md 62 | 63 | **API缓存层: [cache readme][6]** 64 | 65 | [6]: https://github.com/LeechanX/Easy-Load-Balancer/blob/master/api/CacheLayer.md 66 | 67 | ### TODO 68 | 69 | - LB算法对节的异构性考虑不够细致,值得优化 70 | - 增加更多语言API 71 | -------------------------------------------------------------------------------- /api/CacheLayer.md: -------------------------------------------------------------------------------- 1 | ## API Cache Layer 2 | 3 | 使用ELB发现,某台业务较多的线上服务器有时会抖动,于是有少量时刻会造成业务获取节点超时,为解决此问题,提出在业务端增加缓存层 4 | 5 | 除了解决问题外,提供缓存层还基于一个考量: 6 | >在模块节点都正常时(无过载),业务没有必要每次远程调用时候都特地向lbagent获取节点,而可先把模块路由缓存,自主轮询,如此还可以节省大量的QPS lbagent消耗 7 | 8 | 于是,缓存层设计的大思路就是: 9 | 对于某mod,如果其下路由无节点过载,优先走缓存;如有节点过载,则仍走原来的方式:本地网络 10 | 11 | ### 协议支持 12 | 13 | //为支持API cache: api向agent发起获取\更新路由请求 14 | message CacheGetRouteReq { 15 | required int32 modid = 1; 16 | required int32 cmdid = 2; 17 | required int64 version = 3;//首次获取时,version=-1 18 | } 19 | //为支持API cache: agent给api返回的路由应答 20 | message CacheGetRouteRsp { 21 | required int32 modid = 1; 22 | required int32 cmdid = 2; 23 | required int64 version = 3;//agent不存在此mod,则version=-1 24 | optional bool overload = 4; 25 | repeated HostAddr route = 5; 26 | } 27 | //为支持API cache: api向agent批量上报若干成功结果 28 | message CacheBatchRptReq { 29 | required int32 modid = 1; 30 | required int32 cmdid = 2; 31 | repeated HostBatchCallRes results = 3; 32 | } 33 | 34 | ### 带缓存的节点获取流程 35 | 36 | 要对某mod获取节点 37 | 38 | 1、如果此mod不存在于缓存中,则打包`CacheGetRouteReq`请求向lbagent获取路由: 39 | lbagent返回`CacheGetRouteRsp`类型的rsp,如果: 40 | - rsp.version = -1,说明lbagent端无此mod路由,于是返给业务:不存在错误 41 | - 否则添加到本地缓存,包括版本号、路由信息、是否有节点过载等rsp携带的信息,然后走step 3 42 | 43 | 2、如果此mod存在于缓存中,但此mod上次更新时间距今超过2s,则打包`CacheGetRouteReq`请求向lbagent更新路由: 44 | lbagent返回`CacheGetRouteRsp`类型的rsp,如果: 45 | - rsp.version = -1,说明lbagent端此mod路由已删除,于是删除对应缓存,且返给业务:不存在错误 46 | - 否则添加到本地缓存,包括版本号、是否有节点过载等rsp携带的信息,如果`rsp.version!=`本地缓存版本则还要更新路由信息,然后走step 3 47 | 48 | 3、此mod存在于缓存中,但是有节点过载:则走原逻辑:本地网络向lbagent获取节点 49 | 50 | 4、此mod存在于缓存中,且无节点过载,则本地缓存轮询一个节点返给业务 51 | 52 | ### 带缓存的状态上报流程 53 | 54 | 本地缓存永远只暂存调用成功的结果 55 | 56 | 对于待上报条目`modid, cmdid, ip, port, retcode` 57 | - 如果此mod无节点处于过载: 58 | - 如果`retcode = 0`,且此mod无节点处于过载,则暂存到缓存中即可 59 | - 如果`retcode != 0`,将之前缓存的此mod下所有节点调用结果打包成请求`CacheBatchRptReq`批量上报给lbagent;然后将本次调用结果走原来的本地网络方式上报给lbagent 60 | 61 | - 如果此mod有节点处于过载: 62 | - 将本次调用结果走原来的本地网络方式上报给lbagent 63 | 64 | 此外: 65 | - 在mod的节点获取流程中,如果本地缓存时效超时,则先把此mod暂存的调用结果先批量上报给lbagent,然后才发起更新路由请求`CacheGetRouteReq` 66 | - 在业务退出时,ELB客户端析构函数中会把缓存中每个mod暂存的调用结果批量上报给lbagent 67 | 68 | **“暂存0、立即发非0”** 的方式,可以保证两种调用结果(0、非0)的产生顺序不被缓存逻辑打乱,不影响lbagent的LB算法的过载发现、恢复逻辑; 69 | 而如果将无论0、非0调用结果都暂存到缓存,则无法高效地记录下这些调用结果的先后顺序(如100个0,50个非0,要准确记录这150个调用结果的产生顺序需要150长度的数组) 70 | 71 | >**调用结果顺序如何影响lbagent的LB算法过载发现、恢复逻辑?** 72 | > 73 | >假设节点H产生的调用结果是100个0+50个1, 74 | > 75 | >如果产生顺序是先50个非0,而后100个1,则lbagent会在连续15个1后判断H过载;又在连续15个0后判断H恢复 76 | > 77 | >如果产生的顺序是0101010101010......,则lbagent可能一直不认为H过载; 78 | > 79 | >于是说:调用结果顺序将影响lbagent的LB算法 80 | 81 | ### 评估 82 | 83 | 优点: 84 | - 1、节约agent QPS,提高了业务调用ELB的响应能力; 85 | - 2、不影响LB算法的过载发现、恢复逻辑 86 | 87 | 缺点: 88 | - 暂未发现 89 | -------------------------------------------------------------------------------- /api/README.md: -------------------------------------------------------------------------------- 1 | ## API Presentation 2 | 3 | 具体使用见api/[cpp\python]/路径下的example代码 4 | 5 | 依赖: 6 | CPP: 7 | 8 | #include "elbApi.h" 9 | 10 | Python: 11 | 12 | from elbApi.elbClient import elbClient 13 | 14 | ### 1、创建API对象 15 | CPP: 16 | 17 | elbClient client; 18 | Python: 19 | 20 | client = elbClient() 21 | 22 | 23 | ### 2、节点获取 24 | #### CPP: 25 | 26 | int apiGetHost(int modid, int cmdid, int timo, std::string& ip, int& port) 27 | 28 | 参数: 29 | modid + cmdid:模块标识 30 | time:获取节点的超时时间,毫秒 31 | ip,port:作为返回内容 32 | 33 | 返回值: 34 | 0表示获取成功; 35 | -10000表示此模块过载; 36 | -9998表示模块不存在;首次获取某模块时,由于lbagent尚未有此模块路由,一定会返回此错误 37 | -9999:其他系统错误 38 | 39 | #### Python: 40 | 41 | client.apiGetHost(modid, cmdid, timo) 42 | 43 | 参数: 44 | modid + cmdid:模块标识 45 | time:获取节点的超时时间,毫秒 46 | 47 | 返回值:Tuple类型:(retcode, hostOrErrmsg) 48 | 49 | retcode同CPP返回值, 50 | hostOrErrmsg:当retcode=0,是一个ip,port;否则是错误字符串 51 | 52 | 53 | ### 3、节点调用结果汇报 54 | #### CPP: 55 | 56 | void apiReportRes(int modid, int cmdid, const std::string& ip, int port, int retcode); 57 | #### Python: 58 | 59 | client.apiReportRes(modid, cmdid, ip, port, retcode) 60 | 61 | ### 4、(可选)预取路由 62 | 63 | 如果不想第一次模块获取节点返回不存在错误,可以预先调用`apiRegister`,用于事先要求lb agent拉取某模块 64 | 65 | #### CPP: 66 | 67 | int elbClient::apiRegister(int modid, int cmdid); 68 | 69 | 返回值: 70 | 0表示lbagent已成功拉取到此模块;-9998表示此模块确实不存在 71 | 72 | #### Python: 73 | 74 | client.apiRegister(modid, cmdid) 75 | 返回值:同上 76 | -------------------------------------------------------------------------------- /api/cpp/elbApi/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = ../lib/libelbapi.a 2 | CXX = g++ 3 | CFLAGS = -g -O2 -Wall 4 | 5 | COMMON = ../../../common 6 | BASE = $(COMMON)/base 7 | BASE_H = $(BASE)/include 8 | PROTOBUF = $(COMMON)/protobuf 9 | PROTOBUF_LIB = $(PROTOBUF)/lib -lprotobuf 10 | OTHER_LIB = -lpthread -ldl 11 | EASYREACTOR = $(COMMON)/Easy-Reactor 12 | EASYREACTOR_H = $(EASYREACTOR)/include 13 | EASYREACTOR_LIB = $(EASYREACTOR)/lib -lereactor -lrt 14 | AGENT_H=../../../lbagent/include 15 | 16 | PROTO_H = $(COMMON)/proto 17 | 18 | INC = -Iinclude -I$(BASE_H) -I$(EASYREACTOR_H) -I$(PROTO_H) -I$(AGENT_H) 19 | LIB = -L$(PROTOBUF_LIB) -L$(EASYREACTOR_LIB) $(OTHER_LIB) 20 | 21 | OBJS = $(addsuffix .o, $(basename $(wildcard *.cc))) 22 | OBJS += $(PROTO_H)/elb.pb.o $(BASE)/src/log.o 23 | 24 | $(TARGET): $(OBJS) 25 | -mkdir -p ../lib 26 | ar cqs $@ $^ 27 | 28 | -include $(OBJS:.o=.d) 29 | 30 | %.o: %.cc 31 | $(CXX) $(CFLAGS) -c -o $@ $< $(INC) 32 | @$(CXX) -MM $*.cc $(INC) > $*.d 33 | @mv -f $*.d $*.d.tmp 34 | @sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d 35 | @sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \ 36 | sed -e 's/^ *//' -e 's/$$/:/' >> $*.d 37 | @rm -f $*.d.tmp 38 | 39 | .PHONY: clean 40 | 41 | clean: 42 | -rm -f $(OBJS) *.d $(PROTO_H)/elb.pb.d $(BASE)/src/log.d $(TARGET) 43 | -------------------------------------------------------------------------------- /api/cpp/elbApi/StaticRoute.h: -------------------------------------------------------------------------------- 1 | #ifndef __STATICROUTE_H__ 2 | #define __STATICROUTE_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class StaticRoute 14 | { 15 | public: 16 | StaticRoute() 17 | { 18 | srand(time(NULL)); 19 | } 20 | int getHost(int modid, int cmdid, std::string& ip, int& port) 21 | { 22 | if (_route.empty()) 23 | { 24 | FILE* fp = fopen("/tmp/backupRoute.dat.1", "r"); 25 | if (fp) 26 | { 27 | int imodid, icmdid, iip, iport; 28 | while (fscanf(fp, "%d %d %d %d", &imodid, &icmdid, &iip, &iport) != EOF) 29 | { 30 | uint64_t key = ((uint64_t)imodid << 32) + icmdid; 31 | struct in_addr saddr; 32 | saddr.s_addr = iip; 33 | std::string sip = inet_ntoa(saddr); 34 | hostType host(sip, iport); 35 | _route[key].push_back(host); 36 | } 37 | fclose(fp); 38 | } 39 | fp = fopen("/tmp/backupRoute.dat.2", "r"); 40 | if (fp) 41 | { 42 | int imodid, icmdid, iip, iport; 43 | while (fscanf(fp, "%d %d %d %d", &imodid, &icmdid, &iip, &iport) != EOF) 44 | { 45 | uint64_t key = ((uint64_t)imodid << 32) + icmdid; 46 | struct in_addr saddr; 47 | saddr.s_addr = iip; 48 | std::string sip = inet_ntoa(saddr); 49 | hostType host(sip, iport); 50 | _route[key].push_back(host); 51 | } 52 | fclose(fp); 53 | } 54 | fp = fopen("/tmp/backupRoute.dat.3", "r"); 55 | if (fp) 56 | { 57 | int imodid, icmdid, iip, iport; 58 | while (fscanf(fp, "%d %d %d %d", &imodid, &icmdid, &iip, &iport) != EOF) 59 | { 60 | uint64_t key = ((uint64_t)imodid << 32) + icmdid; 61 | struct in_addr saddr; 62 | saddr.s_addr = iip; 63 | std::string sip = inet_ntoa(saddr); 64 | hostType host(sip, iport); 65 | _route[key].push_back(host); 66 | } 67 | fclose(fp); 68 | } 69 | } 70 | uint64_t key = ((uint64_t)modid << 32) + cmdid; 71 | if (_route.find(key) == _route.end()) 72 | return -1; 73 | int index = rand() % _route[key].size(); 74 | hostType& host = _route[key].at(index); 75 | ip = host.first; 76 | port = host.second; 77 | return 0; 78 | } 79 | 80 | void freeData() { _route.clear(); } 81 | 82 | private: 83 | typedef std::pair hostType; 84 | __gnu_cxx::hash_map > _route; 85 | }; 86 | 87 | #endif 88 | -------------------------------------------------------------------------------- /api/cpp/elbApi/cacheLayer.cc: -------------------------------------------------------------------------------- 1 | #include "cacheLayer.h" 2 | #include 3 | 4 | void CacheUnit::getHost(std::string& ip, int& port) 5 | { 6 | const pair host = nodeList.front(); 7 | port = host.second; 8 | //add to tail 9 | nodeList.pop_front(); 10 | nodeList.push_back(host); 11 | struct in_addr saddr; 12 | saddr.s_addr = host.first; 13 | ip = ::inet_ntoa(saddr); 14 | } 15 | 16 | void CacheUnit::report(int ip, int port) 17 | { 18 | uint64_t key = ((uint64_t)ip << 32) + port; 19 | if (succAccum.find(key) != succAccum.end()) 20 | { 21 | succAccum[key] += 1; 22 | succCnt++; 23 | } 24 | } 25 | 26 | void CacheLayer::getAll(vector& all) 27 | { 28 | hash_map::iterator it; 29 | for (it = _cache.begin();it != _cache.end(); ++it) 30 | all.push_back(it->second); 31 | } 32 | 33 | CacheUnit* CacheLayer::getCache(int modid, int cmdid) 34 | { 35 | uint64_t key = ((uint64_t)modid << 32) + cmdid; 36 | CacheUnit* item = NULL; 37 | if (_cache.find(key) != _cache.end()) 38 | item = _cache[key]; 39 | return item; 40 | } 41 | 42 | void CacheLayer::addCache(int modid, int cmdid, CacheUnit* item) 43 | { 44 | uint64_t key = ((uint64_t)modid << 32) + cmdid; 45 | _cache[key] = item; 46 | } 47 | 48 | void CacheLayer::rmCache(int modid, int cmdid) 49 | { 50 | uint64_t key = ((uint64_t)modid << 32) + cmdid; 51 | CacheUnit* item = NULL; 52 | if (_cache.find(key) != _cache.end()) 53 | item = _cache[key]; 54 | if (item) 55 | delete item; 56 | _cache.erase(key); 57 | } 58 | -------------------------------------------------------------------------------- /api/cpp/elbApi/cacheLayer.h: -------------------------------------------------------------------------------- 1 | #ifndef __CACHELAYER_H__ 2 | #define __CACHELAYER_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using std::pair; 10 | using std::list; 11 | using std::vector; 12 | using std::string; 13 | using __gnu_cxx::hash_map; 14 | 15 | //cache unit 16 | struct CacheUnit 17 | { 18 | CacheUnit() { } 19 | //get host 20 | void getHost(string& ip, int& port); 21 | //report 0 in cache for host[ip:port] 22 | void report(int ip, int port); 23 | 24 | int modid; 25 | int cmdid; 26 | bool overload; 27 | long lstUpdTs; 28 | long version; 29 | uint64_t succCnt; 30 | 31 | list > nodeList; 32 | //key => success accumulator 33 | hash_map succAccum; 34 | }; 35 | 36 | struct CacheLayer 37 | { 38 | public: 39 | CacheUnit* getCache(int modid, int cmdid); 40 | 41 | void addCache(int modid, int cmdid, CacheUnit* item); 42 | 43 | void rmCache(int modid, int cmdid); 44 | 45 | void getAll(vector& all); 46 | 47 | private: 48 | hash_map _cache; 49 | }; 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /api/cpp/elbApi/elbApi.h: -------------------------------------------------------------------------------- 1 | #ifndef __ELBAPI_H__ 2 | #define __ELBAPI_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include "cacheLayer.h" 8 | #include "StaticRoute.h" 9 | 10 | class elbClient 11 | { 12 | public: 13 | elbClient(); 14 | 15 | ~elbClient(); 16 | 17 | int apiGetHost(int modid, int cmdid, int timo, std::string& ip, int& port); 18 | 19 | void apiReportRes(int modid, int cmdid, const std::string& ip, int port, int retcode); 20 | 21 | int apiGetRoute(int modid, int cmdid, std::vector >& route); 22 | 23 | int apiRegister(int modid, int cmdid);//非必需使用的API 24 | 25 | private: 26 | //向agent批量上报某mod 27 | void batchReportRes(CacheUnit* cacheItem); 28 | //向agent获取某mod的路由 29 | int getRoute4Cache(int modid, int cmdid, long ts); 30 | 31 | int _sockfd[3]; 32 | uint32_t _seqid; 33 | void* _hb; 34 | StaticRoute _staticRoute; 35 | bool _agentOff; 36 | CacheLayer _cacheLayer; 37 | uint64_t _tsget;//获取到节点的时间戳,毫秒 38 | }; 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /api/cpp/example/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = example 2 | CXX = g++ 3 | CFLAGS = -g -O2 -Wall 4 | 5 | all: 6 | $(CXX) $(CFLAGS) -o example example.cc -I../elbApi ../lib/libelbapi.a ../../../common/protobuf/lib/libprotobuf.a 7 | $(CXX) $(CFLAGS) -o qpstest qpstest.cc -I../elbApi ../lib/libelbapi.a ../../../common/protobuf/lib/libprotobuf.a -lpthread 8 | $(CXX) $(CFLAGS) -o timotest timotest.cc -I../elbApi ../lib/libelbapi.a ../../../common/protobuf/lib/libprotobuf.a -lpthread 9 | $(CXX) $(CFLAGS) -o simulator simulator.cc -I../elbApi ../lib/libelbapi.a ../../../common/protobuf/lib/libprotobuf.a 10 | clean: 11 | rm -f example qpstest timotest 12 | -------------------------------------------------------------------------------- /api/cpp/example/example.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "elbApi.h" 4 | #include 5 | 6 | int main(int argc, char const *argv[]) 7 | { 8 | int modid = atoi(argv[1]); 9 | int cmdid = atoi(argv[2]); 10 | elbClient client; 11 | std::string ip; 12 | int port; 13 | int ret = client.apiRegister(modid, cmdid);//非必需使用的API 14 | if (ret != 0) 15 | std::cout << "still not exist after register" << std::endl; 16 | 17 | ret = client.apiGetHost(modid, cmdid, 10, ip, port); 18 | if (ret == 0) 19 | { 20 | std::cout << "host is " << ip << ":" << port << std::endl; 21 | client.apiReportRes(modid, cmdid, ip, port, 0); 22 | } 23 | else if (ret == -9998) 24 | { 25 | std::cout << modid << "," << cmdid << " not exist" << std::endl; 26 | } 27 | else 28 | { 29 | std::cout << "get error code " << ret << std::endl; 30 | } 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /api/cpp/example/qpstest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "elbApi.h" 3 | #include 4 | 5 | struct Item 6 | { 7 | int modid; 8 | int cmdid; 9 | }; 10 | 11 | void* mockApi(void* args) 12 | { 13 | Item* item = (Item*)args; 14 | int modid = item->modid, cmdid = item->cmdid; 15 | std::string ip; 16 | int port; 17 | int ret; 18 | long qps = 0; 19 | elbClient client; 20 | long lst = time(NULL); 21 | while (1) 22 | { 23 | ret = client.apiGetHost(modid, cmdid, 10, ip, port); 24 | if (ret == 0 || ret == -9998) 25 | { 26 | ++qps; 27 | if (ret == 0) 28 | { 29 | client.apiReportRes(modid, cmdid, ip, port, 0); 30 | } 31 | } 32 | else 33 | { 34 | //printf("[%d,%d] get error %d\n", modid, cmdid, ret); 35 | } 36 | long curr = time(NULL); 37 | if (curr - lst >= 1) 38 | { 39 | lst = curr; 40 | printf("[%ld]\n", qps); 41 | qps = 0; 42 | } 43 | } 44 | return NULL; 45 | } 46 | 47 | int main(int argc, char const *argv[]) 48 | { 49 | int cnt = atoi(argv[1]); 50 | Item* items = new Item[cnt]; 51 | pthread_t* tids = new pthread_t[cnt]; 52 | for (int i = 0;i < cnt; ++i) 53 | { 54 | items[i].modid = 10000 + i; 55 | items[i].cmdid = 1001; 56 | } 57 | for (int i = 0;i < cnt; ++i) 58 | pthread_create(&tids[i], NULL, mockApi, &items[i]); 59 | for (int i = 0;i < cnt; ++i) 60 | pthread_join(tids[i], NULL); 61 | return 0; 62 | } -------------------------------------------------------------------------------- /api/cpp/example/simulator.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "elbApi.h" 4 | #include 5 | #include 6 | #include 7 | 8 | int main(int argc, char const *argv[]) 9 | { 10 | int modid = atoi(argv[1]); 11 | int cmdid = atoi(argv[2]); 12 | elbClient client; 13 | std::string ip; 14 | std::map > stat; 15 | int port; 16 | int ret = client.apiRegister(modid, cmdid);//非必需使用的API 17 | if (ret != 0) 18 | std::cout << "still not exist after register" << std::endl; 19 | 20 | srand(time(NULL)); 21 | for (int i = 0;i < 90; ++i) { 22 | ret = client.apiGetHost(modid, cmdid, 10, ip, port); 23 | if (ret == 0) 24 | { 25 | if (stat.find(ip) == stat.end()) { 26 | std::pair pair(0, 0); 27 | stat[ip] = pair; 28 | } 29 | std::cout << "host is " << ip << ":" << port << " "; 30 | if (rand() % 10 < 2)//以80%的概率产生调用失败 31 | { 32 | if (stat.find(ip) == stat.end()) { 33 | std::pair pair(0, 0); 34 | stat[ip] = pair; 35 | } 36 | stat[ip].second += 1; 37 | client.apiReportRes(modid, cmdid, ip, port, 1); 38 | std::cout << "call error" << std::endl; 39 | } 40 | else 41 | { 42 | stat[ip].first += 1; 43 | client.apiReportRes(modid, cmdid, ip, port, 0); 44 | std::cout << "call success" << std::endl; 45 | } 46 | } 47 | else if (ret == -9998) 48 | { 49 | std::cout << modid << "," << cmdid << " not exist" << std::endl; 50 | } 51 | else 52 | { 53 | std::cout << "get error code " << ret << std::endl; 54 | } 55 | //::usleep(600000); 56 | ::usleep(6000); 57 | } 58 | 59 | std::map >::iterator it; 60 | for (it = stat.begin();it != stat.end(); ++it) 61 | { 62 | std::cout << "ip: " << it->first << ": "; 63 | std::cout << "success: " << it->second.first << "; "; 64 | std::cout << "error: " << it->second.second << std::endl; 65 | } 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /api/cpp/example/testcache.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "elbApi.h" 4 | #include 5 | 6 | int main(int argc, char const *argv[]) 7 | { 8 | int modid = atoi(argv[1]); 9 | int cmdid = atoi(argv[2]); 10 | elbClient client; 11 | std::string ip; 12 | int port, ret; 13 | #if 0 14 | for (int i = 0;i < 1000; ++i) 15 | { 16 | ret = client.apiGetHost(modid, cmdid, 10, ip, port); 17 | if (ret == 0) 18 | { 19 | //std::cout << "host is " << ip << ":" << port << std::endl; 20 | if (rand() % 6 == 0) 21 | client.apiReportRes(modid, cmdid, ip, port, 0); 22 | else 23 | client.apiReportRes(modid, cmdid, ip, port, 1); 24 | } 25 | else if (ret == -9998) 26 | { 27 | //std::cout << modid << "," << cmdid << " not exist" << std::endl; 28 | } 29 | else 30 | { 31 | //std::cout << "get error code " << ret << std::endl; 32 | } 33 | usleep(10000); 34 | } 35 | int x; 36 | printf("continue>:"); 37 | scanf("%d", &x); 38 | #endif 39 | for (int i = 0;i < 30000; ++i) 40 | { 41 | ret = client.apiGetHost(modid, cmdid, 10, ip, port); 42 | if (ret == 0) 43 | { 44 | std::cout << "host is " << ip << ":" << port << std::endl; 45 | client.apiReportRes(modid, cmdid, ip, port, 0); 46 | } 47 | else if (ret == -9998) 48 | { 49 | std::cout << modid << "," << cmdid << " not exist" << std::endl; 50 | } 51 | else 52 | { 53 | //std::cout << "get error code " << ret << std::endl; 54 | } 55 | usleep(10000); 56 | } 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /api/cpp/example/timotest.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "elbApi.h" 4 | #include 5 | 6 | int main(int argc, char const *argv[]) 7 | { 8 | int modid = atoi(argv[1]); 9 | int cmdid = atoi(argv[2]); 10 | elbClient client; 11 | std::string ip; 12 | int port; 13 | int ret = client.apiRegister(modid, cmdid);//非必需使用的API 14 | if (ret != 0) 15 | std::cout << "still not exist after register" << std::endl; 16 | for (int i = 0;i < 10; ++i) 17 | { 18 | ret = client.apiGetHost(modid, cmdid, 10, ip, port); 19 | if (ret == 0) 20 | { 21 | std::cout << "host is " << ip << ":" << port << std::endl; 22 | std::cout << "sleep " << i % 2 + 1 << "s\n"; 23 | sleep(i % 2 + 1); 24 | client.apiReportRes(modid, cmdid, ip, port, 1); 25 | } 26 | else if (ret == -9998) 27 | { 28 | std::cout << modid << "," << cmdid << " not exist" << std::endl; 29 | } 30 | else 31 | { 32 | std::cout << "get error code " << ret << std::endl; 33 | } 34 | } 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /api/java/NOTEMPTY: -------------------------------------------------------------------------------- 1 | 由我的小伙伴编写 -------------------------------------------------------------------------------- /api/python/elbApi/CacheLayer.py: -------------------------------------------------------------------------------- 1 | class CacheUnit: 2 | def __init__(self): 3 | self.nodeList = [] 4 | self.succAccum = {} 5 | def getHost(self): 6 | """return val [ip: string, port: int]""" 7 | host = self.nodeList.pop(0) 8 | self.nodeList.append(host) 9 | return host 10 | 11 | def report(self, ip, port): 12 | """ip: string, port: int""" 13 | if (ip, port) in self.succAccum: 14 | self.succAccum[(ip, port)] += 1 15 | self.succCnt += 1 16 | -------------------------------------------------------------------------------- /api/python/elbApi/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | protoc --python_out=. --proto_path=../../../common/proto ../../../common/proto/elb.proto 3 | clean: 4 | rm -f *.pyc 5 | -------------------------------------------------------------------------------- /api/python/elbApi/StaticRoute.py: -------------------------------------------------------------------------------- 1 | import random 2 | import socket 3 | import struct 4 | 5 | class StaticRoute: 6 | def __init__(self): 7 | self.__route = None 8 | 9 | def getHost(self, modid, cmdid): 10 | if not self.__route: 11 | try: 12 | self.__route = {} 13 | for i in range(3): 14 | with open('/tmp/backupRoute.dat.%d' % (i + 1), 'r') as inf: 15 | for line in inf: 16 | attrs = line.strip().split() 17 | imodid, icmdid = int(attrs[0]), int(attrs[1]) 18 | ip = int(attrs[2]) 19 | port = int(attrs[3]) 20 | key = (imodid, icmdid) 21 | if (imodid, icmdid) not in self.__route: 22 | self.__route[(imodid, icmdid)] = [] 23 | self.__route[(imodid, icmdid)].append((ip, port)) 24 | 25 | except IOError, e: 26 | return -1 27 | if (modid, cmdid) not in self.__route: 28 | return -1 29 | host = random.choice(self.__route[(modid, cmdid)]) 30 | ipn = host[0] 31 | if ipn < 0: 32 | ipn += 2 ** 32 33 | ips = socket.inet_ntoa(struct.pack('I', ipn)) 34 | return (ips, host[1]) 35 | 36 | def freeData(self): 37 | self.__route = None -------------------------------------------------------------------------------- /api/python/elbApi/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeechanX/Easy-Load-Balancer/64bc1a74f7655dfb1968145ecfdf86537acbcd06/api/python/elbApi/__init__.py -------------------------------------------------------------------------------- /api/python/example.py: -------------------------------------------------------------------------------- 1 | #encoding=utf-8 2 | 3 | import sys 4 | from elbApi.elbClient import elbClient 5 | 6 | if __name__ == '__main__': 7 | client = elbClient() 8 | modid = int(sys.argv[1]) 9 | cmdid = int(sys.argv[2]) 10 | 11 | ret = client.apiRegister(modid, cmdid)#非必需使用的API 12 | if ret == -9998: 13 | print 'still no exist after register' 14 | ret, hostOrEmsg = client.apiGetHost(modid, cmdid, 10) 15 | if ret == 0: 16 | ip = hostOrEmsg[0] 17 | port = hostOrEmsg[1] 18 | print '%s:%d' % (ip, port) 19 | client.apiReportRes(modid, cmdid, ip, port, 0) 20 | elif ret == -9998: 21 | print '[%d,%d] not exist' % (modid, cmdid) 22 | else: 23 | print hostOrEmsg 24 | -------------------------------------------------------------------------------- /api/python/testcache.py: -------------------------------------------------------------------------------- 1 | #encoding=utf-8 2 | 3 | import sys 4 | import time 5 | import random 6 | from elbApi.elbClient import elbClient 7 | 8 | if __name__ == '__main__': 9 | client = elbClient() 10 | modid = int(sys.argv[1]) 11 | cmdid = int(sys.argv[2]) 12 | 13 | for i in range(2000): 14 | ret, hostOrEmsg = client.apiGetHost(modid, cmdid, 10) 15 | if ret == 0: 16 | ip = hostOrEmsg[0] 17 | port = hostOrEmsg[1] 18 | print '%s:%d' % (ip, port) 19 | client.apiReportRes(modid, cmdid, ip, port, 0) 20 | elif ret == -9998: 21 | print '[%d,%d] not exist' % (modid, cmdid) 22 | else: 23 | print hostOrEmsg 24 | time.sleep(0.005) 25 | -------------------------------------------------------------------------------- /api/python/timotest.py: -------------------------------------------------------------------------------- 1 | #encoding=utf-8 2 | 3 | import sys 4 | import time 5 | from elbApi.elbClient import elbClient 6 | 7 | if __name__ == '__main__': 8 | client = elbClient() 9 | modid = int(sys.argv[1]) 10 | cmdid = int(sys.argv[2]) 11 | 12 | ret = client.apiRegister(modid, cmdid)#非必需使用的API 13 | if ret == -9998: 14 | print 'still no exist after register' 15 | for i in range(10): 16 | ret, hostOrEmsg = client.apiGetHost(modid, cmdid, 10) 17 | if ret == 0: 18 | ip = hostOrEmsg[0] 19 | port = hostOrEmsg[1] 20 | print '%s:%d' % (ip, port) 21 | print 'sleep %ds' % (i % 2 + 1) 22 | time.sleep(i % 2 + 1) 23 | client.apiReportRes(modid, cmdid, ip, port, 1) 24 | elif ret == -9998: 25 | print '[%d,%d] not exist' % (modid, cmdid) 26 | else: 27 | print hostOrEmsg 28 | -------------------------------------------------------------------------------- /common/base/include/Singleton.h: -------------------------------------------------------------------------------- 1 | #ifndef __SINGLETON_H__ 2 | #define __SINGLETON_H__ 3 | 4 | #include 5 | #include 6 | 7 | template 8 | class Singleton 9 | { 10 | public: 11 | static void init() 12 | { 13 | _ins = new T(); 14 | assert(_ins); 15 | } 16 | 17 | static T* ins() 18 | { 19 | pthread_once(&_once, init); 20 | return _ins; 21 | } 22 | 23 | private: 24 | Singleton(const Singleton&);//necessary 25 | const Singleton& operator=(const Singleton&);//necessary 26 | 27 | static T* _ins; 28 | static pthread_once_t _once; 29 | }; 30 | 31 | template 32 | T* Singleton::_ins = NULL; 33 | 34 | template 35 | pthread_once_t Singleton::_once = PTHREAD_ONCE_INIT; 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /common/base/include/log.h: -------------------------------------------------------------------------------- 1 | #ifndef __TTCLOG_H__ 2 | #define __TTCLOG_H__ 3 | 4 | #include 5 | __BEGIN_DECLS 6 | 7 | #include 8 | 9 | //#if CLIENTAPI 10 | //#define __log_level__ 6 11 | //#else 12 | extern int __log_level__; 13 | //#endif 14 | #define log_generic(lvl, fmt, args...) _write_log_(lvl, __FILE__, __FUNCTION__, __LINE__ , fmt, ##args) 15 | #define log_emerg(fmt, args...) log_generic(0, fmt, ##args) 16 | #define log_alert(fmt, args...) log_generic(1, fmt, ##args) 17 | #define log_crit(fmt, args...) log_generic(2, fmt, ##args) 18 | #define log_error(fmt, args...) log_generic(3, fmt, ##args) 19 | #define log_warning(fmt, args...) do{ if(__log_level__>=4)log_generic(4, fmt, ##args); } while(0) 20 | #define log_notice(fmt, args...) do{ if(__log_level__>=5)log_generic(5, fmt, ##args); } while(0) 21 | #define log_info(fmt, args...) do{ if(__log_level__>=6)log_generic(6, fmt, ##args); } while(0) 22 | #define log_debug(fmt, args...) do{ if(__log_level__>=7)log_generic(7, fmt, ##args); } while(0) 23 | 24 | #define error_log(fmt, args...) log_error(fmt, ##args) 25 | 26 | #if __cplusplus 27 | extern void _init_log_ (const char *app, const char *dir = NULL); 28 | #else 29 | extern void _init_log_ (const char *app, const char *dir); 30 | #endif 31 | extern void _init_log_stat_(void); 32 | extern void _set_log_level_(int); 33 | extern void _set_log_thread_name_(const char *n); 34 | extern void _write_log_ (int, const char*, const char *, int, const char *, ...) __attribute__((format(printf,5,6))); 35 | 36 | #include 37 | #include 38 | #ifndef __NR_gettid 39 | #endif 40 | static inline int _gettid_(void) { return syscall(__NR_gettid); } 41 | 42 | #include 43 | static inline unsigned int GET_MSEC(void) { struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000 + tv.tv_usec/1000; } 44 | #define INIT_MSEC(v) v = GET_MSEC() 45 | #define CALC_MSEC(v) v = GET_MSEC() - (v) 46 | static inline unsigned int GET_USEC(void) { struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000000 + tv.tv_usec; } 47 | #define INIT_USEC(v) v = GET_USEC() 48 | #define CALC_USEC(v) v = GET_USEC() - (v) 49 | 50 | __END_DECLS 51 | #endif 52 | -------------------------------------------------------------------------------- /common/base/include/logo.h: -------------------------------------------------------------------------------- 1 | #ifndef __LOGO_H__ 2 | #define __LOGO_H__ 3 | 4 | #include 5 | 6 | inline void dispLogo() 7 | { 8 | printf("Easy Load Balancer is a simple, easy to use, stable remote call management and scheduling and load system\n"); 9 | printf(" \n"); 10 | printf(" ███████╗██╗ ██████╗ \n"); 11 | printf(" ██╔════╝██║ ██╔══██╗ \n"); 12 | printf(" ██████╗ ██║ ██████╔╝ \n"); 13 | printf(" ██╔═══╝ ██║ ██╔══██╗ \n"); 14 | printf(" ███████╗███████╗██████╔╝ \n"); 15 | printf(" ╚══════╝╚══════╝╚═════╝ \n"); 16 | printf(" \n"); 17 | printf("Designed by LeechanX (email: leechan8@outlook.com, wechat: LeechanX)\n"); 18 | } 19 | 20 | #endif 21 | 22 | -------------------------------------------------------------------------------- /common/base/include/util.h: -------------------------------------------------------------------------------- 1 | #ifndef __UTIL_H__ 2 | #define __UTIL_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | unsigned int murMurHash(const void *key, int len) 9 | { 10 | const unsigned int m = 0x5bd1e995; 11 | const int r = 24; 12 | const int seed = 97; 13 | unsigned int h = seed ^ len; 14 | // Mix 4 bytes at a time into the hash 15 | const unsigned char *data = (const unsigned char *)key; 16 | while(len >= 4) 17 | { 18 | unsigned int k = *(unsigned int *)data; 19 | k *= m; 20 | k ^= k >> r; 21 | k *= m; 22 | h *= m; 23 | h ^= k; 24 | data += 4; 25 | len -= 4; 26 | } 27 | // Handle the last few bytes of the input array 28 | switch(len) 29 | { 30 | case 3: h ^= data[2] << 16; 31 | case 2: h ^= data[1] << 8; 32 | case 1: h ^= data[0]; 33 | h *= m; 34 | }; 35 | // Do a few final mixes of the hash to ensure the last few 36 | // bytes are well-incorporated. 37 | h ^= h >> 13; 38 | h *= m; 39 | h ^= h >> 15; 40 | return h; 41 | } 42 | 43 | #define HASHTO(kp, limit) murMurHash(kp, 8) % limit 44 | /* 45 | int main(int argc, char **argv) 46 | { 47 | int modid = atoi(argv[1]); 48 | int cmdid = atoi(argv[2]); 49 | uint64_t key = ((uint64_t)modid << 32) + cmdid; 50 | unsigned int k = HASHTO(&key, 10);//murMurHash(&key, sizeof key); 51 | printf("murMurHash key = %u\n", k); 52 | } 53 | */ 54 | #endif 55 | -------------------------------------------------------------------------------- /common/base/src/log.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "log.h" 13 | 14 | #define LOGSIZE 4096 15 | 16 | int __log_level__ = 6; 17 | 18 | static int logfd = -1; 19 | static int logday = 0; 20 | static char log_dir[128] = "../log"; 21 | static char appname[32] = ""; 22 | #if CLIENTAPI 23 | static const char *threadname = NULL; 24 | //static void init_namekey(void) { } 25 | void _set_log_thread_name_(const char *n) { } 26 | #else 27 | #if HAS_TLS 28 | static __thread const char *threadname; 29 | void _set_log_thread_name_(const char *n) { threadname = n; } 30 | #else 31 | static pthread_key_t namekey; 32 | static pthread_once_t nameonce = PTHREAD_ONCE_INIT; 33 | static void _init_namekey_(void) { pthread_key_create(&namekey, NULL); } 34 | void _set_log_thread_name_(const char *n) { pthread_setspecific(namekey, n); } 35 | #endif 36 | #endif 37 | 38 | #if HAS_STAT 39 | #include "StatTTC.h" 40 | static int statEnable; 41 | CStatItemU32 statLogCount[8]; 42 | static unsigned int localStatLogCnt[8]; 43 | #endif 44 | 45 | void _init_log_ (const char *app, const char *dir) 46 | { 47 | #if !CLIENTAPI 48 | #if !HAS_TLS 49 | pthread_once(&nameonce, _init_namekey_); 50 | #endif 51 | #endif 52 | #if HAS_STAT 53 | statEnable = 0; // 暂时只在本地统计 54 | memset(localStatLogCnt, 0, sizeof(localStatLogCnt)); 55 | #endif 56 | 57 | strncpy(appname, app, sizeof(appname)-1); 58 | 59 | if(dir) { 60 | strncpy (log_dir, dir, sizeof (log_dir) - 1); 61 | } 62 | mkdir(log_dir, 0777); 63 | if(access(log_dir, W_OK|X_OK) < 0) 64 | { 65 | log_error("logdir(%s): Not writable", log_dir); 66 | } 67 | 68 | logfd = open("/dev/null", O_WRONLY); 69 | if(logfd < 0) 70 | logfd = dup(2); 71 | fcntl(logfd, F_SETFD, FD_CLOEXEC); 72 | } 73 | 74 | void _init_log_stat_(void) 75 | { 76 | #if HAS_STAT 77 | for(unsigned i=0; i<8; i++) 78 | { 79 | statLogCount[i] = statmgr.GetItemU32(LOG_COUNT_0+i); 80 | statLogCount[i].set(localStatLogCnt[i]); 81 | } 82 | statEnable = 1; 83 | #endif 84 | } 85 | 86 | void _set_log_level_(int l) 87 | { 88 | if(l>=0) 89 | __log_level__ = l > 4 ? l : 4; 90 | } 91 | 92 | void _write_log_( 93 | int level, 94 | const char *filename, 95 | const char *funcname, 96 | int lineno, 97 | const char *format, ...) 98 | { 99 | // save errno 100 | int savedErrNo = errno; 101 | int off = 0; 102 | char buf[LOGSIZE]; 103 | char logfile[256]; 104 | #if !CLIENTAPI 105 | #if !HAS_TLS 106 | const char *threadname; 107 | #endif 108 | #endif 109 | 110 | if(appname[0] == 0) 111 | return; 112 | 113 | #if HAS_STAT 114 | if(level < 0) level = 0; 115 | else if(level > 7) level = 7; 116 | if(!statEnable) 117 | ++localStatLogCnt[level]; 118 | else 119 | ++statLogCount[level]; 120 | #endif 121 | 122 | // construct prefix 123 | struct tm tm; 124 | time_t now = time (NULL); 125 | localtime_r(&now, &tm); 126 | filename = basename(filename); 127 | #if !CLIENTAPI 128 | #if HAS_TLS 129 | #else 130 | pthread_once(&nameonce, _init_namekey_); 131 | threadname = (const char *)pthread_getspecific(namekey); 132 | #endif 133 | #endif 134 | if(threadname) 135 | off = snprintf (buf, LOGSIZE, 136 | "<%d>[%02d:%02d:%02d] %s: %s(%d)[%s]: ", 137 | level, 138 | tm.tm_hour, tm.tm_min, tm.tm_sec, 139 | threadname, 140 | filename, lineno, funcname 141 | ); 142 | else 143 | off = snprintf (buf, LOGSIZE, 144 | "<%d>[%02d:%02d:%02d] pid[%d]: %s(%d)[%s]: ", 145 | level, 146 | tm.tm_hour, tm.tm_min, tm.tm_sec, 147 | _gettid_(), 148 | filename, lineno, funcname 149 | ); 150 | if(off >= LOGSIZE) 151 | off = LOGSIZE - 1; 152 | 153 | { 154 | int today = tm.tm_year*1000 + tm.tm_yday; 155 | if(logfd >= 0 && today != logday) 156 | { 157 | int fd; 158 | 159 | logday = today; 160 | snprintf (logfile, sizeof(logfile), 161 | "%s/%s.error%04d%02d%02d.log", log_dir, appname, 162 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); 163 | fd = open (logfile, O_CREAT | O_LARGEFILE | O_APPEND |O_WRONLY, 0644); 164 | if(fd >= 0) 165 | { 166 | dup2(fd, logfd); 167 | close(fd); 168 | fcntl(logfd, F_SETFD, FD_CLOEXEC); 169 | } 170 | } 171 | } 172 | 173 | { 174 | // formatted message 175 | va_list ap; 176 | va_start(ap, format); 177 | // restore errno 178 | errno = savedErrNo; 179 | off += vsnprintf(buf+off, LOGSIZE-off, format, ap); 180 | va_end(ap); 181 | } 182 | 183 | if(off >= LOGSIZE) 184 | off = LOGSIZE - 1; 185 | if(buf[off-1]!='\n'){ 186 | if(off < LOGSIZE - 1) 187 | buf[off++] = '\n'; 188 | else 189 | buf[LOGSIZE-1] = '\n'; 190 | } 191 | 192 | int unused; 193 | unused = fwrite(buf+3, 1, off-3, stderr); 194 | 195 | if(logfd >= 0) 196 | unused = write(logfd, buf, off); 197 | } 198 | 199 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/big_endian.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | #include 17 | 18 | /* 19 | Data in big-endian format. 20 | */ 21 | static inline void float4store(uchar *T, float A) 22 | { *(T)= ((uchar *) &A)[3]; 23 | *((T)+1)=(char) ((uchar *) &A)[2]; 24 | *((T)+2)=(char) ((uchar *) &A)[1]; 25 | *((T)+3)=(char) ((uchar *) &A)[0]; } 26 | 27 | static inline void float4get (float *V, const uchar *M) 28 | { float def_temp; 29 | ((uchar*) &def_temp)[0]=(M)[3]; 30 | ((uchar*) &def_temp)[1]=(M)[2]; 31 | ((uchar*) &def_temp)[2]=(M)[1]; 32 | ((uchar*) &def_temp)[3]=(M)[0]; 33 | (*V)=def_temp; } 34 | 35 | static inline void float8store(uchar *T, double V) 36 | { *(T)= ((uchar *) &V)[7]; 37 | *((T)+1)=(char) ((uchar *) &V)[6]; 38 | *((T)+2)=(char) ((uchar *) &V)[5]; 39 | *((T)+3)=(char) ((uchar *) &V)[4]; 40 | *((T)+4)=(char) ((uchar *) &V)[3]; 41 | *((T)+5)=(char) ((uchar *) &V)[2]; 42 | *((T)+6)=(char) ((uchar *) &V)[1]; 43 | *((T)+7)=(char) ((uchar *) &V)[0]; } 44 | 45 | static inline void float8get (double *V, const uchar *M) 46 | { double def_temp; 47 | ((uchar*) &def_temp)[0]=(M)[7]; 48 | ((uchar*) &def_temp)[1]=(M)[6]; 49 | ((uchar*) &def_temp)[2]=(M)[5]; 50 | ((uchar*) &def_temp)[3]=(M)[4]; 51 | ((uchar*) &def_temp)[4]=(M)[3]; 52 | ((uchar*) &def_temp)[5]=(M)[2]; 53 | ((uchar*) &def_temp)[6]=(M)[1]; 54 | ((uchar*) &def_temp)[7]=(M)[0]; 55 | (*V) = def_temp; } 56 | 57 | static inline void ushortget(uint16 *V, const uchar *pM) 58 | { *V = (uint16) (((uint16) ((uchar) (pM)[1]))+ 59 | ((uint16) ((uint16) (pM)[0]) << 8)); } 60 | static inline void shortget (int16 *V, const uchar *pM) 61 | { *V = (short) (((short) ((uchar) (pM)[1]))+ 62 | ((short) ((short) (pM)[0]) << 8)); } 63 | static inline void longget (int32 *V, const uchar *pM) 64 | { int32 def_temp; 65 | ((uchar*) &def_temp)[0]=(pM)[0]; 66 | ((uchar*) &def_temp)[1]=(pM)[1]; 67 | ((uchar*) &def_temp)[2]=(pM)[2]; 68 | ((uchar*) &def_temp)[3]=(pM)[3]; 69 | (*V)=def_temp; } 70 | static inline void ulongget (uint32 *V, const uchar *pM) 71 | { uint32 def_temp; 72 | ((uchar*) &def_temp)[0]=(pM)[0]; 73 | ((uchar*) &def_temp)[1]=(pM)[1]; 74 | ((uchar*) &def_temp)[2]=(pM)[2]; 75 | ((uchar*) &def_temp)[3]=(pM)[3]; 76 | (*V)=def_temp; } 77 | static inline void shortstore(uchar *T, int16 A) 78 | { uint def_temp=(uint) (A) ; 79 | *(((char*)T)+1)=(char)(def_temp); 80 | *(((char*)T)+0)=(char)(def_temp >> 8); } 81 | static inline void longstore (uchar *T, int32 A) 82 | { *(((char*)T)+3)=((A)); 83 | *(((char*)T)+2)=(((A) >> 8)); 84 | *(((char*)T)+1)=(((A) >> 16)); 85 | *(((char*)T)+0)=(((A) >> 24)); } 86 | 87 | static inline void floatget(float *V, const uchar *M) 88 | { 89 | memcpy(V, (M), sizeof(float)); 90 | } 91 | 92 | static inline void floatstore(uchar *T, float V) 93 | { 94 | memcpy((T), (&V), sizeof(float)); 95 | } 96 | 97 | static inline void doubleget(double *V, const uchar *M) 98 | { 99 | memcpy(V, (M), sizeof(double)); 100 | } 101 | 102 | static inline void doublestore(uchar *T, double V) 103 | { 104 | memcpy((T), &V, sizeof(double)); 105 | } 106 | 107 | static inline void longlongget(longlong *V, const uchar *M) 108 | { 109 | memcpy(V, (M), sizeof(ulonglong)); 110 | } 111 | static inline void longlongstore(uchar *T, longlong V) 112 | { 113 | memcpy((T), &V, sizeof(ulonglong)); 114 | } 115 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/binary_log_types.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014, 2015 Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | /** 17 | @file binary_log_types.h 18 | 19 | @brief This file contains the field type. 20 | 21 | 22 | @note This file can be imported both from C and C++ code, so the 23 | definitions have to be constructed to support this. 24 | */ 25 | 26 | #ifndef BINARY_LOG_TYPES_INCLUDED 27 | #define BINARY_LOG_TYPES_INCLUDED 28 | 29 | #ifdef __cplusplus 30 | extern "C" 31 | { 32 | #endif 33 | 34 | /* 35 | * Constants exported from this package. 36 | */ 37 | 38 | typedef enum enum_field_types { 39 | MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY, 40 | MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG, 41 | MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE, 42 | MYSQL_TYPE_NULL, MYSQL_TYPE_TIMESTAMP, 43 | MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24, 44 | MYSQL_TYPE_DATE, MYSQL_TYPE_TIME, 45 | MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR, 46 | MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR, 47 | MYSQL_TYPE_BIT, 48 | MYSQL_TYPE_TIMESTAMP2, 49 | MYSQL_TYPE_DATETIME2, 50 | MYSQL_TYPE_TIME2, 51 | MYSQL_TYPE_JSON=245, 52 | MYSQL_TYPE_NEWDECIMAL=246, 53 | MYSQL_TYPE_ENUM=247, 54 | MYSQL_TYPE_SET=248, 55 | MYSQL_TYPE_TINY_BLOB=249, 56 | MYSQL_TYPE_MEDIUM_BLOB=250, 57 | MYSQL_TYPE_LONG_BLOB=251, 58 | MYSQL_TYPE_BLOB=252, 59 | MYSQL_TYPE_VAR_STRING=253, 60 | MYSQL_TYPE_STRING=254, 61 | MYSQL_TYPE_GEOMETRY=255 62 | } enum_field_types; 63 | 64 | #define DATETIME_MAX_DECIMALS 6 65 | 66 | #ifdef __cplusplus 67 | } 68 | #endif // __cplusplus 69 | 70 | #endif /* BINARY_LOG_TYPES_INCLUDED */ 71 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/byte_order_generic.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | /* 17 | Endianness-independent definitions for architectures other 18 | than the x86 architecture. 19 | */ 20 | static inline int16 sint2korr(const uchar *A) 21 | { 22 | return 23 | (int16) (((int16) (A[0])) + 24 | ((int16) (A[1]) << 8)) 25 | ; 26 | } 27 | 28 | static inline int32 sint4korr(const uchar *A) 29 | { 30 | return 31 | (int32) (((int32) (A[0])) + 32 | (((int32) (A[1]) << 8)) + 33 | (((int32) (A[2]) << 16)) + 34 | (((int32) (A[3]) << 24))) 35 | ; 36 | } 37 | 38 | static inline uint16 uint2korr(const uchar *A) 39 | { 40 | return 41 | (uint16) (((uint16) (A[0])) + 42 | ((uint16) (A[1]) << 8)) 43 | ; 44 | } 45 | 46 | static inline uint32 uint4korr(const uchar *A) 47 | { 48 | return 49 | (uint32) (((uint32) (A[0])) + 50 | (((uint32) (A[1])) << 8) + 51 | (((uint32) (A[2])) << 16) + 52 | (((uint32) (A[3])) << 24)) 53 | ; 54 | } 55 | 56 | static inline ulonglong uint8korr(const uchar *A) 57 | { 58 | return 59 | ((ulonglong)(((uint32) (A[0])) + 60 | (((uint32) (A[1])) << 8) + 61 | (((uint32) (A[2])) << 16) + 62 | (((uint32) (A[3])) << 24)) + 63 | (((ulonglong) (((uint32) (A[4])) + 64 | (((uint32) (A[5])) << 8) + 65 | (((uint32) (A[6])) << 16) + 66 | (((uint32) (A[7])) << 24))) << 67 | 32)) 68 | ; 69 | } 70 | 71 | static inline longlong sint8korr(const uchar *A) 72 | { 73 | return (longlong) uint8korr(A); 74 | } 75 | 76 | static inline void int2store(uchar *T, uint16 A) 77 | { 78 | uint def_temp= A ; 79 | *(T)= (uchar)(def_temp); 80 | *(T+1)= (uchar)(def_temp >> 8); 81 | } 82 | 83 | static inline void int4store(uchar *T, uint32 A) 84 | { 85 | *(T)= (uchar) (A); 86 | *(T+1)=(uchar) (A >> 8); 87 | *(T+2)=(uchar) (A >> 16); 88 | *(T+3)=(uchar) (A >> 24); 89 | } 90 | 91 | static inline void int8store(uchar *T, ulonglong A) 92 | { 93 | uint def_temp= (uint) A, 94 | def_temp2= (uint) (A >> 32); 95 | int4store(T, def_temp); 96 | int4store(T+4,def_temp2); 97 | } 98 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/byte_order_generic_x86.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | /* 17 | Optimized functions for the x86 architecture (_WIN32 included). 18 | 19 | x86 handles misaligned reads and writes just fine, so suppress 20 | UBSAN warnings for these functions. 21 | */ 22 | static inline int16 sint2korr(const uchar *A) SUPPRESS_UBSAN; 23 | static inline int16 sint2korr(const uchar *A) { return *((int16*) A); } 24 | 25 | static inline int32 sint4korr(const uchar *A) SUPPRESS_UBSAN; 26 | static inline int32 sint4korr(const uchar *A) { return *((int32*) A); } 27 | 28 | static inline uint16 uint2korr(const uchar *A) SUPPRESS_UBSAN; 29 | static inline uint16 uint2korr(const uchar *A) { return *((uint16*) A); } 30 | 31 | static inline uint32 uint4korr(const uchar *A) SUPPRESS_UBSAN; 32 | static inline uint32 uint4korr(const uchar *A) { return *((uint32*) A); } 33 | 34 | static inline ulonglong uint8korr(const uchar *A) SUPPRESS_UBSAN; 35 | static inline ulonglong uint8korr(const uchar *A) { return *((ulonglong*) A);} 36 | 37 | static inline longlong sint8korr(const uchar *A) SUPPRESS_UBSAN; 38 | static inline longlong sint8korr(const uchar *A) { return *((longlong*) A); } 39 | 40 | static inline void int2store(uchar *T, uint16 A) SUPPRESS_UBSAN; 41 | static inline void int2store(uchar *T, uint16 A) 42 | { 43 | *((uint16*) T)= A; 44 | } 45 | 46 | static inline void int4store(uchar *T, uint32 A) SUPPRESS_UBSAN; 47 | static inline void int4store(uchar *T, uint32 A) 48 | { 49 | *((uint32*) T)= A; 50 | } 51 | 52 | static inline void int8store(uchar *T, ulonglong A) SUPPRESS_UBSAN; 53 | static inline void int8store(uchar *T, ulonglong A) 54 | { 55 | *((ulonglong*) T)= A; 56 | } 57 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/errmsg.h: -------------------------------------------------------------------------------- 1 | #ifndef ERRMSG_INCLUDED 2 | #define ERRMSG_INCLUDED 3 | 4 | /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; version 2 of the License. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 18 | 19 | /* Error messages for MySQL clients */ 20 | /* (Error messages for the daemon are in sql/share/errmsg.txt) */ 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | void init_client_errs(void); 26 | void finish_client_errs(void); 27 | extern const char *client_errors[]; /* Error messages */ 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | #define CR_MIN_ERROR 2000 /* For easier client code */ 33 | #define CR_MAX_ERROR 2999 34 | #if !defined(ER) 35 | #define ER(X) (((X) >= CR_ERROR_FIRST && (X) <= CR_ERROR_LAST)? \ 36 | client_errors[(X)-CR_ERROR_FIRST]: client_errors[CR_UNKNOWN_ERROR]) 37 | 38 | #endif 39 | #define CLIENT_ERRMAP 2 /* Errormap used by my_error() */ 40 | 41 | /* Do not add error numbers before CR_ERROR_FIRST. */ 42 | /* If necessary to add lower numbers, change CR_ERROR_FIRST accordingly. */ 43 | #define CR_ERROR_FIRST 2000 /*Copy first error nr.*/ 44 | #define CR_UNKNOWN_ERROR 2000 45 | #define CR_SOCKET_CREATE_ERROR 2001 46 | #define CR_CONNECTION_ERROR 2002 47 | #define CR_CONN_HOST_ERROR 2003 48 | #define CR_IPSOCK_ERROR 2004 49 | #define CR_UNKNOWN_HOST 2005 50 | #define CR_SERVER_GONE_ERROR 2006 51 | #define CR_VERSION_ERROR 2007 52 | #define CR_OUT_OF_MEMORY 2008 53 | #define CR_WRONG_HOST_INFO 2009 54 | #define CR_LOCALHOST_CONNECTION 2010 55 | #define CR_TCP_CONNECTION 2011 56 | #define CR_SERVER_HANDSHAKE_ERR 2012 57 | #define CR_SERVER_LOST 2013 58 | #define CR_COMMANDS_OUT_OF_SYNC 2014 59 | #define CR_NAMEDPIPE_CONNECTION 2015 60 | #define CR_NAMEDPIPEWAIT_ERROR 2016 61 | #define CR_NAMEDPIPEOPEN_ERROR 2017 62 | #define CR_NAMEDPIPESETSTATE_ERROR 2018 63 | #define CR_CANT_READ_CHARSET 2019 64 | #define CR_NET_PACKET_TOO_LARGE 2020 65 | #define CR_EMBEDDED_CONNECTION 2021 66 | #define CR_PROBE_SLAVE_STATUS 2022 67 | #define CR_PROBE_SLAVE_HOSTS 2023 68 | #define CR_PROBE_SLAVE_CONNECT 2024 69 | #define CR_PROBE_MASTER_CONNECT 2025 70 | #define CR_SSL_CONNECTION_ERROR 2026 71 | #define CR_MALFORMED_PACKET 2027 72 | #define CR_WRONG_LICENSE 2028 73 | 74 | /* new 4.1 error codes */ 75 | #define CR_NULL_POINTER 2029 76 | #define CR_NO_PREPARE_STMT 2030 77 | #define CR_PARAMS_NOT_BOUND 2031 78 | #define CR_DATA_TRUNCATED 2032 79 | #define CR_NO_PARAMETERS_EXISTS 2033 80 | #define CR_INVALID_PARAMETER_NO 2034 81 | #define CR_INVALID_BUFFER_USE 2035 82 | #define CR_UNSUPPORTED_PARAM_TYPE 2036 83 | 84 | #define CR_SHARED_MEMORY_CONNECTION 2037 85 | #define CR_SHARED_MEMORY_CONNECT_REQUEST_ERROR 2038 86 | #define CR_SHARED_MEMORY_CONNECT_ANSWER_ERROR 2039 87 | #define CR_SHARED_MEMORY_CONNECT_FILE_MAP_ERROR 2040 88 | #define CR_SHARED_MEMORY_CONNECT_MAP_ERROR 2041 89 | #define CR_SHARED_MEMORY_FILE_MAP_ERROR 2042 90 | #define CR_SHARED_MEMORY_MAP_ERROR 2043 91 | #define CR_SHARED_MEMORY_EVENT_ERROR 2044 92 | #define CR_SHARED_MEMORY_CONNECT_ABANDONED_ERROR 2045 93 | #define CR_SHARED_MEMORY_CONNECT_SET_ERROR 2046 94 | #define CR_CONN_UNKNOW_PROTOCOL 2047 95 | #define CR_INVALID_CONN_HANDLE 2048 96 | #define CR_UNUSED_1 2049 97 | #define CR_FETCH_CANCELED 2050 98 | #define CR_NO_DATA 2051 99 | #define CR_NO_STMT_METADATA 2052 100 | #define CR_NO_RESULT_SET 2053 101 | #define CR_NOT_IMPLEMENTED 2054 102 | #define CR_SERVER_LOST_EXTENDED 2055 103 | #define CR_STMT_CLOSED 2056 104 | #define CR_NEW_STMT_METADATA 2057 105 | #define CR_ALREADY_CONNECTED 2058 106 | #define CR_AUTH_PLUGIN_CANNOT_LOAD 2059 107 | #define CR_DUPLICATE_CONNECTION_ATTR 2060 108 | #define CR_AUTH_PLUGIN_ERR 2061 109 | #define CR_INSECURE_API_ERR 2062 110 | #define CR_ERROR_LAST /*Copy last error nr:*/ 2062 111 | /* Add error numbers before CR_ERROR_LAST and change it accordingly. */ 112 | 113 | #endif /* ERRMSG_INCLUDED */ 114 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/little_endian.h: -------------------------------------------------------------------------------- 1 | #ifndef LITTLE_ENDIAN_INCLUDED 2 | #define LITTLE_ENDIAN_INCLUDED 3 | /* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; version 2 of the License. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 17 | 18 | /* 19 | Data in little-endian format. 20 | */ 21 | 22 | #include 23 | 24 | static inline void float4get (float *V, const uchar *M) 25 | { 26 | memcpy(V, (M), sizeof(float)); 27 | } 28 | 29 | static inline void float4store(uchar *V, float M) 30 | { 31 | memcpy(V, (&M), sizeof(float)); 32 | } 33 | 34 | static inline void float8get (double *V, const uchar *M) 35 | { 36 | memcpy(V, M, sizeof(double)); 37 | } 38 | 39 | static inline void float8store(uchar *V, double M) 40 | { 41 | memcpy(V, &M, sizeof(double)); 42 | } 43 | 44 | static inline void floatget (float *V, const uchar *M) { float4get(V, M); } 45 | static inline void floatstore (uchar *V, float M) { float4store(V, M); } 46 | 47 | /* Bi-endian hardware.... */ 48 | #if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN) 49 | static inline void doublestore(uchar *T, double V) 50 | { *(((char*)T)+0)=(char) ((uchar *) &V)[4]; 51 | *(((char*)T)+1)=(char) ((uchar *) &V)[5]; 52 | *(((char*)T)+2)=(char) ((uchar *) &V)[6]; 53 | *(((char*)T)+3)=(char) ((uchar *) &V)[7]; 54 | *(((char*)T)+4)=(char) ((uchar *) &V)[0]; 55 | *(((char*)T)+5)=(char) ((uchar *) &V)[1]; 56 | *(((char*)T)+6)=(char) ((uchar *) &V)[2]; 57 | *(((char*)T)+7)=(char) ((uchar *) &V)[3]; } 58 | static inline void doubleget(double *V, const uchar *M) 59 | { double def_temp; 60 | ((uchar*) &def_temp)[0]=(M)[4]; 61 | ((uchar*) &def_temp)[1]=(M)[5]; 62 | ((uchar*) &def_temp)[2]=(M)[6]; 63 | ((uchar*) &def_temp)[3]=(M)[7]; 64 | ((uchar*) &def_temp)[4]=(M)[0]; 65 | ((uchar*) &def_temp)[5]=(M)[1]; 66 | ((uchar*) &def_temp)[6]=(M)[2]; 67 | ((uchar*) &def_temp)[7]=(M)[3]; 68 | (*V) = def_temp; } 69 | 70 | #else /* Bi-endian hardware.... */ 71 | 72 | static inline void doublestore(uchar *T, double V) { memcpy(T, &V, sizeof(double)); } 73 | static inline void doubleget (double *V, const uchar *M) { memcpy(V, M, sizeof(double)); } 74 | 75 | #endif /* Bi-endian hardware.... */ 76 | 77 | static inline void ushortget(uint16 *V, const uchar *pM) { *V= uint2korr(pM); } 78 | static inline void shortget (int16 *V, const uchar *pM) { *V= sint2korr(pM); } 79 | static inline void longget (int32 *V, const uchar *pM) { *V= sint4korr(pM); } 80 | static inline void ulongget (uint32 *V, const uchar *pM) { *V= uint4korr(pM); } 81 | static inline void shortstore(uchar *T, int16 V) { int2store(T, V); } 82 | static inline void longstore (uchar *T, int32 V) { int4store(T, V); } 83 | 84 | static inline void longlongget(longlong *V, const uchar *M) 85 | { 86 | memcpy(V, (M), sizeof(ulonglong)); 87 | } 88 | static inline void longlongstore(uchar *T, longlong V) 89 | { 90 | memcpy((T), &V, sizeof(ulonglong)); 91 | } 92 | 93 | #endif /* LITTLE_ENDIAN_INCLUDED */ 94 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/my_alloc.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | /* 17 | Data structures for mysys/my_alloc.c (root memory allocator) 18 | */ 19 | 20 | #ifndef _my_alloc_h 21 | #define _my_alloc_h 22 | 23 | #define ALLOC_MAX_BLOCK_TO_DROP 4096 24 | #define ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP 10 25 | 26 | /* PSI_memory_key */ 27 | #include "mysql/psi/psi_memory.h" 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | typedef struct st_used_mem 34 | { /* struct for once_alloc (block) */ 35 | struct st_used_mem *next; /* Next block in use */ 36 | unsigned int left; /* memory left in block */ 37 | unsigned int size; /* size of block */ 38 | } USED_MEM; 39 | 40 | 41 | typedef struct st_mem_root 42 | { 43 | USED_MEM *free; /* blocks with free memory in it */ 44 | USED_MEM *used; /* blocks almost without free memory */ 45 | USED_MEM *pre_alloc; /* preallocated block */ 46 | /* if block have less memory it will be put in 'used' list */ 47 | size_t min_malloc; 48 | size_t block_size; /* initial block size */ 49 | unsigned int block_num; /* allocated blocks counter */ 50 | /* 51 | first free block in queue test counter (if it exceed 52 | MAX_BLOCK_USAGE_BEFORE_DROP block will be dropped in 'used' list) 53 | */ 54 | unsigned int first_block_usage; 55 | 56 | void (*error_handler)(void); 57 | 58 | PSI_memory_key m_psi_key; 59 | } MEM_ROOT; 60 | 61 | #ifdef __cplusplus 62 | } 63 | #endif 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/my_command.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | #ifndef _mysql_command_h 17 | #define _mysql_command_h 18 | 19 | /** 20 | @enum enum_server_command 21 | @brief You should add new commands to the end of this list, otherwise old 22 | servers won't be able to handle them as 'unsupported'. 23 | */ 24 | enum enum_server_command 25 | { 26 | COM_SLEEP, 27 | COM_QUIT, 28 | COM_INIT_DB, 29 | COM_QUERY, 30 | COM_FIELD_LIST, 31 | COM_CREATE_DB, 32 | COM_DROP_DB, 33 | COM_REFRESH, 34 | COM_SHUTDOWN, 35 | COM_STATISTICS, 36 | COM_PROCESS_INFO, 37 | COM_CONNECT, 38 | COM_PROCESS_KILL, 39 | COM_DEBUG, 40 | COM_PING, 41 | COM_TIME, 42 | COM_DELAYED_INSERT, 43 | COM_CHANGE_USER, 44 | COM_BINLOG_DUMP, 45 | COM_TABLE_DUMP, 46 | COM_CONNECT_OUT, 47 | COM_REGISTER_SLAVE, 48 | COM_STMT_PREPARE, 49 | COM_STMT_EXECUTE, 50 | COM_STMT_SEND_LONG_DATA, 51 | COM_STMT_CLOSE, 52 | COM_STMT_RESET, 53 | COM_SET_OPTION, 54 | COM_STMT_FETCH, 55 | COM_DAEMON, 56 | COM_BINLOG_DUMP_GTID, 57 | COM_RESET_CONNECTION, 58 | /* don't forget to update const char *command_name[] in sql_parse.cc */ 59 | 60 | /* Must be last */ 61 | COM_END 62 | }; 63 | 64 | #endif /* _mysql_command_h */ 65 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/my_dir.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | #ifndef MY_DIR_H 17 | #define MY_DIR_H 18 | 19 | #include "my_global.h" 20 | 21 | #include 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | /* Defines for my_dir and my_stat */ 28 | 29 | #ifdef _WIN32 30 | #define S_IROTH _S_IREAD 31 | #define S_IFIFO _S_IFIFO 32 | #endif 33 | 34 | #define MY_S_IFMT S_IFMT /* type of file */ 35 | #define MY_S_IFDIR S_IFDIR /* directory */ 36 | #define MY_S_IFCHR S_IFCHR /* character special */ 37 | #define MY_S_IFBLK S_IFBLK /* block special */ 38 | #define MY_S_IFREG S_IFREG /* regular */ 39 | #define MY_S_IFIFO S_IFIFO /* fifo */ 40 | #define MY_S_ISUID S_ISUID /* set user id on execution */ 41 | #define MY_S_ISGID S_ISGID /* set group id on execution */ 42 | #define MY_S_ISVTX S_ISVTX /* save swapped text even after use */ 43 | #define MY_S_IREAD S_IREAD /* read permission, owner */ 44 | #define MY_S_IWRITE S_IWRITE /* write permission, owner */ 45 | #define MY_S_IEXEC S_IEXEC /* execute/search permission, owner */ 46 | 47 | #define MY_S_ISDIR(m) (((m) & MY_S_IFMT) == MY_S_IFDIR) 48 | #define MY_S_ISCHR(m) (((m) & MY_S_IFMT) == MY_S_IFCHR) 49 | #define MY_S_ISBLK(m) (((m) & MY_S_IFMT) == MY_S_IFBLK) 50 | #define MY_S_ISREG(m) (((m) & MY_S_IFMT) == MY_S_IFREG) 51 | #define MY_S_ISFIFO(m) (((m) & MY_S_IFMT) == MY_S_IFIFO) 52 | 53 | #define MY_DONT_SORT 512 /* my_lib; Don't sort files */ 54 | #define MY_WANT_STAT 1024 /* my_lib; stat files */ 55 | 56 | /* typedefs for my_dir & my_stat */ 57 | 58 | #if(_MSC_VER) 59 | #define MY_STAT struct _stati64 /* 64 bit file size */ 60 | #else 61 | #define MY_STAT struct stat /* Orginal struct have what we need */ 62 | #endif 63 | 64 | /* Struct describing one file returned from my_dir */ 65 | typedef struct fileinfo 66 | { 67 | char *name; 68 | MY_STAT *mystat; 69 | } FILEINFO; 70 | 71 | typedef struct st_my_dir /* Struct returned from my_dir */ 72 | { 73 | /* 74 | These members are just copies of parts of DYNAMIC_ARRAY structure, 75 | which is allocated right after the end of MY_DIR structure (MEM_ROOT 76 | for storing names is also resides there). We've left them here because 77 | we don't want to change code that uses my_dir. 78 | */ 79 | struct fileinfo *dir_entry; 80 | uint number_off_files; 81 | } MY_DIR; 82 | 83 | extern MY_DIR *my_dir(const char *path,myf MyFlags); 84 | extern void my_dirend(MY_DIR *buffer); 85 | extern MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags); 86 | extern int my_fstat(int filenr, MY_STAT *stat_area, myf MyFlags); 87 | 88 | #ifdef __cplusplus 89 | } 90 | #endif 91 | 92 | #endif /* MY_DIR_H */ 93 | 94 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/my_list.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | #ifndef _list_h_ 17 | #define _list_h_ 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | typedef struct st_list { 24 | struct st_list *prev,*next; 25 | void *data; 26 | } LIST; 27 | 28 | typedef int (*list_walk_action)(void *,void *); 29 | 30 | extern LIST *list_add(LIST *root,LIST *element); 31 | extern LIST *list_delete(LIST *root,LIST *element); 32 | extern LIST *list_cons(void *data,LIST *root); 33 | extern LIST *list_reverse(LIST *root); 34 | extern void list_free(LIST *root,unsigned int free_data); 35 | extern unsigned int list_length(LIST *); 36 | extern int list_walk(LIST *,list_walk_action action,unsigned char * argument); 37 | 38 | #define list_rest(a) ((a)->next) 39 | #define list_push(a,b) (a)=list_cons((b),(a)) 40 | #define list_pop(A) {LIST *old=(A); (A)=list_delete(old,old); my_free(old); } 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | #endif 46 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/my_thread.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ 15 | 16 | /* Defines to make different thread packages compatible */ 17 | 18 | #ifndef MY_THREAD_INCLUDED 19 | #define MY_THREAD_INCLUDED 20 | 21 | #include "my_global.h" /* my_bool */ 22 | 23 | #if !defined(_WIN32) 24 | #include 25 | #endif 26 | 27 | #ifndef ETIME 28 | #define ETIME ETIMEDOUT /* For FreeBSD */ 29 | #endif 30 | 31 | #ifndef ETIMEDOUT 32 | #define ETIMEDOUT 145 /* Win32 doesn't have this */ 33 | #endif 34 | 35 | /* 36 | MySQL can survive with 32K, but some glibc libraries require > 128K stack 37 | To resolve hostnames. Also recursive stored procedures needs stack. 38 | */ 39 | #if SIZEOF_CHARP > 4 40 | #define DEFAULT_THREAD_STACK (256*1024L) 41 | #else 42 | #define DEFAULT_THREAD_STACK (192*1024) 43 | #endif 44 | 45 | #ifdef __cplusplus 46 | #define EXTERNC extern "C" 47 | #else 48 | #define EXTERNC 49 | #endif 50 | 51 | C_MODE_START 52 | 53 | #ifdef _WIN32 54 | typedef volatile LONG my_thread_once_t; 55 | typedef DWORD my_thread_t; 56 | typedef struct thread_attr 57 | { 58 | DWORD dwStackSize; 59 | int detachstate; 60 | } my_thread_attr_t; 61 | #define MY_THREAD_CREATE_JOINABLE 0 62 | #define MY_THREAD_CREATE_DETACHED 1 63 | typedef void * (__cdecl *my_start_routine)(void *); 64 | #define MY_THREAD_ONCE_INIT 0 65 | #define MY_THREAD_ONCE_INPROGRESS 1 66 | #define MY_THREAD_ONCE_DONE 2 67 | #else 68 | typedef pthread_once_t my_thread_once_t; 69 | typedef pthread_t my_thread_t; 70 | typedef pthread_attr_t my_thread_attr_t; 71 | #define MY_THREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE 72 | #define MY_THREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED 73 | typedef void *(* my_start_routine)(void *); 74 | #define MY_THREAD_ONCE_INIT PTHREAD_ONCE_INIT 75 | #endif 76 | 77 | typedef struct st_my_thread_handle 78 | { 79 | my_thread_t thread; 80 | #ifdef _WIN32 81 | HANDLE handle; 82 | #endif 83 | } my_thread_handle; 84 | 85 | int my_thread_once(my_thread_once_t *once_control, void (*init_routine)(void)); 86 | 87 | static inline my_thread_t my_thread_self() 88 | { 89 | #ifdef _WIN32 90 | return GetCurrentThreadId(); 91 | #else 92 | return pthread_self(); 93 | #endif 94 | } 95 | 96 | static inline int my_thread_equal(my_thread_t t1, my_thread_t t2) 97 | { 98 | #ifdef _WIN32 99 | return t1 == t2; 100 | #else 101 | return pthread_equal(t1, t2); 102 | #endif 103 | } 104 | 105 | static inline int my_thread_attr_init(my_thread_attr_t *attr) 106 | { 107 | #ifdef _WIN32 108 | attr->dwStackSize= 0; 109 | /* Set to joinable by default to match Linux */ 110 | attr->detachstate= MY_THREAD_CREATE_JOINABLE; 111 | return 0; 112 | #else 113 | return pthread_attr_init(attr); 114 | #endif 115 | } 116 | 117 | static inline int my_thread_attr_destroy(my_thread_attr_t *attr) 118 | { 119 | #ifdef _WIN32 120 | attr->dwStackSize= 0; 121 | /* Set to joinable by default to match Linux */ 122 | attr->detachstate= MY_THREAD_CREATE_JOINABLE; 123 | return 0; 124 | #else 125 | return pthread_attr_destroy(attr); 126 | #endif 127 | } 128 | 129 | static inline int my_thread_attr_setstacksize(my_thread_attr_t *attr, 130 | size_t stacksize) 131 | { 132 | #ifdef _WIN32 133 | attr->dwStackSize= (DWORD)stacksize; 134 | return 0; 135 | #else 136 | return pthread_attr_setstacksize(attr, stacksize); 137 | #endif 138 | } 139 | 140 | static inline int my_thread_attr_setdetachstate(my_thread_attr_t *attr, 141 | int detachstate) 142 | { 143 | #ifdef _WIN32 144 | attr->detachstate= detachstate; 145 | return 0; 146 | #else 147 | return pthread_attr_setdetachstate(attr, detachstate); 148 | #endif 149 | } 150 | 151 | static inline int my_thread_attr_getstacksize(my_thread_attr_t *attr, 152 | size_t *stacksize) 153 | { 154 | #ifdef _WIN32 155 | *stacksize= (size_t)attr->dwStackSize; 156 | return 0; 157 | #else 158 | return pthread_attr_getstacksize(attr, stacksize); 159 | #endif 160 | } 161 | 162 | static inline void my_thread_yield() 163 | { 164 | #ifdef _WIN32 165 | SwitchToThread(); 166 | #else 167 | sched_yield(); 168 | #endif 169 | } 170 | 171 | int my_thread_create(my_thread_handle *thread, const my_thread_attr_t *attr, 172 | my_start_routine func, void *arg); 173 | int my_thread_join(my_thread_handle *thread, void **value_ptr); 174 | int my_thread_cancel(my_thread_handle *thread); 175 | void my_thread_exit(void *value_ptr); 176 | 177 | 178 | extern my_bool my_thread_global_init(); 179 | extern void my_thread_global_reinit(); 180 | extern void my_thread_global_end(); 181 | extern my_bool my_thread_init(); 182 | extern void my_thread_end(); 183 | 184 | C_MODE_END 185 | 186 | #endif /* MY_THREAD_INCLUDED */ 187 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/my_thread_local.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ 15 | 16 | #ifndef MY_THREAD_LOCAL_INCLUDED 17 | #define MY_THREAD_LOCAL_INCLUDED 18 | 19 | #ifndef _WIN32 20 | #include 21 | #endif 22 | 23 | struct _db_code_state_; 24 | typedef uint32 my_thread_id; 25 | 26 | C_MODE_START 27 | 28 | #ifdef _WIN32 29 | typedef DWORD thread_local_key_t; 30 | #else 31 | typedef pthread_key_t thread_local_key_t; 32 | #endif 33 | 34 | static inline int my_create_thread_local_key(thread_local_key_t *key, 35 | void (*destructor)(void *)) 36 | { 37 | #ifdef _WIN32 38 | *key= TlsAlloc(); 39 | return (*key == TLS_OUT_OF_INDEXES); 40 | #else 41 | return pthread_key_create(key, destructor); 42 | #endif 43 | } 44 | 45 | static inline int my_delete_thread_local_key(thread_local_key_t key) 46 | { 47 | #ifdef _WIN32 48 | return !TlsFree(key); 49 | #else 50 | return pthread_key_delete(key); 51 | #endif 52 | } 53 | 54 | static inline void* my_get_thread_local(thread_local_key_t key) 55 | { 56 | #ifdef _WIN32 57 | return TlsGetValue(key); 58 | #else 59 | return pthread_getspecific(key); 60 | #endif 61 | } 62 | 63 | static inline int my_set_thread_local(thread_local_key_t key, 64 | void *value) 65 | { 66 | #ifdef _WIN32 67 | return !TlsSetValue(key, value); 68 | #else 69 | return pthread_setspecific(key, value); 70 | #endif 71 | } 72 | 73 | /** 74 | Retrieve the MySQL thread-local storage variant of errno. 75 | */ 76 | int my_errno(); 77 | 78 | /** 79 | Set the MySQL thread-local storage variant of errno. 80 | */ 81 | void set_my_errno(int my_errno); 82 | 83 | #ifdef _WIN32 84 | /* 85 | thr_winerr is used for returning the original OS error-code in Windows, 86 | my_osmaperr() returns EINVAL for all unknown Windows errors, hence we 87 | preserve the original Windows Error code in thr_winerr. 88 | */ 89 | int thr_winerr(); 90 | 91 | void set_thr_winerr(int winerr); 92 | 93 | #endif 94 | 95 | #ifndef DBUG_OFF 96 | /* Return pointer to DBUG for holding current state */ 97 | struct _db_code_state_ **my_thread_var_dbug(); 98 | 99 | my_thread_id my_thread_var_id(); 100 | 101 | void set_my_thread_var_id(my_thread_id id); 102 | 103 | #endif 104 | 105 | C_MODE_END 106 | 107 | #endif // MY_THREAD_LOCAL_INCLUDED 108 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/my_xml.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ 15 | 16 | 17 | #ifndef _my_xml_h 18 | #define _my_xml_h 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | 25 | #define MY_XML_OK 0 26 | #define MY_XML_ERROR 1 27 | 28 | /* 29 | A flag whether to use absolute tag names in call-back functions, 30 | like "a", "a.b" and "a.b.c" (used in character set file parser), 31 | or relative names like "a", "b" and "c". 32 | */ 33 | #define MY_XML_FLAG_RELATIVE_NAMES 1 34 | 35 | /* 36 | A flag whether to skip normilization of text values before calling 37 | call-back functions: i.e. skip leading/trailing spaces, 38 | \r, \n, \t characters. 39 | */ 40 | #define MY_XML_FLAG_SKIP_TEXT_NORMALIZATION 2 41 | 42 | enum my_xml_node_type 43 | { 44 | MY_XML_NODE_TAG, /* can have TAG, ATTR and TEXT children */ 45 | MY_XML_NODE_ATTR, /* can have TEXT children */ 46 | MY_XML_NODE_TEXT /* cannot have children */ 47 | }; 48 | 49 | typedef struct xml_stack_st 50 | { 51 | int flags; 52 | enum my_xml_node_type current_node_type; 53 | char errstr[128]; 54 | 55 | struct { 56 | char static_buffer[128]; 57 | char *buffer; 58 | size_t buffer_size; 59 | char *start; 60 | char *end; 61 | } attr; 62 | 63 | const char *beg; 64 | const char *cur; 65 | const char *end; 66 | void *user_data; 67 | int (*enter)(struct xml_stack_st *st,const char *val, size_t len); 68 | int (*value)(struct xml_stack_st *st,const char *val, size_t len); 69 | int (*leave_xml)(struct xml_stack_st *st,const char *val, size_t len); 70 | } MY_XML_PARSER; 71 | 72 | void my_xml_parser_create(MY_XML_PARSER *st); 73 | void my_xml_parser_free(MY_XML_PARSER *st); 74 | int my_xml_parse(MY_XML_PARSER *st,const char *str, size_t len); 75 | 76 | void my_xml_set_value_handler(MY_XML_PARSER *st, int (*)(MY_XML_PARSER *, 77 | const char *, 78 | size_t len)); 79 | void my_xml_set_enter_handler(MY_XML_PARSER *st, int (*)(MY_XML_PARSER *, 80 | const char *, 81 | size_t len)); 82 | void my_xml_set_leave_handler(MY_XML_PARSER *st, int (*)(MY_XML_PARSER *, 83 | const char *, 84 | size_t len)); 85 | void my_xml_set_user_data(MY_XML_PARSER *st, void *); 86 | 87 | size_t my_xml_error_pos(MY_XML_PARSER *st); 88 | uint my_xml_error_lineno(MY_XML_PARSER *st); 89 | 90 | const char *my_xml_error_string(MY_XML_PARSER *st); 91 | 92 | #ifdef __cplusplus 93 | } 94 | #endif 95 | 96 | #endif /* _my_xml_h */ 97 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql/client_authentication.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | #ifndef CLIENT_AUTHENTICATION_H 16 | #define CLIENT_AUTHENTICATION_H 17 | #include 18 | #include "mysql.h" 19 | #include "mysql/client_plugin.h" 20 | 21 | C_MODE_START 22 | int sha256_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql); 23 | int sha256_password_init(char *, size_t, int, va_list); 24 | int sha256_password_deinit(void); 25 | C_MODE_END 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql/client_plugin.h.pp: -------------------------------------------------------------------------------- 1 | struct st_mysql_client_plugin 2 | { 3 | int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; const char *license; void *mysql_api; int (*init)(char *, size_t, int, va_list); int (*deinit)(void); int (*options)(const char *option, const void *); 4 | }; 5 | struct st_mysql; 6 | #include "plugin_auth_common.h" 7 | typedef struct st_plugin_vio_info 8 | { 9 | enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET, 10 | MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol; 11 | int socket; 12 | } MYSQL_PLUGIN_VIO_INFO; 13 | typedef struct st_plugin_vio 14 | { 15 | int (*read_packet)(struct st_plugin_vio *vio, 16 | unsigned char **buf); 17 | int (*write_packet)(struct st_plugin_vio *vio, 18 | const unsigned char *packet, 19 | int packet_len); 20 | void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info); 21 | } MYSQL_PLUGIN_VIO; 22 | struct st_mysql_client_plugin_AUTHENTICATION 23 | { 24 | int type; unsigned int interface_version; const char *name; const char *author; const char *desc; unsigned int version[3]; const char *license; void *mysql_api; int (*init)(char *, size_t, int, va_list); int (*deinit)(void); int (*options)(const char *option, const void *); 25 | int (*authenticate_user)(MYSQL_PLUGIN_VIO *vio, struct st_mysql *mysql); 26 | }; 27 | struct st_mysql_client_plugin * 28 | mysql_load_plugin(struct st_mysql *mysql, const char *name, int type, 29 | int argc, ...); 30 | struct st_mysql_client_plugin * 31 | mysql_load_plugin_v(struct st_mysql *mysql, const char *name, int type, 32 | int argc, va_list args); 33 | struct st_mysql_client_plugin * 34 | mysql_client_find_plugin(struct st_mysql *mysql, const char *name, int type); 35 | struct st_mysql_client_plugin * 36 | mysql_client_register_plugin(struct st_mysql *mysql, 37 | struct st_mysql_client_plugin *plugin); 38 | int mysql_plugin_options(struct st_mysql_client_plugin *plugin, 39 | const char *option, const void *value); 40 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql/get_password.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | /* 17 | ** Ask for a password from tty 18 | ** This is an own file to avoid conflicts with curses 19 | */ 20 | 21 | #ifndef MYSQL_GET_PASSWORD_H_INCLUDED 22 | #define MYSQL_GET_PASSWORD_H_INCLUDED 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | typedef char *(* strdup_handler_t)(const char *, int); 29 | char *get_tty_password_ext(const char *opt_message, 30 | strdup_handler_t strdup_function); 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | 36 | #endif /* ! MYSQL_GET_PASSWORD_H_INCLUDED */ 37 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql/mysql_lex_string.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | #ifndef MYSQL_LEX_STRING_INCLUDED 17 | #define MYSQL_LEX_STRING_INCLUDED 18 | 19 | struct st_mysql_lex_string 20 | { 21 | char *str; 22 | size_t length; 23 | }; 24 | typedef struct st_mysql_lex_string MYSQL_LEX_STRING; 25 | 26 | struct st_mysql_const_lex_string 27 | { 28 | const char *str; 29 | size_t length; 30 | }; 31 | typedef struct st_mysql_const_lex_string MYSQL_LEX_CSTRING; 32 | 33 | #endif // MYSQL_LEX_STRING_INCLUDED 34 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql/plugin_auth_common.h: -------------------------------------------------------------------------------- 1 | #ifndef MYSQL_PLUGIN_AUTH_COMMON_INCLUDED 2 | /* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; version 2 of the License. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 16 | 17 | /** 18 | @file 19 | 20 | This file defines constants and data structures that are the same for 21 | both client- and server-side authentication plugins. 22 | */ 23 | #define MYSQL_PLUGIN_AUTH_COMMON_INCLUDED 24 | 25 | /** the max allowed length for a user name */ 26 | #define MYSQL_USERNAME_LENGTH 96 27 | 28 | /** 29 | return values of the plugin authenticate_user() method. 30 | */ 31 | 32 | /** 33 | Authentication failed, plugin internal error. 34 | An error occurred in the authentication plugin itself. 35 | These errors are reported in table performance_schema.host_cache, 36 | column COUNT_AUTH_PLUGIN_ERRORS. 37 | */ 38 | #define CR_AUTH_PLUGIN_ERROR 3 39 | /** 40 | Authentication failed, client server handshake. 41 | An error occurred during the client server handshake. 42 | These errors are reported in table performance_schema.host_cache, 43 | column COUNT_HANDSHAKE_ERRORS. 44 | */ 45 | #define CR_AUTH_HANDSHAKE 2 46 | /** 47 | Authentication failed, user credentials. 48 | For example, wrong passwords. 49 | These errors are reported in table performance_schema.host_cache, 50 | column COUNT_AUTHENTICATION_ERRORS. 51 | */ 52 | #define CR_AUTH_USER_CREDENTIALS 1 53 | /** 54 | Authentication failed. Additionally, all other CR_xxx values 55 | (libmysql error code) can be used too. 56 | 57 | The client plugin may set the error code and the error message directly 58 | in the MYSQL structure and return CR_ERROR. If a CR_xxx specific error 59 | code was returned, an error message in the MYSQL structure will be 60 | overwritten. If CR_ERROR is returned without setting the error in MYSQL, 61 | CR_UNKNOWN_ERROR will be user. 62 | */ 63 | #define CR_ERROR 0 64 | /** 65 | Authentication (client part) was successful. It does not mean that the 66 | authentication as a whole was successful, usually it only means 67 | that the client was able to send the user name and the password to the 68 | server. If CR_OK is returned, the libmysql reads the next packet expecting 69 | it to be one of OK, ERROR, or CHANGE_PLUGIN packets. 70 | */ 71 | #define CR_OK -1 72 | /** 73 | Authentication was successful. 74 | It means that the client has done its part successfully and also that 75 | a plugin has read the last packet (one of OK, ERROR, CHANGE_PLUGIN). 76 | In this case, libmysql will not read a packet from the server, 77 | but it will use the data at mysql->net.read_pos. 78 | 79 | A plugin may return this value if the number of roundtrips in the 80 | authentication protocol is not known in advance, and the client plugin 81 | needs to read one packet more to determine if the authentication is finished 82 | or not. 83 | */ 84 | #define CR_OK_HANDSHAKE_COMPLETE -2 85 | 86 | /** 87 | Flag to be passed back to server from authentication plugins via 88 | authenticated_as when proxy mapping should be done by the server. 89 | */ 90 | #define PROXY_FLAG 0 91 | 92 | /* 93 | We need HANDLE definition if on Windows. Define WIN32_LEAN_AND_MEAN (if 94 | not already done) to minimize amount of imported declarations. 95 | */ 96 | #ifdef _WIN32 97 | #ifndef WIN32_LEAN_AND_MEAN 98 | #define WIN32_LEAN_AND_MEAN 99 | #endif 100 | #include 101 | #endif 102 | 103 | typedef struct st_plugin_vio_info 104 | { 105 | enum { MYSQL_VIO_INVALID, MYSQL_VIO_TCP, MYSQL_VIO_SOCKET, 106 | MYSQL_VIO_PIPE, MYSQL_VIO_MEMORY } protocol; 107 | int socket; /**< it's set, if the protocol is SOCKET or TCP */ 108 | #ifdef _WIN32 109 | HANDLE handle; /**< it's set, if the protocol is PIPE or MEMORY */ 110 | #endif 111 | } MYSQL_PLUGIN_VIO_INFO; 112 | 113 | /** 114 | Provides plugin access to communication channel 115 | */ 116 | typedef struct st_plugin_vio 117 | { 118 | /** 119 | Plugin provides a pointer reference and this function sets it to the 120 | contents of any incoming packet. Returns the packet length, or -1 if 121 | the plugin should terminate. 122 | */ 123 | int (*read_packet)(struct st_plugin_vio *vio, 124 | unsigned char **buf); 125 | 126 | /** 127 | Plugin provides a buffer with data and the length and this 128 | function sends it as a packet. Returns 0 on success, 1 on failure. 129 | */ 130 | int (*write_packet)(struct st_plugin_vio *vio, 131 | const unsigned char *packet, 132 | int packet_len); 133 | 134 | /** 135 | Fills in a st_plugin_vio_info structure, providing the information 136 | about the connection. 137 | */ 138 | void (*info)(struct st_plugin_vio *vio, struct st_plugin_vio_info *info); 139 | 140 | } MYSQL_PLUGIN_VIO; 141 | 142 | #endif 143 | 144 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql/psi/mysql_idle.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software Foundation, 14 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ 15 | 16 | #ifndef MYSQL_IDLE_H 17 | #define MYSQL_IDLE_H 18 | 19 | /** 20 | @file mysql/psi/mysql_idle.h 21 | Instrumentation helpers for idle waits. 22 | */ 23 | 24 | #include "mysql/psi/psi.h" 25 | 26 | #ifndef PSI_IDLE_CALL 27 | #define PSI_IDLE_CALL(M) PSI_DYNAMIC_CALL(M) 28 | #endif 29 | 30 | /** 31 | @defgroup Idle_instrumentation Idle Instrumentation 32 | @ingroup Instrumentation_interface 33 | @{ 34 | */ 35 | 36 | /** 37 | @def MYSQL_START_IDLE_WAIT 38 | Instrumentation helper for table io_waits. 39 | This instrumentation marks the start of a wait event. 40 | @param LOCKER the locker 41 | @param STATE the locker state 42 | @sa MYSQL_END_IDLE_WAIT. 43 | */ 44 | #ifdef HAVE_PSI_IDLE_INTERFACE 45 | #define MYSQL_START_IDLE_WAIT(LOCKER, STATE) \ 46 | LOCKER= inline_mysql_start_idle_wait(STATE, __FILE__, __LINE__) 47 | #else 48 | #define MYSQL_START_IDLE_WAIT(LOCKER, STATE) \ 49 | do {} while (0) 50 | #endif 51 | 52 | /** 53 | @def MYSQL_END_IDLE_WAIT 54 | Instrumentation helper for idle waits. 55 | This instrumentation marks the end of a wait event. 56 | @param LOCKER the locker 57 | @sa MYSQL_START_IDLE_WAIT. 58 | */ 59 | #ifdef HAVE_PSI_IDLE_INTERFACE 60 | #define MYSQL_END_IDLE_WAIT(LOCKER) \ 61 | inline_mysql_end_idle_wait(LOCKER) 62 | #else 63 | #define MYSQL_END_IDLE_WAIT(LOCKER) \ 64 | do {} while (0) 65 | #endif 66 | 67 | #ifdef HAVE_PSI_IDLE_INTERFACE 68 | /** 69 | Instrumentation calls for MYSQL_START_IDLE_WAIT. 70 | @sa MYSQL_END_IDLE_WAIT. 71 | */ 72 | static inline struct PSI_idle_locker * 73 | inline_mysql_start_idle_wait(PSI_idle_locker_state *state, 74 | const char *src_file, int src_line) 75 | { 76 | struct PSI_idle_locker *locker; 77 | locker= PSI_IDLE_CALL(start_idle_wait)(state, src_file, src_line); 78 | return locker; 79 | } 80 | 81 | /** 82 | Instrumentation calls for MYSQL_END_IDLE_WAIT. 83 | @sa MYSQL_START_IDLE_WAIT. 84 | */ 85 | static inline void 86 | inline_mysql_end_idle_wait(struct PSI_idle_locker *locker) 87 | { 88 | if (likely(locker != NULL)) 89 | PSI_IDLE_CALL(end_idle_wait)(locker); 90 | } 91 | #endif 92 | 93 | /** @} (end of group Idle_instrumentation) */ 94 | 95 | #endif 96 | 97 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql/psi/mysql_mdl.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software Foundation, 14 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ 15 | 16 | #ifndef MYSQL_MDL_H 17 | #define MYSQL_MDL_H 18 | 19 | /** 20 | @file mysql/psi/mysql_mdl.h 21 | Instrumentation helpers for metadata locks. 22 | */ 23 | 24 | #include "mysql/psi/psi.h" 25 | 26 | #ifndef PSI_METADATA_CALL 27 | #define PSI_METADATA_CALL(M) PSI_DYNAMIC_CALL(M) 28 | #endif 29 | 30 | /** 31 | @defgroup Thread_instrumentation Metadata Instrumentation 32 | @ingroup Instrumentation_interface 33 | @{ 34 | */ 35 | 36 | /** 37 | @def mysql_mdl_create(K, M, A) 38 | Instrumented metadata lock creation. 39 | @param I Metadata lock identity 40 | @param K Metadata key 41 | @param T Metadata lock type 42 | @param D Metadata lock duration 43 | @param S Metadata lock status 44 | @param F request source file 45 | @param L request source line 46 | */ 47 | 48 | #ifdef HAVE_PSI_METADATA_INTERFACE 49 | #define mysql_mdl_create(I, K, T, D, S, F, L) \ 50 | inline_mysql_mdl_create(I, K, T, D, S, F, L) 51 | #else 52 | #define mysql_mdl_create(I, K, T, D, S, F, L) NULL 53 | #endif 54 | 55 | #ifdef HAVE_PSI_METADATA_INTERFACE 56 | #define mysql_mdl_set_status(L, S) \ 57 | inline_mysql_mdl_set_status(L, S) 58 | #else 59 | #define mysql_mdl_set_status(L, S) \ 60 | do {} while (0) 61 | #endif 62 | 63 | 64 | /** 65 | @def mysql_mdl_destroy(M) 66 | Instrumented metadata lock destruction. 67 | @param M Metadata lock 68 | */ 69 | #ifdef HAVE_PSI_METADATA_INTERFACE 70 | #define mysql_mdl_destroy(M) \ 71 | inline_mysql_mdl_destroy(M, __FILE__, __LINE__) 72 | #else 73 | #define mysql_mdl_destroy(M) \ 74 | do {} while (0) 75 | #endif 76 | 77 | #ifdef HAVE_PSI_METADATA_INTERFACE 78 | 79 | static inline PSI_metadata_lock * 80 | inline_mysql_mdl_create(void *identity, 81 | const MDL_key *mdl_key, 82 | enum_mdl_type mdl_type, 83 | enum_mdl_duration mdl_duration, 84 | MDL_ticket::enum_psi_status mdl_status, 85 | const char *src_file, uint src_line) 86 | { 87 | PSI_metadata_lock *result; 88 | 89 | /* static_cast: Fit a round C++ enum peg into a square C int hole ... */ 90 | result= PSI_METADATA_CALL(create_metadata_lock) 91 | (identity, 92 | mdl_key, 93 | static_cast (mdl_type), 94 | static_cast (mdl_duration), 95 | static_cast (mdl_status), 96 | src_file, src_line); 97 | 98 | return result; 99 | } 100 | 101 | static inline void inline_mysql_mdl_set_status( 102 | PSI_metadata_lock *psi, 103 | MDL_ticket::enum_psi_status mdl_status) 104 | { 105 | if (psi != NULL) 106 | PSI_METADATA_CALL(set_metadata_lock_status)(psi, mdl_status); 107 | } 108 | 109 | static inline void inline_mysql_mdl_destroy( 110 | PSI_metadata_lock *psi, 111 | const char *src_file, uint src_line) 112 | { 113 | if (psi != NULL) 114 | PSI_METADATA_CALL(destroy_metadata_lock)(psi); 115 | } 116 | #endif /* HAVE_PSI_METADATA_INTERFACE */ 117 | 118 | /** @} (end of group Metadata_instrumentation) */ 119 | 120 | #endif 121 | 122 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql/psi/mysql_memory.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software Foundation, 14 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ 15 | 16 | #ifndef MYSQL_MEMORY_H 17 | #define MYSQL_MEMORY_H 18 | 19 | /** 20 | @file mysql/psi/mysql_memory.h 21 | Instrumentation helpers for memory allocation. 22 | */ 23 | 24 | #include "mysql/psi/psi.h" 25 | 26 | #ifndef PSI_MEMORY_CALL 27 | #define PSI_MEMORY_CALL(M) PSI_DYNAMIC_CALL(M) 28 | #endif 29 | 30 | /** 31 | @defgroup Memory_instrumentation Memory Instrumentation 32 | @ingroup Instrumentation_interface 33 | @{ 34 | */ 35 | 36 | /** 37 | @def mysql_memory_register(P1, P2, P3) 38 | Memory registration. 39 | */ 40 | #define mysql_memory_register(P1, P2, P3) \ 41 | inline_mysql_memory_register(P1, P2, P3) 42 | 43 | static inline void inline_mysql_memory_register( 44 | #ifdef HAVE_PSI_MEMORY_INTERFACE 45 | const char *category, 46 | PSI_memory_info *info, 47 | int count) 48 | #else 49 | const char *category MY_ATTRIBUTE((unused)), 50 | void *info MY_ATTRIBUTE((unused)), 51 | int count MY_ATTRIBUTE((unused))) 52 | #endif 53 | { 54 | #ifdef HAVE_PSI_MEMORY_INTERFACE 55 | PSI_MEMORY_CALL(register_memory)(category, info, count); 56 | #endif 57 | } 58 | 59 | /** @} (end of group Memory_instrumentation) */ 60 | 61 | #endif 62 | 63 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql/psi/mysql_ps.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | #ifndef MYSQL_PS_H 17 | #define MYSQL_PS_H 18 | 19 | /** 20 | @file mysql/psi/mysql_ps.h 21 | Instrumentation helpers for prepared statements. 22 | */ 23 | 24 | #include "mysql/psi/psi.h" 25 | 26 | #ifndef PSI_PS_CALL 27 | #define PSI_PS_CALL(M) PSI_DYNAMIC_CALL(M) 28 | #endif 29 | 30 | #ifdef HAVE_PSI_PS_INTERFACE 31 | #define MYSQL_CREATE_PS(IDENTITY, ID, LOCKER, NAME, NAME_LENGTH, SQLTEXT, SQLTEXT_LENGTH) \ 32 | inline_mysql_create_prepared_stmt(IDENTITY, ID, LOCKER, NAME, NAME_LENGTH, SQLTEXT, SQLTEXT_LENGTH) 33 | #define MYSQL_EXECUTE_PS(LOCKER, PREPARED_STMT) \ 34 | inline_mysql_execute_prepared_stmt(LOCKER, PREPARED_STMT) 35 | #define MYSQL_DESTROY_PS(PREPARED_STMT) \ 36 | inline_mysql_destroy_prepared_stmt(PREPARED_STMT) 37 | #define MYSQL_REPREPARE_PS(PREPARED_STMT) \ 38 | inline_mysql_reprepare_prepared_stmt(PREPARED_STMT) 39 | #else 40 | #define MYSQL_CREATE_PS(IDENTITY, ID, LOCKER, NAME, NAME_LENGTH, SQLTEXT, SQLTEXT_LENGTH) \ 41 | NULL 42 | #define MYSQL_EXECUTE_PS(LOCKER, PREPARED_STMT) \ 43 | do {} while (0) 44 | #define MYSQL_DESTROY_PS(PREPARED_STMT) \ 45 | do {} while (0) 46 | #define MYSQL_REPREPARE_PS(PREPARED_STMT) \ 47 | do {} while (0) 48 | #endif 49 | 50 | #ifdef HAVE_PSI_PS_INTERFACE 51 | static inline struct PSI_prepared_stmt* 52 | inline_mysql_create_prepared_stmt(void *identity, uint stmt_id, 53 | PSI_statement_locker *locker, 54 | const char *stmt_name, size_t stmt_name_length, 55 | const char *sqltext, size_t sqltext_length) 56 | { 57 | if (locker == NULL) 58 | return NULL; 59 | return PSI_PS_CALL(create_prepared_stmt)(identity, stmt_id, 60 | locker, 61 | stmt_name, stmt_name_length, 62 | sqltext, sqltext_length); 63 | } 64 | 65 | static inline void 66 | inline_mysql_execute_prepared_stmt(PSI_statement_locker *locker, 67 | PSI_prepared_stmt* prepared_stmt) 68 | { 69 | if (prepared_stmt != NULL && locker != NULL) 70 | PSI_PS_CALL(execute_prepared_stmt)(locker, prepared_stmt); 71 | } 72 | 73 | static inline void 74 | inline_mysql_destroy_prepared_stmt(PSI_prepared_stmt *prepared_stmt) 75 | { 76 | if (prepared_stmt != NULL) 77 | PSI_PS_CALL(destroy_prepared_stmt)(prepared_stmt); 78 | } 79 | 80 | static inline void 81 | inline_mysql_reprepare_prepared_stmt(PSI_prepared_stmt *prepared_stmt) 82 | { 83 | if (prepared_stmt != NULL) 84 | PSI_PS_CALL(reprepare_prepared_stmt)(prepared_stmt); 85 | } 86 | #endif 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql/psi/mysql_sp.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | #ifndef MYSQL_SP_H 17 | #define MYSQL_SP_H 18 | 19 | /** 20 | @file mysql/psi/mysql_sp.h 21 | Instrumentation helpers for stored programs. 22 | */ 23 | 24 | #include "mysql/psi/psi.h" 25 | 26 | #ifndef PSI_SP_CALL 27 | #define PSI_SP_CALL(M) PSI_DYNAMIC_CALL(M) 28 | #endif 29 | 30 | #ifdef HAVE_PSI_SP_INTERFACE 31 | #define MYSQL_START_SP(STATE, SP_SHARE) \ 32 | inline_mysql_start_sp(STATE, SP_SHARE) 33 | #else 34 | #define MYSQL_START_SP(STATE, SP_SHARE) \ 35 | NULL 36 | #endif 37 | 38 | 39 | #ifdef HAVE_PSI_SP_INTERFACE 40 | #define MYSQL_END_SP(LOCKER) \ 41 | inline_mysql_end_sp(LOCKER) 42 | #else 43 | #define MYSQL_END_SP(LOCKER) \ 44 | do {} while (0) 45 | #endif 46 | 47 | #ifdef HAVE_PSI_SP_INTERFACE 48 | #define MYSQL_DROP_SP(OT, SN, SNL, ON, ONL) \ 49 | inline_mysql_drop_sp(OT, SN, SNL, ON, ONL) 50 | #else 51 | #define MYSQL_DROP_SP(OT, SN, SNL, ON, ONL) \ 52 | do {} while (0) 53 | #endif 54 | 55 | #ifdef HAVE_PSI_SP_INTERFACE 56 | #define MYSQL_GET_SP_SHARE(OT, SN, SNL, ON, ONL) \ 57 | inline_mysql_get_sp_share(OT, SN, SNL, ON, ONL) 58 | #else 59 | #define MYSQL_GET_SP_SHARE(OT, SN, SNL, ON, ONL) \ 60 | NULL 61 | #endif 62 | 63 | #ifdef HAVE_PSI_SP_INTERFACE 64 | static inline struct PSI_sp_locker* 65 | inline_mysql_start_sp(PSI_sp_locker_state *state, PSI_sp_share *sp_share) 66 | { 67 | return PSI_SP_CALL(start_sp)(state, sp_share); 68 | } 69 | 70 | static inline void inline_mysql_end_sp(PSI_sp_locker *locker) 71 | { 72 | if (likely(locker != NULL)) 73 | PSI_SP_CALL(end_sp)(locker); 74 | } 75 | 76 | static inline void 77 | inline_mysql_drop_sp(uint sp_type, 78 | const char* schema_name, uint shcema_name_length, 79 | const char* object_name, uint object_name_length) 80 | { 81 | PSI_SP_CALL(drop_sp)(sp_type, 82 | schema_name, shcema_name_length, 83 | object_name, object_name_length); 84 | } 85 | 86 | static inline PSI_sp_share* 87 | inline_mysql_get_sp_share(uint sp_type, 88 | const char* schema_name, uint shcema_name_length, 89 | const char* object_name, uint object_name_length) 90 | { 91 | return PSI_SP_CALL(get_sp_share)(sp_type, 92 | schema_name, shcema_name_length, 93 | object_name, object_name_length); 94 | } 95 | #endif 96 | 97 | #endif 98 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql/psi/mysql_stage.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | #ifndef MYSQL_STAGE_H 17 | #define MYSQL_STAGE_H 18 | 19 | /** 20 | @file mysql/psi/mysql_stage.h 21 | Instrumentation helpers for stages. 22 | */ 23 | 24 | #include "mysql/psi/psi.h" 25 | 26 | #ifndef PSI_STAGE_CALL 27 | #define PSI_STAGE_CALL(M) PSI_DYNAMIC_CALL(M) 28 | #endif 29 | 30 | /** 31 | @defgroup Stage_instrumentation Stage Instrumentation 32 | @ingroup Instrumentation_interface 33 | @{ 34 | */ 35 | 36 | /** 37 | @def mysql_stage_register(P1, P2, P3) 38 | Stage registration. 39 | */ 40 | #ifdef HAVE_PSI_STAGE_INTERFACE 41 | #define mysql_stage_register(P1, P2, P3) \ 42 | inline_mysql_stage_register(P1, P2, P3) 43 | #else 44 | #define mysql_stage_register(P1, P2, P3) \ 45 | do {} while (0) 46 | #endif 47 | 48 | /** 49 | @def MYSQL_SET_STAGE 50 | Set the current stage. 51 | Use this API when the file and line 52 | is passed from the caller. 53 | @param K the stage key 54 | @param F the source file name 55 | @param L the source file line 56 | @return the current stage progress 57 | */ 58 | #ifdef HAVE_PSI_STAGE_INTERFACE 59 | #define MYSQL_SET_STAGE(K, F, L) \ 60 | inline_mysql_set_stage(K, F, L) 61 | #else 62 | #define MYSQL_SET_STAGE(K, F, L) \ 63 | NULL 64 | #endif 65 | 66 | /** 67 | @def mysql_set_stage 68 | Set the current stage. 69 | @param K the stage key 70 | @return the current stage progress 71 | */ 72 | #ifdef HAVE_PSI_STAGE_INTERFACE 73 | #define mysql_set_stage(K) \ 74 | inline_mysql_set_stage(K, __FILE__, __LINE__) 75 | #else 76 | #define mysql_set_stage(K) \ 77 | NULL 78 | #endif 79 | 80 | /** 81 | @def mysql_end_stage 82 | End the last stage 83 | */ 84 | #ifdef HAVE_PSI_STAGE_INTERFACE 85 | #define mysql_end_stage \ 86 | inline_mysql_end_stage 87 | #else 88 | #define mysql_end_stage \ 89 | do {} while (0) 90 | #endif 91 | 92 | #ifdef HAVE_PSI_STAGE_INTERFACE 93 | static inline void inline_mysql_stage_register( 94 | const char *category, PSI_stage_info **info, int count) 95 | { 96 | PSI_STAGE_CALL(register_stage)(category, info, count); 97 | } 98 | #endif 99 | 100 | #ifdef HAVE_PSI_STAGE_INTERFACE 101 | static inline PSI_stage_progress* 102 | inline_mysql_set_stage(PSI_stage_key key, 103 | const char *src_file, int src_line) 104 | { 105 | return PSI_STAGE_CALL(start_stage)(key, src_file, src_line); 106 | } 107 | #endif 108 | 109 | #ifdef HAVE_PSI_STAGE_INTERFACE 110 | static inline void 111 | inline_mysql_end_stage() 112 | { 113 | PSI_STAGE_CALL(end_stage)(); 114 | } 115 | #endif 116 | 117 | #ifdef HAVE_PSI_STAGE_INTERFACE 118 | #define mysql_stage_set_work_completed(P1, P2) \ 119 | inline_mysql_stage_set_work_completed(P1, P2) 120 | 121 | #define mysql_stage_get_work_completed(P1) \ 122 | inline_mysql_stage_get_work_completed(P1) 123 | #else 124 | #define mysql_stage_set_work_completed(P1, P2) \ 125 | do {} while (0) 126 | 127 | #define mysql_stage_get_work_completed(P1) \ 128 | do {} while (0) 129 | #endif 130 | 131 | #ifdef HAVE_PSI_STAGE_INTERFACE 132 | #define mysql_stage_inc_work_completed(P1, P2) \ 133 | inline_mysql_stage_inc_work_completed(P1, P2) 134 | #else 135 | #define mysql_stage_inc_work_completed(P1, P2) \ 136 | do {} while (0) 137 | #endif 138 | 139 | #ifdef HAVE_PSI_STAGE_INTERFACE 140 | #define mysql_stage_set_work_estimated(P1, P2) \ 141 | inline_mysql_stage_set_work_estimated(P1, P2) 142 | 143 | #define mysql_stage_get_work_estimated(P1) \ 144 | inline_mysql_stage_get_work_estimated(P1) 145 | #else 146 | #define mysql_stage_set_work_estimated(P1, P2) \ 147 | do {} while (0) 148 | 149 | #define mysql_stage_get_work_estimated(P1) \ 150 | do {} while (0) 151 | #endif 152 | 153 | #ifdef HAVE_PSI_STAGE_INTERFACE 154 | static inline void 155 | inline_mysql_stage_set_work_completed(PSI_stage_progress *progress, 156 | ulonglong val) 157 | { 158 | if (progress != NULL) 159 | progress->m_work_completed= val; 160 | } 161 | 162 | static inline ulonglong 163 | inline_mysql_stage_get_work_completed(PSI_stage_progress *progress) 164 | { 165 | return progress->m_work_completed; 166 | } 167 | #endif 168 | 169 | #ifdef HAVE_PSI_STAGE_INTERFACE 170 | static inline void 171 | inline_mysql_stage_inc_work_completed(PSI_stage_progress *progress, 172 | ulonglong val) 173 | { 174 | if (progress != NULL) 175 | progress->m_work_completed+= val; 176 | } 177 | #endif 178 | 179 | #ifdef HAVE_PSI_STAGE_INTERFACE 180 | static inline void 181 | inline_mysql_stage_set_work_estimated(PSI_stage_progress *progress, 182 | ulonglong val) 183 | { 184 | if (progress != NULL) 185 | progress->m_work_estimated= val; 186 | } 187 | 188 | static inline ulonglong 189 | inline_mysql_stage_get_work_estimated(PSI_stage_progress *progress) 190 | { 191 | return progress->m_work_estimated; 192 | } 193 | #endif 194 | 195 | /** @} (end of group Stage_instrumentation) */ 196 | 197 | #endif 198 | 199 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql/psi/mysql_table.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software Foundation, 14 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ 15 | 16 | #ifndef MYSQL_TABLE_H 17 | #define MYSQL_TABLE_H 18 | 19 | /** 20 | @file mysql/psi/mysql_table.h 21 | Instrumentation helpers for table io. 22 | */ 23 | 24 | #include "mysql/psi/psi.h" 25 | 26 | #ifndef PSI_TABLE_CALL 27 | #define PSI_TABLE_CALL(M) PSI_DYNAMIC_CALL(M) 28 | #endif 29 | 30 | /** 31 | @defgroup Table_instrumentation Table Instrumentation 32 | @ingroup Instrumentation_interface 33 | @{ 34 | */ 35 | 36 | /** 37 | @def MYSQL_TABLE_WAIT_VARIABLES 38 | Instrumentation helper for table waits. 39 | This instrumentation declares local variables. 40 | Do not use a ';' after this macro 41 | @param LOCKER the locker 42 | @param STATE the locker state 43 | @sa MYSQL_START_TABLE_IO_WAIT. 44 | @sa MYSQL_END_TABLE_IO_WAIT. 45 | @sa MYSQL_START_TABLE_LOCK_WAIT. 46 | @sa MYSQL_END_TABLE_LOCK_WAIT. 47 | */ 48 | #ifdef HAVE_PSI_TABLE_INTERFACE 49 | #define MYSQL_TABLE_WAIT_VARIABLES(LOCKER, STATE) \ 50 | struct PSI_table_locker* LOCKER; \ 51 | PSI_table_locker_state STATE; 52 | #else 53 | #define MYSQL_TABLE_WAIT_VARIABLES(LOCKER, STATE) 54 | #endif 55 | 56 | /** 57 | @def MYSQL_START_TABLE_LOCK_WAIT 58 | Instrumentation helper for table lock waits. 59 | This instrumentation marks the start of a wait event. 60 | @param LOCKER the locker 61 | @param STATE the locker state 62 | @param PSI the instrumented table 63 | @param OP the table operation to be performed 64 | @param FLAGS per table operation flags. 65 | @sa MYSQL_END_TABLE_LOCK_WAIT. 66 | */ 67 | #ifdef HAVE_PSI_TABLE_INTERFACE 68 | #define MYSQL_START_TABLE_LOCK_WAIT(LOCKER, STATE, PSI, OP, FLAGS) \ 69 | LOCKER= inline_mysql_start_table_lock_wait(STATE, PSI, \ 70 | OP, FLAGS, __FILE__, __LINE__) 71 | #else 72 | #define MYSQL_START_TABLE_LOCK_WAIT(LOCKER, STATE, PSI, OP, FLAGS) \ 73 | do {} while (0) 74 | #endif 75 | 76 | /** 77 | @def MYSQL_END_TABLE_LOCK_WAIT 78 | Instrumentation helper for table lock waits. 79 | This instrumentation marks the end of a wait event. 80 | @param LOCKER the locker 81 | @sa MYSQL_START_TABLE_LOCK_WAIT. 82 | */ 83 | #ifdef HAVE_PSI_TABLE_INTERFACE 84 | #define MYSQL_END_TABLE_LOCK_WAIT(LOCKER) \ 85 | inline_mysql_end_table_lock_wait(LOCKER) 86 | #else 87 | #define MYSQL_END_TABLE_LOCK_WAIT(LOCKER) \ 88 | do {} while (0) 89 | #endif 90 | 91 | #ifdef HAVE_PSI_TABLE_INTERFACE 92 | #define MYSQL_UNLOCK_TABLE(T) \ 93 | inline_mysql_unlock_table(T) 94 | #else 95 | #define MYSQL_UNLOCK_TABLE(T) \ 96 | do {} while (0) 97 | #endif 98 | 99 | #ifdef HAVE_PSI_TABLE_INTERFACE 100 | /** 101 | Instrumentation calls for MYSQL_START_TABLE_LOCK_WAIT. 102 | @sa MYSQL_END_TABLE_LOCK_WAIT. 103 | */ 104 | static inline struct PSI_table_locker * 105 | inline_mysql_start_table_lock_wait(PSI_table_locker_state *state, 106 | struct PSI_table *psi, 107 | enum PSI_table_lock_operation op, 108 | ulong flags, const char *src_file, int src_line) 109 | { 110 | if (psi != NULL) 111 | { 112 | struct PSI_table_locker *locker; 113 | locker= PSI_TABLE_CALL(start_table_lock_wait) 114 | (state, psi, op, flags, src_file, src_line); 115 | return locker; 116 | } 117 | return NULL; 118 | } 119 | 120 | /** 121 | Instrumentation calls for MYSQL_END_TABLE_LOCK_WAIT. 122 | @sa MYSQL_START_TABLE_LOCK_WAIT. 123 | */ 124 | static inline void 125 | inline_mysql_end_table_lock_wait(struct PSI_table_locker *locker) 126 | { 127 | if (locker != NULL) 128 | PSI_TABLE_CALL(end_table_lock_wait)(locker); 129 | } 130 | 131 | static inline void 132 | inline_mysql_unlock_table(struct PSI_table *table) 133 | { 134 | if (table != NULL) 135 | PSI_TABLE_CALL(unlock_table)(table); 136 | } 137 | #endif 138 | 139 | /** @} (end of group Table_instrumentation) */ 140 | 141 | #endif 142 | 143 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql/psi/psi_base.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software Foundation, 14 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ 15 | 16 | #ifndef MYSQL_PSI_BASE_H 17 | #define MYSQL_PSI_BASE_H 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | /** 24 | @file mysql/psi/psi_base.h 25 | Performance schema instrumentation interface. 26 | 27 | @defgroup Instrumentation_interface Instrumentation Interface 28 | @ingroup Performance_schema 29 | @{ 30 | */ 31 | 32 | #define PSI_INSTRUMENT_ME 0 33 | 34 | #define PSI_NOT_INSTRUMENTED 0 35 | 36 | /** 37 | Global flag. 38 | This flag indicate that an instrumentation point is a global variable, 39 | or a singleton. 40 | */ 41 | #define PSI_FLAG_GLOBAL (1 << 0) 42 | 43 | /** 44 | Mutable flag. 45 | This flag indicate that an instrumentation point is a general placeholder, 46 | that can mutate into a more specific instrumentation point. 47 | */ 48 | #define PSI_FLAG_MUTABLE (1 << 1) 49 | 50 | #define PSI_FLAG_THREAD (1 << 2) 51 | 52 | /** 53 | Stage progress flag. 54 | This flag apply to the stage instruments only. 55 | It indicates the instrumentation provides progress data. 56 | */ 57 | #define PSI_FLAG_STAGE_PROGRESS (1 << 3) 58 | 59 | /** 60 | Shared Exclusive flag. 61 | Indicates that rwlock support the shared exclusive state. 62 | */ 63 | #define PSI_RWLOCK_FLAG_SX (1 << 4) 64 | 65 | /** 66 | Transferable flag. 67 | This flag indicate that an instrumented object can 68 | be created by a thread and destroyed by another thread. 69 | */ 70 | #define PSI_FLAG_TRANSFER (1 << 5) 71 | 72 | /** 73 | Volatility flag. 74 | This flag indicate that an instrumented object 75 | has a volatility (life cycle) comparable 76 | to the volatility of a session. 77 | */ 78 | #define PSI_FLAG_VOLATILITY_SESSION (1 << 6) 79 | 80 | #ifdef HAVE_PSI_INTERFACE 81 | 82 | /** 83 | @def PSI_VERSION_1 84 | Performance Schema Interface number for version 1. 85 | This version is supported. 86 | */ 87 | #define PSI_VERSION_1 1 88 | 89 | /** 90 | @def PSI_VERSION_2 91 | Performance Schema Interface number for version 2. 92 | This version is not implemented, it's a placeholder. 93 | */ 94 | #define PSI_VERSION_2 2 95 | 96 | /** 97 | @def PSI_CURRENT_VERSION 98 | Performance Schema Interface number for the most recent version. 99 | The most current version is @c PSI_VERSION_1 100 | */ 101 | #define PSI_CURRENT_VERSION 1 102 | 103 | /** 104 | @def USE_PSI_1 105 | Define USE_PSI_1 to use the interface version 1. 106 | */ 107 | 108 | /** 109 | @def USE_PSI_2 110 | Define USE_PSI_2 to use the interface version 2. 111 | */ 112 | 113 | /** 114 | @def HAVE_PSI_1 115 | Define HAVE_PSI_1 if the interface version 1 needs to be compiled in. 116 | */ 117 | 118 | /** 119 | @def HAVE_PSI_2 120 | Define HAVE_PSI_2 if the interface version 2 needs to be compiled in. 121 | */ 122 | 123 | #ifndef USE_PSI_2 124 | #ifndef USE_PSI_1 125 | #define USE_PSI_1 126 | #endif 127 | #endif 128 | 129 | #ifdef USE_PSI_1 130 | #define HAVE_PSI_1 131 | #endif 132 | 133 | #ifdef USE_PSI_2 134 | #define HAVE_PSI_2 135 | #endif 136 | 137 | /* 138 | Allow to override PSI_XXX_CALL at compile time 139 | with more efficient implementations, if available. 140 | If nothing better is available, 141 | make a dynamic call using the PSI_server function pointer. 142 | */ 143 | 144 | #define PSI_DYNAMIC_CALL(M) PSI_server->M 145 | 146 | #endif /* HAVE_PSI_INTERFACE */ 147 | 148 | /** @} */ 149 | 150 | #ifdef __cplusplus 151 | } 152 | #endif 153 | 154 | #endif /* MYSQL_PSI_BASE_H */ 155 | 156 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql/psi/psi_memory.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software Foundation, 14 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ 15 | 16 | #ifndef MYSQL_PSI_MEMORY_H 17 | #define MYSQL_PSI_MEMORY_H 18 | 19 | #include "psi_base.h" 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | /** 26 | @file mysql/psi/psi_memory.h 27 | Performance schema instrumentation interface. 28 | 29 | @defgroup Instrumentation_interface Instrumentation Interface 30 | @ingroup Performance_schema 31 | @{ 32 | */ 33 | 34 | #ifdef HAVE_PSI_INTERFACE 35 | #ifndef DISABLE_ALL_PSI 36 | #ifndef DISABLE_PSI_MEMORY 37 | #define HAVE_PSI_MEMORY_INTERFACE 38 | #endif /* DISABLE_PSI_MEMORY */ 39 | #endif /* DISABLE_ALL_PSI */ 40 | #endif /* HAVE_PSI_INTERFACE */ 41 | 42 | struct PSI_thread; 43 | 44 | /** 45 | Instrumented memory key. 46 | To instrument memory, a memory key must be obtained using @c register_memory. 47 | Using a zero key always disable the instrumentation. 48 | */ 49 | typedef unsigned int PSI_memory_key; 50 | 51 | #ifdef HAVE_PSI_1 52 | 53 | /** 54 | @defgroup Group_PSI_v1 Application Binary Interface, version 1 55 | @ingroup Instrumentation_interface 56 | @{ 57 | */ 58 | 59 | /** 60 | Memory instrument information. 61 | @since PSI_VERSION_1 62 | This structure is used to register instrumented memory. 63 | */ 64 | struct PSI_memory_info_v1 65 | { 66 | /** Pointer to the key assigned to the registered memory. */ 67 | PSI_memory_key *m_key; 68 | /** The name of the memory instrument to register. */ 69 | const char *m_name; 70 | /** 71 | The flags of the socket instrument to register. 72 | @sa PSI_FLAG_GLOBAL 73 | */ 74 | int m_flags; 75 | }; 76 | typedef struct PSI_memory_info_v1 PSI_memory_info_v1; 77 | 78 | /** 79 | Memory registration API. 80 | @param category a category name (typically a plugin name) 81 | @param info an array of memory info to register 82 | @param count the size of the info array 83 | */ 84 | typedef void (*register_memory_v1_t) 85 | (const char *category, struct PSI_memory_info_v1 *info, int count); 86 | 87 | /** 88 | Instrument memory allocation. 89 | @param key the memory instrument key 90 | @param size the size of memory allocated 91 | @param[out] owner the memory owner 92 | @return the effective memory instrument key 93 | */ 94 | typedef PSI_memory_key (*memory_alloc_v1_t) 95 | (PSI_memory_key key, size_t size, struct PSI_thread ** owner); 96 | 97 | /** 98 | Instrument memory re allocation. 99 | @param key the memory instrument key 100 | @param old_size the size of memory previously allocated 101 | @param new_size the size of memory re allocated 102 | @param[in, out] owner the memory owner 103 | @return the effective memory instrument key 104 | */ 105 | typedef PSI_memory_key (*memory_realloc_v1_t) 106 | (PSI_memory_key key, size_t old_size, size_t new_size, struct PSI_thread ** owner); 107 | 108 | /** 109 | Instrument memory claim. 110 | @param key the memory instrument key 111 | @param size the size of memory allocated 112 | @param[in, out] owner the memory owner 113 | @return the effective memory instrument key 114 | */ 115 | typedef PSI_memory_key (*memory_claim_v1_t) 116 | (PSI_memory_key key, size_t size, struct PSI_thread ** owner); 117 | 118 | /** 119 | Instrument memory free. 120 | @param key the memory instrument key 121 | @param size the size of memory allocated 122 | @param owner the memory owner 123 | */ 124 | typedef void (*memory_free_v1_t) 125 | (PSI_memory_key key, size_t size, struct PSI_thread * owner); 126 | 127 | /** @} (end of group Group_PSI_v1) */ 128 | 129 | #endif /* HAVE_PSI_1 */ 130 | 131 | #ifdef HAVE_PSI_2 132 | struct PSI_memory_info_v2 133 | { 134 | int placeholder; 135 | }; 136 | 137 | #endif /* HAVE_PSI_2 */ 138 | 139 | #ifdef USE_PSI_1 140 | typedef struct PSI_memory_info_v1 PSI_memory_info; 141 | #endif 142 | 143 | #ifdef USE_PSI_2 144 | typedef struct PSI_memory_info_v2 PSI_memory_info; 145 | #endif 146 | 147 | /** @} (end of group Instrumentation_interface) */ 148 | 149 | #ifdef __cplusplus 150 | } 151 | #endif 152 | 153 | 154 | #endif /* MYSQL_PSI_MEMORY_H */ 155 | 156 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql/service_my_snprintf.h: -------------------------------------------------------------------------------- 1 | #ifndef MYSQL_SERVICE_MY_SNPRINTF_INCLUDED 2 | #define MYSQL_SERVICE_MY_SNPRINTF_INCLUDED 3 | /* Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. 4 | 5 | This program is free software; you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation; version 2 of the License. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 17 | 18 | /** 19 | @file 20 | my_snprintf service 21 | 22 | Portable and limited vsnprintf() implementation. 23 | 24 | This is a portable, limited vsnprintf() implementation, with some 25 | extra features. "Portable" means that it'll produce identical result 26 | on all platforms (for example, on Windows and Linux system printf %e 27 | formats the exponent differently, on different systems %p either 28 | prints leading 0x or not, %s may accept null pointer or crash on 29 | it). "Limited" means that it does not support all the C89 features. 30 | But it supports few extensions, not in any standard. 31 | 32 | my_vsnprintf(to, n, fmt, ap) 33 | 34 | @param[out] to A buffer to store the result in 35 | @param[in] n Store up to n-1 characters, followed by an end 0 36 | @param[in] fmt printf-like format string 37 | @param[in] ap Arguments 38 | 39 | @return a number of bytes written to a buffer *excluding* terminating '\0' 40 | 41 | @post 42 | The syntax of a format string is generally the same: 43 | % 44 | where everithing but the format is optional. 45 | 46 | Three one-character flags are recognized: 47 | '0' has the standard zero-padding semantics; 48 | '-' is parsed, but silently ignored; 49 | '`' (backtick) is only supported for strings (%s) and means that the 50 | string will be quoted according to MySQL identifier quoting rules. 51 | 52 | Both and can be specified as numbers or '*'. 53 | If an asterisk is used, an argument of type int is consumed. 54 | 55 | can be 'l', 'll', or 'z'. 56 | 57 | Supported formats are 's' (null pointer is accepted, printed as 58 | "(null)"), 'b' (extension, see below), 'c', 'd', 'i', 'u', 'x', 'o', 59 | 'X', 'p' (works as 0x%x). 60 | 61 | Standard syntax for positional arguments $n is supported. 62 | 63 | Extensions: 64 | 65 | Flag '`' (backtick): see above. 66 | 67 | Format 'b': binary buffer, prints exactly bytes from the 68 | argument, without stopping at '\0'. 69 | */ 70 | 71 | #ifdef __cplusplus 72 | extern "C" { 73 | #endif 74 | 75 | #ifndef MYSQL_ABI_CHECK 76 | #include 77 | #include 78 | #endif 79 | 80 | extern struct my_snprintf_service_st { 81 | size_t (*my_snprintf_type)(char*, size_t, const char*, ...); 82 | size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list); 83 | } *my_snprintf_service; 84 | 85 | #ifdef MYSQL_DYNAMIC_PLUGIN 86 | 87 | #define my_vsnprintf my_snprintf_service->my_vsnprintf_type 88 | #define my_snprintf my_snprintf_service->my_snprintf_type 89 | 90 | #else 91 | 92 | size_t my_snprintf(char* to, size_t n, const char* fmt, ...); 93 | size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap); 94 | 95 | #endif 96 | 97 | #ifdef __cplusplus 98 | } 99 | #endif 100 | 101 | #endif /* #define MYSQL_SERVICE_MY_SNPRINTF_INCLUDED */ 102 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql/service_mysql_alloc.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | #ifndef MYSQL_SERVICE_MYSQL_ALLOC_INCLUDED 17 | #define MYSQL_SERVICE_MYSQL_ALLOC_INCLUDED 18 | 19 | #ifndef MYSQL_ABI_CHECK 20 | #include 21 | #endif 22 | 23 | /* PSI_memory_key */ 24 | #include "mysql/psi/psi_memory.h" 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | /* myf */ 31 | typedef int myf_t; 32 | 33 | typedef void * (*mysql_malloc_t)(PSI_memory_key key, size_t size, myf_t flags); 34 | typedef void * (*mysql_realloc_t)(PSI_memory_key key, void *ptr, size_t size, myf_t flags); 35 | typedef void (*mysql_claim_t)(void *ptr); 36 | typedef void (*mysql_free_t)(void *ptr); 37 | typedef void * (*my_memdup_t)(PSI_memory_key key, const void *from, size_t length, myf_t flags); 38 | typedef char * (*my_strdup_t)(PSI_memory_key key, const char *from, myf_t flags); 39 | typedef char * (*my_strndup_t)(PSI_memory_key key, const char *from, size_t length, myf_t flags); 40 | 41 | struct mysql_malloc_service_st 42 | { 43 | mysql_malloc_t mysql_malloc; 44 | mysql_realloc_t mysql_realloc; 45 | mysql_claim_t mysql_claim; 46 | mysql_free_t mysql_free; 47 | my_memdup_t my_memdup; 48 | my_strdup_t my_strdup; 49 | my_strndup_t my_strndup; 50 | }; 51 | 52 | extern struct mysql_malloc_service_st *mysql_malloc_service; 53 | 54 | #ifdef MYSQL_DYNAMIC_PLUGIN 55 | 56 | #define my_malloc mysql_malloc_service->mysql_malloc 57 | #define my_realloc mysql_malloc_service->mysql_realloc 58 | #define my_claim mysql_malloc_service->mysql_claim 59 | #define my_free mysql_malloc_service->mysql_free 60 | #define my_memdup mysql_malloc_service->my_memdup 61 | #define my_strdup mysql_malloc_service->my_strdup 62 | #define my_strndup mysql_malloc_service->my_strndup 63 | 64 | #else 65 | 66 | extern void * my_malloc(PSI_memory_key key, size_t size, myf_t flags); 67 | extern void * my_realloc(PSI_memory_key key, void *ptr, size_t size, myf_t flags); 68 | extern void my_claim(void *ptr); 69 | extern void my_free(void *ptr); 70 | extern void * my_memdup(PSI_memory_key key, const void *from, size_t length, myf_t flags); 71 | extern char * my_strdup(PSI_memory_key key, const char *from, myf_t flags); 72 | extern char * my_strndup(PSI_memory_key key, const char *from, size_t length, myf_t flags); 73 | 74 | #endif 75 | 76 | #ifdef __cplusplus 77 | } 78 | #endif 79 | 80 | #endif 81 | 82 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql_com_server.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | /* 17 | Definitions private to the server, 18 | used in the networking layer to notify specific events. 19 | */ 20 | 21 | #ifndef _mysql_com_server_h 22 | #define _mysql_com_server_h 23 | 24 | struct st_net_server; 25 | 26 | typedef void (*before_header_callback_fn) 27 | (struct st_net *net, void *user_data, size_t count); 28 | 29 | typedef void (*after_header_callback_fn) 30 | (struct st_net *net, void *user_data, size_t count, my_bool rc); 31 | 32 | struct st_net_server 33 | { 34 | before_header_callback_fn m_before_header; 35 | after_header_callback_fn m_after_header; 36 | void *m_user_data; 37 | }; 38 | 39 | typedef struct st_net_server NET_SERVER; 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql_embed.h: -------------------------------------------------------------------------------- 1 | #ifndef MYSQL_EMBED_INCLUDED 2 | #define MYSQL_EMBED_INCLUDED 3 | 4 | /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 5 | 6 | This program is free software; you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation; version 2 of the License. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 18 | 19 | /* Defines that are unique to the embedded version of MySQL */ 20 | 21 | #ifdef EMBEDDED_LIBRARY 22 | 23 | /* Things we don't need in the embedded version of MySQL */ 24 | /* TODO HF add #undef HAVE_VIO if we don't want client in embedded library */ 25 | 26 | #undef HAVE_DLOPEN /* No udf functions */ 27 | 28 | #endif /* EMBEDDED_LIBRARY */ 29 | #endif /* MYSQL_EMBED_INCLUDED */ 30 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql_time.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ 15 | 16 | #ifndef _mysql_time_h_ 17 | #define _mysql_time_h_ 18 | 19 | /* 20 | Time declarations shared between the server and client API: 21 | you should not add anything to this header unless it's used 22 | (and hence should be visible) in mysql.h. 23 | If you're looking for a place to add new time-related declaration, 24 | it's most likely my_time.h. See also "C API Handling of Date 25 | and Time Values" chapter in documentation. 26 | */ 27 | 28 | enum enum_mysql_timestamp_type 29 | { 30 | MYSQL_TIMESTAMP_NONE= -2, MYSQL_TIMESTAMP_ERROR= -1, 31 | MYSQL_TIMESTAMP_DATE= 0, MYSQL_TIMESTAMP_DATETIME= 1, MYSQL_TIMESTAMP_TIME= 2 32 | }; 33 | 34 | 35 | /* 36 | Structure which is used to represent datetime values inside MySQL. 37 | 38 | We assume that values in this structure are normalized, i.e. year <= 9999, 39 | month <= 12, day <= 31, hour <= 23, hour <= 59, hour <= 59. Many functions 40 | in server such as my_system_gmt_sec() or make_time() family of functions 41 | rely on this (actually now usage of make_*() family relies on a bit weaker 42 | restriction). Also functions that produce MYSQL_TIME as result ensure this. 43 | There is one exception to this rule though if this structure holds time 44 | value (time_type == MYSQL_TIMESTAMP_TIME) days and hour member can hold 45 | bigger values. 46 | */ 47 | typedef struct st_mysql_time 48 | { 49 | unsigned int year, month, day, hour, minute, second; 50 | unsigned long second_part; /**< microseconds */ 51 | my_bool neg; 52 | enum enum_mysql_timestamp_type time_type; 53 | } MYSQL_TIME; 54 | 55 | #endif /* _mysql_time_h_ */ 56 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/mysql_version.h: -------------------------------------------------------------------------------- 1 | /* Copyright Abandoned 1996,1999 TCX DataKonsult AB & Monty Program KB 2 | & Detron HB, 1996, 1999-2004, 2007 MySQL AB. 3 | This file is public domain and comes with NO WARRANTY of any kind 4 | */ 5 | 6 | /* Version numbers for protocol & mysqld */ 7 | 8 | #ifndef _mysql_version_h 9 | #define _mysql_version_h 10 | #ifdef _CUSTOMCONFIG_ 11 | #include 12 | #else 13 | #define PROTOCOL_VERSION 10 14 | #define MYSQL_SERVER_VERSION "5.7.16" 15 | #define MYSQL_VERSION_ID 50716 16 | #define MYSQL_PORT 3306 17 | #define MYSQL_PORT_DEFAULT 0 18 | #define MYSQL_UNIX_ADDR "/tmp/mysql.sock" 19 | #define MYSQL_CONFIG_NAME "my" 20 | #define MYSQL_COMPILATION_COMMENT "MySQL Connector/C (GPL)" 21 | #define LIBMYSQL_VERSION "6.1.11" 22 | #define LIBMYSQL_VERSION_ID 60111 23 | 24 | /* mysqld compile time options */ 25 | #endif /* _CUSTOMCONFIG_ */ 26 | 27 | #ifndef LICENSE 28 | #define LICENSE GPL 29 | #endif /* LICENSE */ 30 | 31 | #endif /* _mysql_version_h */ 32 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/sslopt-case.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) 17 | 18 | #ifndef MYSQL_CLIENT 19 | #error This header is supposed to be used only in the client 20 | #endif 21 | 22 | case OPT_SSL_MODE: 23 | opt_ssl_mode= find_type_or_exit(argument, &ssl_mode_typelib, 24 | opt->name); 25 | ssl_mode_set_explicitly= TRUE; 26 | break; 27 | case OPT_SSL_SSL: 28 | CLIENT_WARN_DEPRECATED("--ssl", "--ssl-mode"); 29 | if (!opt_use_ssl_arg) 30 | opt_ssl_mode= SSL_MODE_DISABLED; 31 | else if (opt_ssl_mode < SSL_MODE_REQUIRED) 32 | opt_ssl_mode= SSL_MODE_REQUIRED; 33 | break; 34 | case OPT_SSL_VERIFY_SERVER_CERT: 35 | CLIENT_WARN_DEPRECATED("--ssl-verify-server-cert", 36 | "--ssl-mode=VERIFY_IDENTITY"); 37 | if (!opt_ssl_verify_server_cert_arg) 38 | { 39 | if (opt_ssl_mode >= SSL_MODE_VERIFY_IDENTITY) 40 | opt_ssl_mode= SSL_MODE_VERIFY_CA; 41 | } 42 | else 43 | opt_ssl_mode= SSL_MODE_VERIFY_IDENTITY; 44 | break; 45 | case OPT_SSL_CA: 46 | case OPT_SSL_CAPATH: 47 | /* Don't change ssl-mode if set explicitly. */ 48 | if (!ssl_mode_set_explicitly) 49 | opt_ssl_mode= SSL_MODE_VERIFY_CA; 50 | break; 51 | case OPT_SSL_KEY: 52 | case OPT_SSL_CERT: 53 | case OPT_SSL_CIPHER: 54 | case OPT_SSL_CRL: 55 | case OPT_SSL_CRLPATH: 56 | case OPT_TLS_VERSION: 57 | #ifdef HAVE_YASSL 58 | /* crl has no effect in yaSSL. */ 59 | opt_ssl_crl= NULL; 60 | opt_ssl_crlpath= NULL; 61 | #endif /* HAVE_YASSL */ 62 | break; 63 | #endif /* HAVE_OPENSSL */ 64 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/sslopt-longopts.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) 17 | #ifdef MYSQL_CLIENT 18 | {"ssl-mode", OPT_SSL_MODE, 19 | "SSL connection mode.", 20 | 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 21 | {"ssl", OPT_SSL_SSL, 22 | "Deprecated. Use --ssl-mode instead.", 23 | &opt_use_ssl_arg, &opt_use_ssl_arg, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, 24 | {"ssl-verify-server-cert", OPT_SSL_VERIFY_SERVER_CERT, 25 | "Deprecated. Use --ssl-mode=VERIFY_IDENTITY instead.", 26 | &opt_ssl_verify_server_cert_arg, &opt_ssl_verify_server_cert_arg, 27 | 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0}, 28 | #else 29 | {"ssl", OPT_SSL_SSL, 30 | "If set to ON, this option enforces that SSL is established before client " 31 | "attempts to authenticate to the server. To disable client SSL capabilities " 32 | "use --ssl=OFF.", 33 | &opt_use_ssl, &opt_use_ssl, 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0}, 34 | #endif 35 | {"ssl-ca", OPT_SSL_CA, 36 | "CA file in PEM format.", 37 | &opt_ssl_ca, &opt_ssl_ca, 0, GET_STR, REQUIRED_ARG, 38 | 0, 0, 0, 0, 0, 0}, 39 | {"ssl-capath", OPT_SSL_CAPATH, 40 | "CA directory.", 41 | &opt_ssl_capath, &opt_ssl_capath, 0, GET_STR, REQUIRED_ARG, 42 | 0, 0, 0, 0, 0, 0}, 43 | {"ssl-cert", OPT_SSL_CERT, "X509 cert in PEM format.", 44 | &opt_ssl_cert, &opt_ssl_cert, 0, GET_STR, REQUIRED_ARG, 45 | 0, 0, 0, 0, 0, 0}, 46 | {"ssl-cipher", OPT_SSL_CIPHER, "SSL cipher to use.", 47 | &opt_ssl_cipher, &opt_ssl_cipher, 0, GET_STR, REQUIRED_ARG, 48 | 0, 0, 0, 0, 0, 0}, 49 | {"ssl-key", OPT_SSL_KEY, "X509 key in PEM format.", 50 | &opt_ssl_key, &opt_ssl_key, 0, GET_STR, REQUIRED_ARG, 51 | 0, 0, 0, 0, 0, 0}, 52 | {"ssl-crl", OPT_SSL_CRL, "Certificate revocation list.", 53 | &opt_ssl_crl, &opt_ssl_crl, 0, GET_STR, REQUIRED_ARG, 54 | 0, 0, 0, 0, 0, 0}, 55 | {"ssl-crlpath", OPT_SSL_CRLPATH, 56 | "Certificate revocation list path.", 57 | &opt_ssl_crlpath, &opt_ssl_crlpath, 0, GET_STR, REQUIRED_ARG, 58 | 0, 0, 0, 0, 0, 0}, 59 | {"tls-version", OPT_TLS_VERSION, "TLS version to use, " 60 | #ifndef HAVE_YASSL 61 | "permitted values are: TLSv1, TLSv1.1, TLSv1.2", 62 | #else 63 | "permitted values are: TLSv1, TLSv1.1", 64 | #endif 65 | &opt_tls_version, &opt_tls_version, 0, GET_STR, REQUIRED_ARG, 66 | 0, 0, 0, 0, 0, 0}, 67 | #endif /* HAVE_OPENSSL */ 68 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/sslopt-vars.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 15 | 16 | #ifndef SSLOPT_VARS_INCLUDED 17 | #define SSLOPT_VARS_INCLUDED 18 | 19 | #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) 20 | 21 | #ifndef MYSQL_CLIENT 22 | #error This header is supposed to be used only in the client 23 | #endif 24 | 25 | const char *ssl_mode_names_lib[] = 26 | {"DISABLED", "PREFERRED", "REQUIRED", "VERIFY_CA", "VERIFY_IDENTITY", 27 | NullS }; 28 | TYPELIB ssl_mode_typelib = {array_elements(ssl_mode_names_lib) - 1, "", 29 | ssl_mode_names_lib, NULL}; 30 | 31 | static uint opt_ssl_mode = SSL_MODE_PREFERRED; 32 | static char *opt_ssl_ca = 0; 33 | static char *opt_ssl_capath = 0; 34 | static char *opt_ssl_cert = 0; 35 | static char *opt_ssl_cipher = 0; 36 | static char *opt_ssl_key = 0; 37 | static char *opt_ssl_crl = 0; 38 | static char *opt_ssl_crlpath = 0; 39 | static char *opt_tls_version = 0; 40 | static my_bool ssl_mode_set_explicitly= FALSE; 41 | static my_bool opt_use_ssl_arg= TRUE; 42 | static my_bool opt_ssl_verify_server_cert_arg= FALSE; 43 | 44 | static void set_client_ssl_options(MYSQL *mysql) 45 | { 46 | /* 47 | Print a warning if explicitly defined combination of --ssl-mode other than 48 | VERIFY_CA or VERIFY_IDENTITY with explicit --ssl-ca or --ssl-capath values. 49 | */ 50 | if (ssl_mode_set_explicitly && 51 | opt_ssl_mode < SSL_MODE_VERIFY_CA && 52 | (opt_ssl_ca || opt_ssl_capath)) 53 | { 54 | printf("WARNING: no verification of server certificate will be done. " 55 | "Use --ssl-mode=VERIFY_CA or VERIFY_IDENTITY.\n"); 56 | } 57 | 58 | /* Set SSL parameters: key, cert, ca, capath, cipher, clr, clrpath. */ 59 | if (opt_ssl_mode >= SSL_MODE_VERIFY_CA) 60 | mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, 61 | opt_ssl_capath, opt_ssl_cipher); 62 | else 63 | mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, NULL, 64 | NULL, opt_ssl_cipher); 65 | mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); 66 | mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); 67 | mysql_options(mysql, MYSQL_OPT_TLS_VERSION, opt_tls_version); 68 | mysql_options(mysql, MYSQL_OPT_SSL_MODE, &opt_ssl_mode); 69 | } 70 | 71 | #define SSL_SET_OPTIONS(mysql) set_client_ssl_options(mysql); 72 | #else 73 | #define SSL_SET_OPTIONS(mysql) do { } while(0) 74 | #endif 75 | #endif /* SSLOPT_VARS_INCLUDED */ 76 | -------------------------------------------------------------------------------- /common/mysql-connector-c/include/typelib.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; version 2 of the License. 6 | 7 | This program is distributed in the hope that it will be useful, 8 | but WITHOUT ANY WARRANTY; without even the implied warranty of 9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 | GNU General Public License for more details. 11 | 12 | You should have received a copy of the GNU General Public License 13 | along with this program; if not, write to the Free Software 14 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ 15 | 16 | 17 | #ifndef _typelib_h 18 | #define _typelib_h 19 | 20 | #include "my_alloc.h" 21 | 22 | typedef struct st_typelib { /* Different types saved here */ 23 | unsigned int count; /* How many types */ 24 | const char *name; /* Name of typelib */ 25 | const char **type_names; 26 | unsigned int *type_lengths; 27 | } TYPELIB; 28 | 29 | extern my_ulonglong find_typeset(char *x, TYPELIB *typelib,int *error_position); 30 | extern int find_type_or_exit(const char *x, TYPELIB *typelib, 31 | const char *option); 32 | #define FIND_TYPE_BASIC 0 33 | /** makes @c find_type() require the whole name, no prefix */ 34 | #define FIND_TYPE_NO_PREFIX (1 << 0) 35 | /** always implicitely on, so unused, but old code may pass it */ 36 | #define FIND_TYPE_NO_OVERWRITE (1 << 1) 37 | /** makes @c find_type() accept a number */ 38 | #define FIND_TYPE_ALLOW_NUMBER (1 << 2) 39 | /** makes @c find_type() treat ',' as terminator */ 40 | #define FIND_TYPE_COMMA_TERM (1 << 3) 41 | 42 | extern int find_type(const char *x, const TYPELIB *typelib, unsigned int flags); 43 | extern void make_type(char *to,unsigned int nr,TYPELIB *typelib); 44 | extern const char *get_type(TYPELIB *typelib,unsigned int nr); 45 | extern TYPELIB *copy_typelib(MEM_ROOT *root, TYPELIB *from); 46 | 47 | extern TYPELIB sql_protocol_typelib; 48 | 49 | my_ulonglong find_set_from_flags(const TYPELIB *lib, unsigned int default_name, 50 | my_ulonglong cur_set, my_ulonglong default_set, 51 | const char *str, unsigned int length, 52 | char **err_pos, unsigned int *err_len); 53 | 54 | #endif /* _typelib_h */ 55 | -------------------------------------------------------------------------------- /common/mysql-connector-c/lib/libmysqlclient.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeechanX/Easy-Load-Balancer/64bc1a74f7655dfb1968145ecfdf86537acbcd06/common/mysql-connector-c/lib/libmysqlclient.a -------------------------------------------------------------------------------- /common/mysql-connector-c/lib/libmysqlclient.so: -------------------------------------------------------------------------------- 1 | libmysqlclient.so.18 -------------------------------------------------------------------------------- /common/mysql-connector-c/lib/libmysqlclient.so.18: -------------------------------------------------------------------------------- 1 | libmysqlclient.so.18.4. -------------------------------------------------------------------------------- /common/mysql-connector-c/lib/libmysqlclient.so.18.4.: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeechanX/Easy-Load-Balancer/64bc1a74f7655dfb1968145ecfdf86537acbcd06/common/mysql-connector-c/lib/libmysqlclient.so.18.4. -------------------------------------------------------------------------------- /common/proto/Makefile: -------------------------------------------------------------------------------- 1 | CXX = g++ 2 | CFLAGS = -g -O2 -Wall 3 | 4 | all: 5 | protoc elb.proto --cpp_out=. 6 | 7 | clean: 8 | -rm *.cc *.h 9 | -------------------------------------------------------------------------------- /common/proto/elb.proto: -------------------------------------------------------------------------------- 1 | package elb; 2 | 3 | enum MsgTypeId { 4 | GetHostReqId = 1; //api get a host from agent 5 | GetHostRspId = 2; //agent give a host to api 6 | ReportReqId = 3; //api report call result to agent 7 | GetRouteByToolReqId = 4; //tool get route from agent 8 | GetRouteByToolRspId = 5; //agent give route to tool 9 | GetRouteByAgentReqId = 6; //agent get route from dnsserver 10 | GetRouteByAgentRspId = 7; //dnsserver give route to agent 11 | ReportStatusReqId = 8; //agent report lb status to reporter 12 | CacheGetRouteReqId = 9; //为支持API cache: api向agent发起获取\更新路由请求 13 | CacheGetRouteRspId = 10;//为支持API cache: agent给api返回的路由应答 14 | CacheBatchRptReqId = 11;//为支持API cache: api向agent批量上报若干成功结果 15 | } 16 | 17 | //represent a remote node 18 | message HostAddr { 19 | required int32 ip = 1; 20 | required int32 port = 2; 21 | } 22 | 23 | //api get a host from agent (UDP) 24 | message GetHostReq { 25 | required uint32 seq = 1; 26 | required int32 modid = 2; 27 | required int32 cmdid = 3; 28 | } 29 | 30 | //agent give a host to api (UDP) 31 | message GetHostRsp { 32 | required uint32 seq = 1; 33 | required int32 modid = 2; 34 | required int32 cmdid = 3; 35 | required int32 retcode = 4; 36 | optional HostAddr host = 5; 37 | } 38 | 39 | //api report call result to agent 40 | message ReportReq { 41 | required int32 modid = 1; 42 | required int32 cmdid = 2; 43 | required HostAddr host = 3; 44 | required int32 retcode = 4; 45 | optional uint32 tcost = 5;//如果调用失败,需要收集调用用时 46 | } 47 | 48 | //agent get route from dnsserver (TCP), or tool get route from agent (UDP) 49 | message GetRouteReq { 50 | required int32 modid = 1; 51 | required int32 cmdid = 2; 52 | } 53 | 54 | //dnsserver give route to agent (TCP), or agent give route to tool (UDP) 55 | message GetRouteRsp { 56 | required int32 modid = 1; 57 | required int32 cmdid = 2; 58 | repeated HostAddr hosts = 3; 59 | } 60 | 61 | //host call result 62 | message HostCallResult { 63 | required int32 ip = 1; 64 | required int32 port = 2; 65 | required uint32 succ = 3; 66 | required uint32 err = 4; 67 | required bool overload = 5; 68 | } 69 | 70 | //agent report lb status to reporter 71 | message ReportStatusReq { 72 | required int32 modid = 1; 73 | required int32 cmdid = 2; 74 | required int32 caller = 3; 75 | repeated HostCallResult results = 4; 76 | required uint32 ts = 5;//sec 77 | } 78 | 79 | //为支持API cache: api向agent发起获取\更新路由请求 80 | message CacheGetRouteReq { 81 | required int32 modid = 1; 82 | required int32 cmdid = 2; 83 | required int64 version = 3;//首次获取时,version=-1 84 | } 85 | 86 | //为支持API cache: agent给api返回的路由应答 87 | message CacheGetRouteRsp { 88 | required int32 modid = 1; 89 | required int32 cmdid = 2; 90 | required int64 version = 3;//agent不存在此mod,则version=-1 91 | optional bool overload = 4; 92 | repeated HostAddr route = 5; 93 | } 94 | 95 | //host batch call result 96 | message HostBatchCallRes { 97 | required int32 ip = 1; 98 | required int32 port = 2; 99 | required uint32 succCnt = 3; 100 | } 101 | 102 | //为支持API cache: api向agent批量上报若干成功结果 103 | message CacheBatchRptReq { 104 | required int32 modid = 1; 105 | required int32 cmdid = 2; 106 | repeated HostBatchCallRes results = 3; 107 | } 108 | -------------------------------------------------------------------------------- /common/protobuf/lib/libprotobuf.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeechanX/Easy-Load-Balancer/64bc1a74f7655dfb1968145ecfdf86537acbcd06/common/protobuf/lib/libprotobuf.a -------------------------------------------------------------------------------- /common/sql/dnsserver.sql: -------------------------------------------------------------------------------- 1 | DROP DATABASE if exists dnsserver; 2 | CREATE DATABASE dnsserver; 3 | USE dnsserver; 4 | 5 | DROP TABLE IF EXISTS `DnsServerRoute`; 6 | CREATE TABLE `DnsServerRoute` ( 7 | `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 8 | `modid` int(10) unsigned NOT NULL, 9 | `cmdid` int(10) unsigned NOT NULL, 10 | `serverip` int(10) unsigned NOT NULL, 11 | `serverport` int(10) unsigned NOT NULL, 12 | PRIMARY KEY (`id`) 13 | ) ENGINE=InnoDB AUTO_INCREMENT=116064 DEFAULT CHARSET=utf8; 14 | 15 | DROP TABLE IF EXISTS `ServerCallStatus`; 16 | CREATE TABLE `ServerCallStatus` ( 17 | `modid` int(11) NOT NULL, 18 | `cmdid` int(11) NOT NULL, 19 | `ip` int(11) NOT NULL, 20 | `port` int(11) NOT NULL, 21 | `caller` int(11) NOT NULL, 22 | `succ_cnt` int(11) NOT NULL, 23 | `err_cnt` int(11) NOT NULL, 24 | `ts` bigint(20) NOT NULL, 25 | `overload` char(1) NOT NULL, 26 | PRIMARY KEY (`modid`,`cmdid`,`ip`,`port`,`caller`), 27 | KEY `mlb_index` (`modid`,`cmdid`,`ip`,`port`,`caller`) 28 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 29 | 30 | DROP TABLE IF EXISTS `RouteVersion`; 31 | CREATE TABLE RouteVersion ( 32 | `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 33 | `version` int(10) unsigned NOT NULL, 34 | PRIMARY KEY (`id`) 35 | ); 36 | INSERT INTO RouteVersion(version) VALUES(0); 37 | 38 | DROP TABLE IF EXISTS `ChangeLog`; 39 | CREATE TABLE ChangeLog ( 40 | `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 41 | `modid` int(10) unsigned NOT NULL, 42 | `cmdid` int(10) unsigned NOT NULL, 43 | `version` bigint(20) unsigned NOT NULL, 44 | PRIMARY KEY (`id`) 45 | ); -------------------------------------------------------------------------------- /dnsserver/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = bin/dnsserver.prog 2 | CXX = g++ 3 | CFLAGS = -g -O2 -Wall 4 | 5 | COMMON = ../common 6 | BASE = $(COMMON)/base 7 | BASE_H = $(BASE)/include 8 | MYSQL = $(COMMON)/mysql-connector-c 9 | MYSQL_H = $(MYSQL)/include 10 | MYSQL_LIB = $(MYSQL)/lib/libmysqlclient.a 11 | PROTOBUF = $(COMMON)/protobuf 12 | PROTOBUF_LIB = $(PROTOBUF)/lib -lprotobuf 13 | OTHER_LIB = -lpthread -ldl 14 | EASYREACTOR = $(COMMON)/Easy-Reactor 15 | EASYREACTOR_H = $(EASYREACTOR)/include 16 | EASYREACTOR_LIB = $(EASYREACTOR)/lib -lereactor -lrt 17 | 18 | PROTO_H = $(COMMON)/proto 19 | 20 | INC = -Iinclude -I$(MYSQL_H) -I$(BASE_H) -I$(EASYREACTOR_H) -I$(PROTO_H) 21 | LIB = $(MYSQL_LIB) -L$(PROTOBUF_LIB) -L$(EASYREACTOR_LIB) $(OTHER_LIB) 22 | 23 | OBJS = $(addsuffix .o, $(basename $(wildcard src/*.cc))) 24 | OBJS += $(PROTO_H)/elb.pb.o $(BASE)/src/log.o 25 | 26 | $(TARGET): $(OBJS) 27 | -mkdir -p bin 28 | $(CXX) $(CFLAGS) -o $(TARGET) $(OBJS) $(INC) $(LIB) 29 | 30 | -include $(OBJS:.o=.d) 31 | 32 | %.o: %.cc 33 | $(CXX) $(CFLAGS) -c -o $@ $< $(INC) 34 | @$(CXX) -MM $*.cc $(INC) > $*.d 35 | @mv -f $*.d $*.d.tmp 36 | @sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d 37 | @sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \ 38 | sed -e 's/^ *//' -e 's/$$/:/' >> $*.d 39 | @rm -f $*.d.tmp 40 | 41 | .PHONY: clean 42 | 43 | clean: 44 | -rm -f $(OBJS) src/*.d $(PROTO_H)/elb.pb.d $(BASE)/src/log.d $(TARGET) 45 | -------------------------------------------------------------------------------- /dnsserver/README.md: -------------------------------------------------------------------------------- 1 | ## DNS Server Presentation 2 | ### **feature** 3 | 负责接收各agent对某modid、cmdid的请求并返回该modid、cmdid下的所有节点,即为agent提供获取路由服务 4 | ### **principle arch** 5 | ![Alt text](pictures/DnsServer-Arch.png) 6 | ### **server model** 7 | DnsServer服务模型采用了one loop per thread TCP服务器: 8 | - 主线程Accepter负责接收连接(agent端连接) 9 | - Thread loop们负责处理连接的请求、回复;(agent端发送查询请求,期望获取结果) 10 | 11 | ### **DB information** 12 | 13 | DnsServerRoute: 保存了所有mod路由信息 14 | 15 | RouteVersion: 当前DnsServerRoute路由版本号,每次管理端修改某mod的路由,RouteVersion表中的版本号都被更新为当前时间戳 16 | 17 | ChangeLog: 每次管理端修改某mod的路由,会记录本次对哪个mod进行修改(增、删、改),以便指示最新的DnsServerRoute路由有哪些mod变更了 18 | 19 | ### **business model** 20 | DnsServer使用两个map存储路由数据(key = `modid<<32 + cmdid` , value = set of `ip<<32 + port`) 21 | - 一个map:主数据,查询请求在此map执行 22 | - 另一个map:后台线程周期性重加载路由到此map,作为最新数据替换掉上一个map 23 | 24 | 这两个map分别由指针`data_ptr`与`tmp_ptr`指向 25 | 26 | #### **dnsserver还有个业务线程:** Backend Thread: 27 | 28 | 1、负责周期性(default:1s)检查RouteVersion表版本号,如有变化,说明DnsServerRoute有变更,则重加载DnsServerRoute表内容;然后将ChangeLog表中被变更的mod取出,根据订阅列表查出mod被哪些连接订阅后,向所有工作线程发送任务:要求订阅这些mod的连接推送mod路由到agent 29 | 30 | 2、此外,还负责周期性(default:8s)重加载DnsServerRoute表内容 31 | 32 | **PS:重加载DnsServerRoute表内容的细节** 33 | 34 | 重加载DnsServerRoute表内容到`tmp_ptr`指向的map,而后上写锁,交换指针`data_ptr`与`tmp_ptr`的地址,于是完成了路由数据更新 35 | 36 | ### **in service** 37 | 服务启动时,DnsServerRoute表被加载到`data_ptr`指向的map中, `tmp_ptr`指向的map为空 38 | 39 | 服务启动后,agent发来Query for 某modid/cmdid,其所在Thread Loop上,上读锁查询`data_ptr`指向的map,返回查询结果; 40 | 顺便如果此moid,cmdid不存在,则把agent ip+agent port+此moid+cmdid发送到Backend thread loop1的队列,让其记录到ClientMap 41 | 42 | 后台线程Backend thread每隔10s清空`tmp_ptr`指向的map,再加载DnsServerRoute表内容到`tmp_ptr`指向的map,加载成功后交换指针`data_ptr`与`tmp_ptr`指针内容,于是完成了路由数据的更新 43 | 44 | ### **performance** 45 | 46 | >服务器参数: 47 | >CPU个数:24 内存:128GB 网卡队列个数:24 48 | 49 | **QPS测试结果:** 50 | 51 | | dnsserverTCP服务线程数 | benchmark情况 | QPS | 52 | | :-----: | :-----: | :-----: | 53 | |3线程|6个benchmark,各建立100个连接| `25.83W/s` | 54 | |5线程|6个benchmark,各建立100个连接| `39.4W/s` | 55 | -------------------------------------------------------------------------------- /dnsserver/conf/dnsserver.ini: -------------------------------------------------------------------------------- 1 | [mysql] 2 | db_host=10.118.15.126 3 | db_port=6646 4 | db_user=dnsserver_x 5 | db_passwd=??? 6 | db_name=dnsserver 7 | ;重加载MySQL数据的周期(秒) 8 | load_interval=10 9 | [log] 10 | level=6 11 | [reactor] 12 | ;服务器线程池的线程个数 13 | threadNum = 3 14 | ;最大连接数 15 | maxConns = 1024 16 | ip=0.0.0.0 17 | port=12315 18 | -------------------------------------------------------------------------------- /dnsserver/include/Route.h: -------------------------------------------------------------------------------- 1 | #ifndef __ROUTE_H__ 2 | #define __ROUTE_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "mysql.h" 10 | #include "Singleton.h" 11 | 12 | using __gnu_cxx::hash_set; 13 | using __gnu_cxx::hash_map; 14 | 15 | typedef hash_map > routeMap; 16 | typedef hash_map >::iterator routeMapIt; 17 | typedef hash_set hostSet; 18 | typedef hash_set::iterator hostSetIt; 19 | 20 | class Route 21 | { 22 | public: 23 | //main threads call it 24 | hostSet getHosts(int modid, int cmdid); 25 | 26 | //backend thread call it 27 | int reload(); 28 | 29 | //backend thread call it 30 | void swap(); 31 | 32 | long routeVersion; 33 | 34 | int loadVersion(); 35 | 36 | void loadChanges(std::vector& changes); 37 | 38 | void rmChanges(bool recent = true); 39 | 40 | private: 41 | Route(); 42 | 43 | friend class Singleton; 44 | 45 | //~Route(); No need to write ~Route() 46 | 47 | MYSQL _dbConn; 48 | pthread_rwlock_t _rwlock; 49 | routeMap* _data; 50 | routeMap* _tmpData; 51 | 52 | char _sql[1000]; 53 | }; 54 | 55 | //backend thread domain 56 | void* dataLoader(void* args); 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /dnsserver/include/Server.h: -------------------------------------------------------------------------------- 1 | #ifndef __DNSSERVER_H_ 2 | #define __DNSSERVER_H_ 3 | 4 | #include 5 | #include 6 | #include "easy_reactor.h" 7 | 8 | extern tcp_server* server; 9 | 10 | struct Interest 11 | { 12 | std::set m; 13 | }; 14 | 15 | void pushChange(event_loop* loop, void* args); 16 | 17 | #endif -------------------------------------------------------------------------------- /dnsserver/include/SubscribeList.h: -------------------------------------------------------------------------------- 1 | #ifndef __SUBSCRIBELIST_H__ 2 | #define __SUBSCRIBELIST_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class SubscribeList 11 | { 12 | public: 13 | void subscribe(uint64_t mod, int fd); 14 | 15 | void unsubscribe(uint64_t mod, int fd); 16 | 17 | //将有变更的mod加入待push队列 18 | void push(std::vector& changes); 19 | 20 | void fetchPush(__gnu_cxx::hash_set& subscribers, 21 | __gnu_cxx::hash_map >& news); 22 | private: 23 | //记录订阅信息: mod -> fds 24 | __gnu_cxx::hash_map > bookl; 25 | pthread_mutex_t booklock; 26 | //记录已产生待push的消息: fd -> mods 27 | __gnu_cxx::hash_map > pushl; 28 | pthread_mutex_t pushlock; 29 | }; 30 | 31 | #endif -------------------------------------------------------------------------------- /dnsserver/pictures/DnsServer-Arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeechanX/Easy-Load-Balancer/64bc1a74f7655dfb1968145ecfdf86537acbcd06/dnsserver/pictures/DnsServer-Arch.png -------------------------------------------------------------------------------- /dnsserver/src/Server.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "log.h" 7 | #include "logo.h" 8 | #include "Route.h" 9 | #include "elb.pb.h" 10 | #include "Server.h" 11 | #include "SubscribeList.h" 12 | 13 | tcp_server* server; 14 | 15 | void getRoute(const char* data, uint32_t len, int msgid, net_commu* com, void* usr_data) 16 | { 17 | elb::GetRouteReq req; 18 | elb::GetRouteRsp rsp; 19 | req.ParseFromArray(data, len);//解包,data[0:len)保证是一个完整包 20 | 21 | if (!req.ParseFromArray(data, len)) 22 | { 23 | log_error("request decode error"); 24 | return ; 25 | } 26 | 27 | int modid = req.modid(), cmdid = req.cmdid(); 28 | 29 | //如果之前没有订阅过此mod,就订阅 30 | uint64_t key = (((uint64_t)modid) << 32) + cmdid; 31 | Interest* book = (Interest*)com->parameter; 32 | if (book->m.find(key) == book->m.end()) 33 | { 34 | book->m.insert(key); 35 | //记录到全局订阅列表 36 | Singleton::ins()->subscribe(key, com->get_fd()); 37 | } 38 | 39 | hostSet hosts = Singleton::ins()->getHosts(modid, cmdid); 40 | 41 | rsp.set_modid(modid); 42 | rsp.set_cmdid(cmdid); 43 | 44 | for (hostSetIt it = hosts.begin();it != hosts.end(); ++it) 45 | { 46 | uint64_t key = *it; 47 | elb::HostAddr host; 48 | host.set_ip((uint32_t)(key >> 32)); 49 | host.set_port((int)key); 50 | rsp.add_hosts()->CopyFrom(host); 51 | } 52 | 53 | std::string rspStr; 54 | rsp.SerializeToString(&rspStr); 55 | com->send_data(rspStr.c_str(), rspStr.size(), elb::GetRouteByAgentRspId);//回复消息 56 | } 57 | 58 | void createSubscribe(net_commu* com) 59 | { 60 | com->parameter = new Interest(); 61 | assert(com->parameter); 62 | } 63 | 64 | void clearSubscribe(net_commu* com) 65 | { 66 | std::set::iterator it; 67 | Interest* book = (Interest*)com->parameter; 68 | for (it = book->m.begin();it != book->m.end(); ++it) 69 | { 70 | uint64_t mod = *it; 71 | Singleton::ins()->unsubscribe(mod, com->get_fd()); 72 | } 73 | delete book; 74 | com->parameter = NULL; 75 | } 76 | 77 | void pushChange(event_loop* loop, void* args) 78 | { 79 | __gnu_cxx::hash_set listening; 80 | __gnu_cxx::hash_map > news; 81 | __gnu_cxx::hash_map >::iterator it; 82 | __gnu_cxx::hash_set::iterator st; 83 | 84 | loop->nlistenings(listening);//获取当前loop所有连接 85 | //从订阅列表取走所有待push消息 86 | Singleton::ins()->fetchPush(listening, news); 87 | for (it = news.begin();it != news.end(); ++it) 88 | { 89 | int fd = it->first; 90 | for (st = it->second.begin();st != it->second.end(); ++st) 91 | { 92 | int modid = (int)((*st) >> 32); 93 | int cmdid = (int)(*st); 94 | 95 | elb::GetRouteRsp rsp; 96 | rsp.set_modid(modid); 97 | rsp.set_cmdid(cmdid); 98 | 99 | hostSet hosts = Singleton::ins()->getHosts(modid, cmdid); 100 | for (hostSetIt ht = hosts.begin();ht != hosts.end(); ++ht) 101 | { 102 | uint64_t key = *ht; 103 | elb::HostAddr host; 104 | host.set_ip((uint32_t)(key >> 32)); 105 | host.set_port((int)key); 106 | rsp.add_hosts()->CopyFrom(host); 107 | } 108 | std::string rspStr; 109 | rsp.SerializeToString(&rspStr); 110 | net_commu* com = tcp_server::conns[fd]; 111 | com->send_data(rspStr.c_str(), rspStr.size(), elb::GetRouteByAgentRspId);//回复消息 112 | } 113 | } 114 | } 115 | 116 | int main() 117 | { 118 | event_loop loop; 119 | 120 | config_reader::setPath("dnsserver.ini"); 121 | std::string ip = config_reader::ins()->GetString("reactor", "ip", "0.0.0.0"); 122 | short port = config_reader::ins()->GetNumber("reactor", "port", 12315); 123 | 124 | dispLogo(); 125 | server = new tcp_server(&loop, ip.c_str(), port);//创建TCP服务器 126 | if (!server) 127 | { 128 | perror("malloc new tcp_server"); 129 | ::exit(1); 130 | } 131 | 132 | //设置:当收到消息id = GetRouteByAgentReqId (即获取路由)的消息调用的回调函数 133 | server->add_msg_cb(elb::GetRouteByAgentReqId, getRoute); 134 | 135 | //当连接建立,调用函数createSubscribe,创建保存自己所订阅mod的集合 136 | server->onConnBuild(createSubscribe); 137 | //当连接关闭,调用函数,删除自己所订阅mod 138 | server->onConnClose(clearSubscribe); 139 | 140 | _init_log_("dnsserver", "."); 141 | int log_level = config_reader::ins()->GetNumber("log", "level", 3); 142 | _set_log_level_(log_level); 143 | 144 | //thread: 周期性加载路由数据 145 | pthread_t tid; 146 | int ret = ::pthread_create(&tid, NULL, dataLoader, NULL); 147 | if (ret == -1) 148 | { 149 | perror("pthread_create"); 150 | ::exit(1); 151 | } 152 | ::pthread_detach(tid); 153 | 154 | loop.process_evs(); 155 | return 0; 156 | } 157 | -------------------------------------------------------------------------------- /dnsserver/src/SubscribeList.cc: -------------------------------------------------------------------------------- 1 | #include "SubscribeList.h" 2 | #include "Server.h" 3 | 4 | void SubscribeList::subscribe(uint64_t mod, int fd) 5 | { 6 | ::pthread_mutex_lock(&booklock); 7 | bookl[mod].insert(fd); 8 | ::pthread_mutex_unlock(&booklock); 9 | } 10 | 11 | void SubscribeList::unsubscribe(uint64_t mod, int fd) 12 | { 13 | ::pthread_mutex_lock(&booklock); 14 | if (bookl.find(mod) != bookl.end()) 15 | { 16 | bookl[mod].erase(fd); 17 | if (bookl[mod].empty()) 18 | { 19 | bookl.erase(mod); 20 | } 21 | } 22 | ::pthread_mutex_unlock(&booklock); 23 | } 24 | 25 | //将有变更的mod加入待push队列, 并通知各个线程 26 | void SubscribeList::push(std::vector& changes) 27 | { 28 | std::vector::iterator it; 29 | __gnu_cxx::hash_set::iterator st; 30 | 31 | ::pthread_mutex_lock(&booklock); 32 | ::pthread_mutex_lock(&pushlock); 33 | for (it = changes.begin();it != changes.end(); ++it) 34 | { 35 | uint64_t mod = *it; 36 | if (bookl.find(mod) != bookl.end()) 37 | { 38 | for (st = bookl[mod].begin();st != bookl[mod].end(); ++st) 39 | { 40 | int fd = *st; 41 | pushl[fd].insert(mod); 42 | } 43 | } 44 | } 45 | ::pthread_mutex_unlock(&pushlock); 46 | ::pthread_mutex_unlock(&booklock); 47 | 48 | //通知各个线程都去执行pushChange 49 | server->threadPool()->run_task(pushChange); 50 | } 51 | 52 | void SubscribeList::fetchPush(__gnu_cxx::hash_set& subscribers, 53 | __gnu_cxx::hash_map >& news) 54 | { 55 | __gnu_cxx::hash_map >::iterator it; 56 | ::pthread_mutex_lock(&pushlock); 57 | for (it = pushl.begin();it != pushl.end();) 58 | { 59 | if (subscribers.find(it->first) != subscribers.end()) 60 | { 61 | news[it->first] = pushl[it->first]; 62 | pushl.erase(it++); 63 | } 64 | else 65 | { 66 | ++it; 67 | } 68 | } 69 | ::pthread_mutex_unlock(&pushlock); 70 | } 71 | -------------------------------------------------------------------------------- /dnsserver/test/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = dss-benchmark.prog 2 | CXX = g++ 3 | CFLAGS = -g -O2 -Wall 4 | 5 | COMMON = ../../common 6 | PROTOBUF = $(COMMON)/protobuf 7 | PROTOBUF_LIB = $(PROTOBUF)/lib -lprotobuf 8 | OTHER_LIB = -lpthread -ldl 9 | EASYREACTOR = $(COMMON)/Easy-Reactor 10 | EASYREACTOR_H = $(EASYREACTOR)/include 11 | EASYREACTOR_LIB = $(EASYREACTOR)/lib -lereactor -lrt 12 | 13 | PROTO_H = $(COMMON)/proto 14 | 15 | INC = -Iinclude -I$(EASYREACTOR_H) -I$(PROTO_H) 16 | LIB = -L$(PROTOBUF_LIB) -L$(EASYREACTOR_LIB) $(OTHER_LIB) 17 | 18 | OBJS = benchmark.o 19 | OBJS += $(PROTO_H)/elb.pb.o 20 | 21 | $(TARGET): $(OBJS) 22 | $(CXX) $(CFLAGS) -o $(TARGET) $(OBJS) $(INC) $(LIB) 23 | 24 | -include $(OBJS:.o=.d) 25 | 26 | %.o: %.cc 27 | $(CXX) $(CFLAGS) -c -o $@ $< $(INC) 28 | @$(CXX) -MM $*.cc $(INC) > $*.d 29 | @mv -f $*.d $*.d.tmp 30 | @sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d 31 | @sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \ 32 | sed -e 's/^ *//' -e 's/$$/:/' >> $*.d 33 | @rm -f $*.d.tmp 34 | 35 | .PHONY: clean 36 | 37 | clean: 38 | -rm -f *.o *.d $(TARGET) 39 | -------------------------------------------------------------------------------- /dnsserver/test/benchmark.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "elb.pb.h" 10 | #include "easy_reactor.h" 11 | 12 | struct Config 13 | { 14 | Config(): hostip(NULL), hostPort(0), concurrency(0), total(0) {} 15 | char* hostip; 16 | short hostPort; 17 | int concurrency; 18 | long total; 19 | }; 20 | 21 | unsigned long getCurrentMills() 22 | { 23 | struct timeval tv; 24 | gettimeofday(&tv, NULL); 25 | return (unsigned long)tv.tv_sec * 1000 + tv.tv_usec / 1000; 26 | } 27 | 28 | Config config; 29 | unsigned long startTs, endTs; 30 | 31 | void parseOption(int argc, char** argv) 32 | { 33 | for (int i = 0;i < argc; ++i) 34 | { 35 | if (!strcmp(argv[i], "-h")) 36 | { 37 | config.hostip = argv[i + 1]; 38 | } 39 | else if (!strcmp(argv[i], "-p")) 40 | { 41 | config.hostPort = atoi(argv[i + 1]); 42 | } 43 | else if (!strcmp(argv[i], "-c")) 44 | { 45 | config.concurrency = atoi(argv[i + 1]); 46 | } 47 | else if (!strcmp(argv[i], "-n")) 48 | { 49 | config.total = atol(argv[i + 1]); 50 | } 51 | } 52 | if (!config.hostip || !config.hostPort || !config.concurrency || !config.total) 53 | { 54 | printf("./dss-benchmark -h ip -p port -c concurrency -n total\n"); 55 | exit(1); 56 | } 57 | } 58 | 59 | void ActionGetRoute(const char* data, uint32_t len, int msgId, net_commu* commu, void* usr_data) 60 | { 61 | long* count = (long*)usr_data; 62 | elb::GetRouteRsp rsp; 63 | //解包,data[0:len)保证是一个完整包 64 | rsp.ParseFromArray(data, len); 65 | 66 | *count = *count + 1; 67 | if (*count >= config.total) 68 | { 69 | endTs = getCurrentMills(); 70 | printf("communicate %ld times\n", *count); 71 | printf("time use %ldms\n", endTs - startTs); 72 | printf("qps %.2f\n", (*count * 1000.0) / (endTs - startTs)); 73 | exit(1); 74 | } 75 | 76 | int modid = rsp.modid(); 77 | int cmdid = rsp.cmdid(); 78 | elb::GetRouteReq req; 79 | req.set_modid(modid); 80 | req.set_cmdid(cmdid); 81 | std::string reqStr; 82 | req.SerializeToString(&reqStr); 83 | commu->send_data(reqStr.c_str(), reqStr.size(), elb::GetRouteByAgentReqId);//回复消息 84 | } 85 | 86 | void onConnectionCb(tcp_client* client, void *args) 87 | { 88 | unsigned long* startTsPtr = (unsigned long*)args; 89 | if (!*startTsPtr) 90 | *startTsPtr = getCurrentMills(); 91 | //连接建立后,主动发送消息 92 | elb::GetRouteReq req; 93 | req.set_modid(10001); 94 | req.set_cmdid(1001); 95 | std::string reqStr; 96 | req.SerializeToString(&reqStr); 97 | client->send_data(reqStr.c_str(), reqStr.size(), elb::GetRouteByAgentReqId); 98 | } 99 | 100 | int main(int argc, char** argv) 101 | { 102 | parseOption(argc, argv); 103 | long done = 0; 104 | event_loop loop; 105 | std::vector clients; 106 | for (int i = 0;i < config.concurrency; ++i) 107 | { 108 | tcp_client* cli = new tcp_client(&loop, config.hostip, config.hostPort);//创建TCP客户端 109 | if (!cli) exit(1); 110 | cli->add_msg_cb(elb::GetRouteByAgentRspId, ActionGetRoute, &done);//设置:当收到消息id=GetRouteByAgentRspId的消息时的回调函数 111 | cli->onConnection(onConnectionCb, &startTs);//当连接建立后,执行函数onConnectionCb 112 | clients.push_back(cli); 113 | } 114 | 115 | loop.process_evs(); 116 | 117 | for (int i = 0;i < config.concurrency; ++i) 118 | { 119 | tcp_client* cli = clients[i]; 120 | delete cli; 121 | } 122 | return 0; 123 | } 124 | -------------------------------------------------------------------------------- /lbagent/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = bin/lbagent.prog 2 | CXX = g++ 3 | CFLAGS = -g -O2 -Wall 4 | 5 | COMMON = ../common 6 | BASE = $(COMMON)/base 7 | BASE_H = $(BASE)/include 8 | PROTOBUF = $(COMMON)/protobuf 9 | PROTOBUF_LIB = $(PROTOBUF)/lib -lprotobuf 10 | OTHER_LIB = -lpthread -ldl 11 | EASYREACTOR = $(COMMON)/Easy-Reactor 12 | EASYREACTOR_H = $(EASYREACTOR)/include 13 | EASYREACTOR_LIB = $(EASYREACTOR)/lib -lereactor -lrt 14 | 15 | PROTO_H = $(COMMON)/proto 16 | 17 | INC = -Iinclude -I$(BASE_H) -I$(EASYREACTOR_H) -I$(PROTO_H) 18 | LIB = -L$(PROTOBUF_LIB) -L$(EASYREACTOR_LIB) $(OTHER_LIB) 19 | 20 | OBJS = $(addsuffix .o, $(basename $(wildcard src/*.cc))) 21 | OBJS += $(PROTO_H)/elb.pb.o $(BASE)/src/log.o 22 | 23 | $(TARGET): $(OBJS) 24 | -mkdir -p bin 25 | $(CXX) $(CFLAGS) -o $(TARGET) $(OBJS) $(INC) $(LIB) 26 | 27 | -include $(OBJS:.o=.d) 28 | 29 | %.o: %.cc 30 | $(CXX) $(CFLAGS) -c -o $@ $< $(INC) 31 | @$(CXX) -MM $*.cc $(INC) > $*.d 32 | @mv -f $*.d $*.d.tmp 33 | @sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d 34 | @sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \ 35 | sed -e 's/^ *//' -e 's/$$/:/' >> $*.d 36 | @rm -f $*.d.tmp 37 | 38 | .PHONY: clean 39 | 40 | clean: 41 | -rm -f $(OBJS) src/*.d $(PROTO_H)/elb.pb.d $(BASE)/src/log.d $(TARGET) 42 | -------------------------------------------------------------------------------- /lbagent/Optimization-log.md: -------------------------------------------------------------------------------- 1 | ## 实际使用反馈与优化 2 | 3 | ### 2018-3-31, 量小的情况下过载发现太慢 4 | 5 | 对于一个小量服务, 假设一个窗口内(15s)匀速只有20次过程调用,如果远端过载, 则在已有策略上需要1succ 19err 几乎全失败才会感知 6 | 7 | 更严重的是,匀速<20次过程调用,即使全部失败也不可能达到过载条件 8 | 9 | **优化:** 10 | 11 | 连续2个窗口内都没过载,但是这2个窗口内真实失败率都高于70%: 说明是小业务量,认为此节点过载 12 | 13 | ### 2017-11-10,某场景下节点过载发现太慢 14 | 15 | **场景回顾:** 16 | 17 | 远程服务mod的一台节点h已经挂了,但ELB系统一直没有将h节点判定为过载 18 | 19 | **问题分析** 20 | 21 | 业务调用方的超时时间设置的是1秒,每次调用h节点都超时,即都消耗1秒,于是1秒才向ELB agent上报一次状态 22 | 23 | 与此行为冲突的是,agent每隔15秒会重置所有正常节点的调用统计,15s内,agent仅收到15次对h节点调用错误的上报,即15个err,根本达不到h节点过载的条件,于是h节点在每个15s内都一直被ELB认为是正常的,永远无法被判定为过载 24 | 25 | **结论** 26 | 27 | ELB的过载判定算法没有对节点调用耗时进行考虑 28 | 29 | 假设业务设置的调用超时时间为3秒,则业务方调用h节点失败消耗了3秒,并仅向ELB agent上报一个调用错误,`err + 1` 30 | 31 | **优化:** 32 | 33 | 当调用节点失败,向上报状态要携带本次调用时间`timecost`(ms),ELB agent在收到调用失败的汇报时,会对失败个数根据`timecost`进行放大 34 | 35 | 具体是: 36 | >`errcnt = timecost / 100; errcnt = 1 if timecost = 0` 37 | 38 | 39 | 于是乎,业务调用方调用h节点失败并消耗了1s,上报给ELB agent后,agent会认为h节点失败了1000ms/100 = 10次,会使挂掉的h更快达到过载条件 40 | 41 | **本优化可以更快感知调用超时情况的过载** 42 | 43 | -------------------------------------------------------------------------------- /lbagent/README.md: -------------------------------------------------------------------------------- 1 | ## Lb Agent Presentation 2 | 3 | ### **feature** 4 | 5 | 一个服务称为一个模块,一个模块由modid+cmdid来标识 6 | modid+cmdid的组合表示一个远程服务,这个远程服务一般部署在多个节点上 7 | 8 | LB Agent以UDP方式为业务方提供:1、节点获取服务;2、节点调用结果上报服务 9 | #### 1、节点获取服务: 10 | 业务方每次要向远程服务发送消息时,先利用modid+cmdid去向LB Agent获取一个可用节点,然后向该节点发送消息,完成一次远程调用;具体获取modid+cmdid下的哪个节点是由LB Agent负责的 11 | 12 | #### 2、节点调用结果上报服务 13 | 对LB Agent节点的一次远程调用后,调用结果会汇报给LB Agent,以便LB Agent根据自身的LB算法来感知远程服务节点的状态是空闲还是过载,进而控制节点获取时的节点调度 14 | 15 | 16 | ![lbagent-arch](pictures/Lbagent-Arch.png) 17 | 18 | LB Agent拥有5个线程,一个LB算法: 19 | 20 | - UDP Server服务,并运行LB算法,对业务提供节点获取和节点调用结果上报服务;为了增大系统吞吐量,使用3个UDP Server服务互相独立运行LB算法:`modid+cmdid % 3 = i`的那些模块的服务与调度,由第`i+1`个UDP Server线程负责 21 | 22 | - DSS Client:是dnsserver的客户端线程,负责根据需要,向dnsserver获取一个模块的节点集合(或称为获取路由);UDP Server会按需向此线程的MQ写入获取路由请求,DSS Client将MQ到来的请求转发到dnsserver,之后将dnsserver返回的路由信息更新到对应的UDP Server线程维护的路由信息中 23 | - Rpt Client:是reporter的客户端线程,负责将每个模块下所有节点在一段时间内的调用结果、过载情况上报到reporter端,便于观察情况、做报警;本身消费MQ数据,UDP Server会按需向MQ写入上报状态请求 24 | 25 | 26 | ### **business model** 27 | #### **1、节点获取服务getHost** 28 | 29 | 1. 当业务方调用API:getHost,将利用自己需要的modid+cmdid,先计算i = (modid+cmdid)%3,然后向LB Agent的第i+1个UDP Server获取节点 30 | 2. LB Agent收到getHost请求,在内存查询是否有要求模块的路由;如果没有,返回不存在给API;否则由LB算法选择一个可用节点、或返回过载错误给API 31 | 3. getHost也驱动着向Dss Client传递拉取路由请求: 32 | 1. 如果模块modid+cmdid不存在,会打包一个拉取此模块路由的请求,发给Dss Client线程MQ;(作为首次拉取路由) 33 | 2. 如果模块modid+cmdid上次拉取路由时间距今超时(默认15s),也打包一个拉取此模块路由的请求,发给Dss Client线程MQ;(作为路由更新) 34 | 35 | 36 | #### **2、节点调用结果上报服务** 37 | 1. 当业务方调用API:`report(modid, cmdid, ip, port, retcode)`,将利用自己需要的modid+cmdid,先计算`i = (modid+cmdid)%3`,然后向LB Agent的第`i+1`个UDP Server上报对节点`(ip, port)`的调用结果 38 | 2. LB Agent获取到report请求,而后根据调用结果,更新LB算法维护的该modid,cmdid下该节点ip,port的调用信息,用于LB算法调度 39 | 3. 一次report后,LB Agent顺便会决定是否向reporter上报最近一段时间(默认15秒)的该模块的调用结果,决定方式是上次上报时间距今是否超时(到15秒);如果已经超时,则将模块近期调用结果打包为上报请求交给Rpt Client的MQ 40 | 4. Rpt Client消费MQ,拿到上报请求,而后发送给reporter 41 | 42 | ### Timer Event 43 | #### 1、自身心跳记录 44 | LB Agent会每隔1秒钟向共享内存写入此时的时间戳(秒),以便业务API及时发现是否LB Agent已宕机; 45 | 46 | 业务API每次获取节点前,会对比当前时间与共享内存中的时间,如果相差超过2s,认为LB Agent已经宕机,则转而向持久化到本地磁盘的静态路由中随机获取一个要求模块的节点 47 | 48 | #### 2、周期性路由落地 49 | LB Agent每隔60秒向磁盘落地自身保存的所有模块的路由信息,作为静态路由;以便在LB Agent宕机后,可以由静态数据继续对业务提供节点获取服务 50 | 51 | 52 | ### **performance** 53 | 54 | 服务器参数: 55 | 56 | CPU个数:24 内存:128GB 网卡队列个数:24 57 | 58 | qpstest使用30个线程并发访问lbagent,压满lbagent UDP Server的3个线程CPU 59 | 60 | QPS测试结果:`≈50.96W/s` 61 | 62 | ### **PS** 63 | 除了节点获取服务、节点调用结果上报服务,LB Agent还为工具提供模块路由获取服务 64 | 65 | 66 | ### LB Algorithm 67 | 68 | ### 一、基础 69 | 70 | 每个模块(modid+cmdid)下有若干节点,节点的集合称为此模块的路由; 71 | 对于每个节点,有两种状态: 72 | - idle:此节点可用,可作为API请求的节点使用; 73 | - overload:此节点过载,暂时不可作为API请求的节点使用; 74 | 75 | 在请求节点时, 76 | 77 | 有如下几个关键属性: 78 | - 虚拟成功次数`vsucc`,API汇报节点调用结果是成功时,该值+1 79 | - 虚拟失败次数`verr`,API汇报节点调用结果是失败时,该值+1 80 | - 连续成功次数,顾名思义 81 | - 连续失败次数,顾名思义 82 | 83 | 以上4个字段在节点状态改变时(idle<->overload)会被重置 84 | 85 | ### 二、调度方式 86 | LB算法对每个模块路由维护两个队列:空闲队列、过载队列,空闲队列放置空闲节点,过载队列放置过载节点 87 | 最初,模块下所有节点都处于空闲队列 88 | 89 | ![lb](pictures/LB.png) 90 | 91 | 如图,当API对某模块发起节点获取时: 92 | - LB从空闲队列拿出队列头部节点,作为选取的节点返回,同时将此节点重追到队列尾部; 93 | - **probe机制** :如果此模块过载队列非空,则每经过probeNum次节点获取后(默认=10),给过载队列中的节点一个机会,从过载队列拿出队列头部节点,作为选取的节点返回,让API试探性的用一下,同时将此节点重追到队列尾部; 94 | - 如果空闲队列为空,说明整个模块过载了,返回过载错误;且也会经过probeNum次节点获取后(默认=10),给过载队列中的节点一个机会,从过载队列拿出队列头部节点,作为选取的节点返回,让API试探性的用一下,同时将此节点重追到队列尾部; 95 | 96 | >调度就是:从空闲队列轮流选择节点;同时利用probe机制,给过载队列中节点一些被选择的机会 97 | 98 | 99 | ### 三、过载判断 100 | 101 | 依赖于API对节点调用结果的汇报 102 | 103 | #### 1、idle节点关注失败率,overload节点关注成功率 104 | >节点失败率 = 节点`verr` / (`vsucc` + `verr`) 105 | >节点成功率 = 节点`vsucc` / (`vsucc` + `verr`) 106 | 107 | 当idle节点的失败率>预设值(默认10%),将节点判定为overload; 108 | 当overload节点的成功率>预设值(默认95%),将节点判定为idle; 109 | 110 | 而不可以idle/overload节点都只关注成功率or都只关注失败率,这样可能造成节点在idle/overload状态间频繁切换 111 | 为idle节点、overload节点设置不同的阈值可以区别对待 112 | 113 | #### 2、连续成功、连续失败 114 | 为了加速对宕机节点的发现 115 | 当idle节点连续失败次数超过预设值(默认15),将节点判定为overload; 116 | 而当overload节点连续成功次数超过预设值(默认15),将节点判定为idle; 117 | 118 | #### 3、预设初始虚拟成功个数、预设过载虚拟失败个数 119 | 120 | 假设节点idle时初始:`vsucc = 0, verr = 0`,则第一次对该节点调用失败会使得此节点失败率 = 100%,被判定为overload 121 | 为了在idle初始状态时不会因为少量错误就被判定为overload,当节点变为idle状态时,预设虚拟成功个数(默认180) 122 | 123 | 假设节点overload时初始:`vsucc = 0, verr = 0`,则第一次对该节点调用成功会使得此节点成功率 = 100%,被判定为idle 124 | 为了在idle初始状态时不会因为少量成功就被判定为idle,当节点变为overload状态时,预设虚拟失败个数(默认5) 125 | 126 | #### 4、idle节点设置统计窗口 127 | 128 | 假设节点h长期处于idle,已经累计`vsucc = 100000, err = 0`;此时突然h过载,API调用产生了大量的错误,假设汇报了500个失败,于是`verr = 500`,此时节点的失败率0.5%,尚未被判定为过载;且因为之前长期运行的成功个数太多,使得需要更多的错误汇报才会让LB感知到h过载 129 | 130 | 将idle节点每隔一定时间(默认15s)重置为idle初始状态(`vsucc = 270, verr = 0`) 131 | 于是将节点的运行情况按照15s分隔,我们永远只关注当前15s内此节点的状态,于是过载的节点将会被更快感知 132 | 133 | #### 5、overload设置过载超时 134 | 135 | 当节点被判定为overload后超过一段时间(默认3min),将此节点强制判定为idle状态,即强行认为经过3min,节点已经恢复了 136 | 即使节点实际上并没有从overload中恢复,接下来此节点依然会被很快地判定为overload 137 | 138 | 139 | ### FAQ 140 | 141 | >init_succ = 180,err_rate = 0.1 142 | >而 : 10succ+21err 才过载,实际失败率并不是0.1啊? 143 | 144 | 答: 145 | 146 | 实际上,观察一组数据: 147 | 148 | 10succ+21err 过载 实际rate=67% 149 | 20succ+22err 过载 实际rate=50% 150 | ...... 151 | 90succ + 30err 过载 实际rate=25% 152 | ...... 153 | 200succ + 42err 过载,实际rate=17% 154 | ...... 155 | 500succ + 75err 过载,实际rate=13% 156 | 即量越大越接近我们设定的=10% 157 | 158 | 而量越小,失败率更大才会导致过载 159 | 160 | **这样的设计是很好的,因为量小的时候不应该武断的认为10%就过载,比如10succ+2err就会过载,才失败了两次,但是达到了10%,所以过载了,这是很不合理的** 161 | 162 | 我们的init_succ弄巧成拙的在这方面防止了这个情况(本来只想用他防止一上来就失败过载的情况) 163 | 164 | 165 | ### 实际使用反馈与优化 166 | 167 | [优化日志][1] 168 | 169 | [1]: https://github.com/LeechanX/Easy-Load-Balancer/blob/master/lbagent/Optimization-log.md -------------------------------------------------------------------------------- /lbagent/conf/lbagent.ini: -------------------------------------------------------------------------------- 1 | [log] 2 | level=3 3 | [reporter] 4 | ip=10.38.164.56 5 | port=9999 6 | [dnsserver] 7 | ip=10.38.164.56 8 | port=7777 9 | [lb] 10 | ;初始的成功个数,防止刚启动时少量失败就认为过载 11 | init_succ_cnt=180 12 | ;被判定为overload时(虚拟)失败个数 13 | ovld_err_cnt=5 14 | ;当overload节点连续成功次数超过此值,认为成功恢复 15 | contin_succ_lim=15 16 | ;当正常节点连续失败次数超过此值,认为overload 17 | contin_err_lim=15 18 | ;经过几次获取节点请求后,试探选择一次overload节点 19 | probe_num=10 20 | ;对于每个modid/cmdid,多久更新一下本地路由,秒 21 | update_timeout=15 22 | ;对于每个modid/cmdid下的每个host,多久清理一下负载信息,秒 23 | clear_timeout=15 24 | ;对于每个modid/cmdid,多久上报给reporter一次 25 | report_timeout=15 26 | ;对于某个modid/cmdid下的某个host被判断过载后,在过载队列等待的最大时间,秒 27 | overload_wait_lim=180 28 | ;当overload节点成功率高于此值,节点变idle 29 | succ_rate=0.95 30 | ;当idle节点失败率高于此值,节点变overload 31 | err_rate=0.1 32 | ;一个窗口内,真实失败率阈值 33 | wind_err_rate=0.7 34 | ;真实失败率大于wind_err_rate的最大连续窗口个数,超过就过载 35 | yind_err_limit=2 36 | -------------------------------------------------------------------------------- /lbagent/include/HeartBeat.h: -------------------------------------------------------------------------------- 1 | #ifndef __ALIVE_DO_HEADER__ 2 | #define __ALIVE_DO_HEADER__ 3 | 4 | #define DEAD_THRESHOLD 2 5 | 6 | #define HB_FILE "/tmp/hb_map.bin" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | class HeartBeat 19 | { 20 | public: 21 | HeartBeat(bool create = false) 22 | { 23 | int fd = open(HB_FILE, O_CREAT | O_EXCL | O_RDWR, 0666); 24 | if (fd == -1 && errno != EEXIST) 25 | { 26 | perror("open /tmp/hb_map.bin"); 27 | exit(1); 28 | } 29 | if (fd == -1) 30 | fd = open(HB_FILE, O_RDWR); 31 | 32 | if(ftruncate(fd, 8) == -1) 33 | { 34 | perror("ftruncate /tmp/hb_map.bin"); 35 | exit(1); 36 | } 37 | _hb = (uint64_t *)mmap(0, 8, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 38 | if (!_hb) 39 | { 40 | perror("mmap /tmp/hb_map.bin"); 41 | exit(1); 42 | } 43 | if (create) 44 | *_hb = time(NULL); 45 | } 46 | 47 | bool die() const { return time(NULL) - *_hb > DEAD_THRESHOLD; } 48 | 49 | void recordTs() { *_hb = time(NULL); } 50 | 51 | private: 52 | uint64_t *_hb; 53 | }; 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /lbagent/include/RouteLb.h: -------------------------------------------------------------------------------- 1 | #ifndef __ROUTELB_H__ 2 | #define __ROUTELB_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "elb.pb.h" 12 | 13 | //host info 14 | struct HI 15 | { 16 | HI(uint32_t myIp, int myPort, uint32_t initSucc): 17 | ip(myIp), 18 | port(myPort), 19 | succ(initSucc), 20 | err(0), 21 | rSucc(0), 22 | rErr(0), 23 | continSucc(0), 24 | continErr(0), 25 | overload(false), 26 | overloadTs(0), 27 | windErrCnt(0) { 28 | windowTs = time(NULL); 29 | } 30 | 31 | bool checkWindow(); 32 | void resetIdle(uint32_t initSucc); 33 | void setOverload(uint32_t overloadErr); 34 | 35 | uint32_t ip; 36 | int port; 37 | uint32_t succ;//虚拟成功个数,用于过载、空闲判定 38 | uint32_t err;//虚拟失败个数,用于过载、空闲判定 39 | uint32_t rSucc;//真实成功个数,用于上报给reporter观察,每个modid/cmdid的上报周期重置一次 40 | uint32_t rErr;//真实失败个数,用于上报给reporter观察,每个modid/cmdid的上报周期重置一次 41 | uint32_t continSucc; 42 | uint32_t continErr; 43 | bool overload; 44 | long windowTs; 45 | long overloadTs; 46 | 47 | uint32_t windErrCnt;//失败率>=windErrRate的连续idle窗口个数,含此时的idle窗口 48 | }; 49 | 50 | class LB 51 | { 52 | public: 53 | LB(int modid, int cmdid): 54 | effectData(0), 55 | lstRptTime(0), 56 | status(ISPULLING), 57 | _modid(modid), 58 | _cmdid(cmdid), 59 | _accessCnt(0) { } 60 | 61 | ~LB(); 62 | 63 | bool empty() const { return _hostMap.empty(); } 64 | 65 | int getHost(elb::GetHostRsp& rsp); 66 | 67 | void getRoute(std::vector& vec); 68 | 69 | void report(int ip, int port, int retcode); 70 | void reportSomeSucc(int ip, int port, unsigned succCnt); 71 | void reportSomeErr(int ip, int port, unsigned errCnt); 72 | 73 | void update(elb::GetRouteRsp& rsp); 74 | 75 | void pull(); 76 | 77 | void persist(FILE* fp); 78 | 79 | void report2Rpter(); 80 | 81 | bool hasOvHost() const { return !_downList.empty(); } 82 | 83 | enum STATUS 84 | { 85 | ISPULLING, 86 | ISNEW 87 | }; 88 | 89 | long effectData;//used to repull, last pull timestamp 90 | long lstRptTime;//last report timestamp 91 | STATUS status; 92 | long version;//route version 93 | 94 | private: 95 | typedef __gnu_cxx::hash_map HostMap; 96 | typedef __gnu_cxx::hash_map::iterator HostMapIt; 97 | 98 | int _modid; 99 | int _cmdid; 100 | int _accessCnt; 101 | HostMap _hostMap; 102 | std::list _runningList, _downList; 103 | typedef std::list::iterator ListIt; 104 | }; 105 | 106 | class RouteLB 107 | { 108 | public: 109 | RouteLB(int id); 110 | 111 | int getHost(int modid, int cmdid, elb::GetHostRsp& rsp); 112 | 113 | void report(elb::ReportReq& req); 114 | void batchReport(elb::CacheBatchRptReq& req); 115 | 116 | void getRoute(int modid, int cmdid, elb::GetRouteRsp& rsp); 117 | void cacheGetRoute(int modid, int cmdid, long version, elb::CacheGetRouteRsp& rsp); 118 | 119 | void update(int modid, int cmdid, elb::GetRouteRsp& rsp); 120 | 121 | //清除任何标记为:正在拉取 的[modid,cmdid]状态,当dss client网络断开后需要调用之 122 | void clearPulling(); 123 | 124 | void persistRoute(); 125 | 126 | private: 127 | typedef __gnu_cxx::hash_map RouteMap; 128 | typedef __gnu_cxx::hash_map::iterator RouteMapIt; 129 | RouteMap _routeMap; 130 | //用于同步agent线程和后台dnsserver-client线程 131 | pthread_mutex_t _mutex; 132 | //标识自己是第几个RouteLB 133 | int _id; 134 | }; 135 | 136 | #endif 137 | -------------------------------------------------------------------------------- /lbagent/include/Server.h: -------------------------------------------------------------------------------- 1 | #ifndef __SERVER_H__ 2 | #define __SERVER_H__ 3 | 4 | #include "elb.pb.h" 5 | #include "RouteLb.h" 6 | #include "easy_reactor.h" 7 | 8 | enum RETCODE 9 | { 10 | OVERLOAD = -10000, 11 | SYSERR,//-9999 12 | NOEXIST,//-9998 13 | SUCCESS = 0, 14 | }; 15 | 16 | extern thread_queue* pullQueue; 17 | extern thread_queue* reptQueue; 18 | 19 | extern RouteLB* routeLB[3]; 20 | 21 | void initUDPServers(); 22 | void dssConnectorDomain(event_loop& loop); 23 | void rptConnectorDomain(); 24 | 25 | #endif -------------------------------------------------------------------------------- /lbagent/pictures/LB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeechanX/Easy-Load-Balancer/64bc1a74f7655dfb1968145ecfdf86537acbcd06/lbagent/pictures/LB.png -------------------------------------------------------------------------------- /lbagent/pictures/Lbagent-Arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeechanX/Easy-Load-Balancer/64bc1a74f7655dfb1968145ecfdf86537acbcd06/lbagent/pictures/Lbagent-Arch.png -------------------------------------------------------------------------------- /lbagent/src/AgentServer.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "log.h" 3 | #include "elb.pb.h" 4 | #include "Server.h" 5 | #include "easy_reactor.h" 6 | 7 | static void getHost(const char* data, uint32_t len, int msgid, net_commu* commu, void* usrData) 8 | { 9 | elb::GetHostReq req; 10 | req.ParseFromArray(data, len);//解包,data[0:len)保证是一个完整包 11 | int modid = req.modid(); 12 | int cmdid = req.cmdid(); 13 | //response 14 | elb::GetHostRsp rsp; 15 | rsp.set_seq(req.seq()); 16 | rsp.set_modid(modid); 17 | rsp.set_cmdid(cmdid); 18 | //get host from route lb metadata 19 | RouteLB* ptrRouteLB = (RouteLB*)usrData; 20 | ptrRouteLB->getHost(modid, cmdid, rsp); 21 | std::string rspStr; 22 | rsp.SerializeToString(&rspStr); 23 | commu->send_data(rspStr.c_str(), rspStr.size(), elb::GetHostRspId);//回复消息 24 | } 25 | 26 | static void reportStatus(const char* data, uint32_t len, int msgid, net_commu* commu, void* usrData) 27 | { 28 | elb::ReportReq req; 29 | req.ParseFromArray(data, len);//解包,data[0:len)保证是一个完整包 30 | //report to route lb metadata 31 | RouteLB* ptrRouteLB = (RouteLB*)usrData; 32 | ptrRouteLB->report(req); 33 | } 34 | 35 | static void getRouteByTool(const char* data, uint32_t len, int msgid, net_commu* commu, void* usrData) 36 | { 37 | elb::GetRouteReq req; 38 | req.ParseFromArray(data, len);//解包,data[0:len)保证是一个完整包 39 | //report to route lb metadata 40 | RouteLB* ptrRouteLB = (RouteLB*)usrData; 41 | elb::GetRouteRsp rsp; 42 | rsp.set_modid(req.modid()); 43 | rsp.set_cmdid(req.cmdid()); 44 | ptrRouteLB->getRoute(req.modid(), req.cmdid(), rsp); 45 | std::string rspStr; 46 | rsp.SerializeToString(&rspStr); 47 | commu->send_data(rspStr.c_str(), rspStr.size(), elb::GetRouteByToolRspId);//回复消息 48 | } 49 | 50 | static void cacheGetRoute(const char* data, uint32_t len, int msgid, net_commu* commu, void* usrData) 51 | { 52 | elb::CacheGetRouteReq req; 53 | req.ParseFromArray(data, len);//解包,data[0:len)保证是一个完整包 54 | //report to route lb metadata 55 | RouteLB* ptrRouteLB = (RouteLB*)usrData; 56 | elb::CacheGetRouteRsp rsp; 57 | rsp.set_modid(req.modid()); 58 | rsp.set_cmdid(req.cmdid()); 59 | long version = req.version(); 60 | ptrRouteLB->cacheGetRoute(req.modid(), req.cmdid(), version, rsp); 61 | std::string rspStr; 62 | rsp.SerializeToString(&rspStr); 63 | commu->send_data(rspStr.c_str(), rspStr.size(), elb::CacheGetRouteRspId);//回复消息 64 | } 65 | 66 | static void batchReport(const char* data, uint32_t len, int msgid, net_commu* commu, void* usrData) 67 | { 68 | elb::CacheBatchRptReq req; 69 | req.ParseFromArray(data, len);//解包,data[0:len)保证是一个完整包 70 | //report to route 71 | RouteLB* ptrRouteLB = (RouteLB*)usrData; 72 | ptrRouteLB->batchReport(req); 73 | } 74 | 75 | static void persistRoute(event_loop* loop, void* usrData) 76 | { 77 | RouteLB* ptrRouteLB = (RouteLB*)usrData; 78 | ptrRouteLB->persistRoute(); 79 | } 80 | 81 | static void* initUDPServerIns(void* portPtr) 82 | { 83 | short port = *((short*)portPtr); 84 | event_loop loop; 85 | udp_server server(&loop, "127.0.0.1", port);//创建UDP服务器 86 | 87 | server.add_msg_cb(elb::GetHostReqId, getHost, routeLB[port - 8888]);//设置:当收到消息id = GetHostReqId的消息调用的回调函数getHost 88 | server.add_msg_cb(elb::ReportReqId, reportStatus, routeLB[port - 8888]);//设置:当收到消息id = ReportReqId的消息调用的回调函数reportStatus 89 | server.add_msg_cb(elb::GetRouteByToolReqId, getRouteByTool, routeLB[port - 8888]);//设置:当收到消息id = GetRouteByToolReqId的消息调用的回调函数getRouteByTool 90 | server.add_msg_cb(elb::CacheGetRouteReqId, cacheGetRoute, routeLB[port - 8888]);//设置:当收到消息id = CacheGetRouteReqId的消息调用的回调函数cacheGetRoute 91 | server.add_msg_cb(elb::CacheBatchRptReqId, batchReport, routeLB[port - 8888]);//设置:当收到消息id = CacheBatchRptReqId的消息调用的回调函数batchReport 92 | 93 | loop.run_every(persistRoute, routeLB[port - 8888], 60);//设置:每隔60s将本地已拉到的路由持久化到磁盘 94 | 95 | loop.process_evs(); 96 | return NULL; 97 | } 98 | 99 | void initUDPServers() 100 | { 101 | static short ports[3] = {8888, 8889, 8890}; 102 | for (int i = 0;i < 3; ++i) 103 | { 104 | pthread_t tid; 105 | int ret = ::pthread_create(&tid, NULL, initUDPServerIns, &ports[i]); 106 | if (ret == -1) 107 | { 108 | perror("pthread_create"); 109 | ::exit(1); 110 | } 111 | ::pthread_detach(tid); 112 | } 113 | } -------------------------------------------------------------------------------- /lbagent/src/DssClient.cc: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include 3 | #include "elb.pb.h" 4 | #include "Server.h" 5 | #include "easy_reactor.h" 6 | 7 | static void recvRoute(const char* data, uint32_t len, int msgid, net_commu* commu, void* usr_data) 8 | { 9 | elb::GetRouteRsp rsp; 10 | rsp.ParseFromArray(data, len);//解包,data[0:len)保证是一个完整包 11 | int modid = rsp.modid(); 12 | int cmdid = rsp.cmdid(); 13 | int index = (modid + cmdid) % 3; 14 | //update metadata 15 | routeLB[index]->update(modid, cmdid, rsp); 16 | } 17 | 18 | static void newPullReq(event_loop* loop, int fd, void *args) 19 | { 20 | tcp_client* cli = (tcp_client*)args; 21 | std::queue msgs; 22 | pullQueue->recv_msg(msgs); 23 | while (!msgs.empty()) 24 | { 25 | elb::GetRouteReq req = msgs.front(); 26 | msgs.pop(); 27 | std::string reqStr; 28 | req.SerializeToString(&reqStr); 29 | cli->send_data(reqStr.c_str(), reqStr.size(), elb::GetRouteByAgentReqId);//发送消息 30 | } 31 | } 32 | 33 | static void whenConnected(tcp_client* client, void* args) 34 | { 35 | for (int i = 0;i < 3; ++i) 36 | routeLB[i]->clearPulling(); 37 | } 38 | 39 | void dssConnectorDomain(event_loop& loop) 40 | { 41 | const char* dssIp = config_reader::ins()->GetString("dnsserver", "ip", "").c_str(); 42 | short dssPort = config_reader::ins()->GetNumber("dnsserver", "port", 0); 43 | tcp_client client(&loop, dssIp, dssPort, "dnsserver");//创建TCP客户端 44 | 45 | //设置:当收到消息id=1的消息时的回调函数 46 | client.add_msg_cb(elb::GetRouteByAgentRspId, recvRoute/*, ???*/); 47 | 48 | //设置:连接成功、断线重连接成功后调用whenConnClose来清理之前的任务 49 | client.onConnection(whenConnected); 50 | 51 | //loop install message queue's messge coming event 52 | pullQueue->set_loop(&loop, newPullReq, &client); 53 | //run forever 54 | loop.process_evs(); 55 | } 56 | -------------------------------------------------------------------------------- /lbagent/src/RptClient.cc: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include 3 | #include "elb.pb.h" 4 | #include "Server.h" 5 | #include 6 | #include "easy_reactor.h" 7 | 8 | static void newReportReq(event_loop* loop, int fd, void *args) 9 | { 10 | tcp_client* cli = (tcp_client*)args; 11 | std::queue msgs; 12 | reptQueue->recv_msg(msgs); 13 | while (!msgs.empty()) 14 | { 15 | elb::ReportStatusReq req = msgs.front(); 16 | msgs.pop(); 17 | std::string reqStr; 18 | req.SerializeToString(&reqStr); 19 | cli->send_data(reqStr.c_str(), reqStr.size(), elb::ReportStatusReqId);//发送消息 20 | } 21 | } 22 | 23 | static void* initRptCliIns(void* args) 24 | { 25 | const char* rptIp = config_reader::ins()->GetString("reporter", "ip", "").c_str(); 26 | short rptPort = config_reader::ins()->GetNumber("reporter", "port", 0); 27 | event_loop loop; 28 | tcp_client client(&loop, rptIp, rptPort, "reporter");//创建TCP客户端 29 | //loop install message queue's messge coming event 30 | reptQueue->set_loop(&loop, newReportReq, &client); 31 | //run loop 32 | loop.process_evs(); 33 | return NULL; 34 | } 35 | 36 | void rptConnectorDomain() 37 | { 38 | pthread_t tid; 39 | int ret = ::pthread_create(&tid, NULL, initRptCliIns, NULL); 40 | if (ret == -1) 41 | { 42 | perror("pthread_create"); 43 | ::exit(1); 44 | } 45 | ::pthread_detach(tid); 46 | } 47 | -------------------------------------------------------------------------------- /lbagent/src/Server.cc: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include "logo.h" 3 | #include "elb.pb.h" 4 | #include "Server.h" 5 | #include "HeartBeat.h" 6 | #include 7 | #include "easy_reactor.h" 8 | 9 | thread_queue* pullQueue = NULL; 10 | thread_queue* reptQueue = NULL; 11 | 12 | RouteLB* routeLB[3]; 13 | 14 | //timeout event 1: record current time in shared memory 15 | static void recordTs(event_loop* loop, void* usrData) 16 | { 17 | HeartBeat* hb = (HeartBeat*)usrData; 18 | hb->recordTs(); 19 | } 20 | 21 | int main(int argc, const char** argv) 22 | { 23 | if (argc != 2) 24 | { 25 | printf("USAGE: ./lbagent configPath\n"); 26 | ::exit(1); 27 | } 28 | dispLogo(); 29 | 30 | config_reader::setPath(argv[1]); 31 | 32 | for (int i = 0;i < 3; ++i) 33 | { 34 | int id = i + 1; 35 | routeLB[i] = new RouteLB(id); 36 | if (!routeLB[i]) 37 | { 38 | fprintf(stderr, "no more space to new RouteLB\n"); 39 | return 1; 40 | } 41 | } 42 | 43 | _init_log_("lbagent", "."); 44 | int log_level = config_reader::ins()->GetNumber("log", "level", 3); 45 | _set_log_level_(log_level); 46 | 47 | pullQueue = new thread_queue(); 48 | if (!pullQueue) 49 | { 50 | log_error("no space to create thread_queue"); 51 | return 1; 52 | } 53 | 54 | reptQueue = new thread_queue(); 55 | if (!reptQueue) 56 | { 57 | log_error("no space to create thread_queue"); 58 | return 1; 59 | } 60 | 61 | //init three UDP servers and create three thread for localhost[8888~8890] run in loop 62 | initUDPServers(); 63 | //init connector who connects to reporter, create a thread and run in loop 64 | rptConnectorDomain(); 65 | 66 | event_loop mainLoop; 67 | //install timeout event 1: record current time in shared memory, 1 second 1 do 68 | HeartBeat hb(true); 69 | mainLoop.run_every(recordTs, &hb, 1); 70 | //init connector who connects to dns server, and run in loop [main thread] 71 | dssConnectorDomain(mainLoop); 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /lbagent/tool/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = getroute 2 | CXX = g++ 3 | CFLAGS = -g -O2 -Wall 4 | 5 | $(TARGET): 6 | $(CXX) $(CFLAGS) -o $(TARGET) $(TARGET).cc -I../../api/cpp/elbApi/ ../../api/cpp/elbApi/libelbapi.a ../../common/protobuf/lib/libprotobuf.a 7 | 8 | clean: 9 | rm -f getroute 10 | -------------------------------------------------------------------------------- /lbagent/tool/getroute: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeechanX/Easy-Load-Balancer/64bc1a74f7655dfb1968145ecfdf86537acbcd06/lbagent/tool/getroute -------------------------------------------------------------------------------- /lbagent/tool/getroute.cc: -------------------------------------------------------------------------------- 1 | #include "elbApi.h" 2 | #include 3 | #include 4 | 5 | int main(int argc, char const *argv[]) 6 | { 7 | if (argc != 3) 8 | { 9 | printf("./getroute modid cmdid\n"); 10 | exit(1); 11 | } 12 | int modid = atoi(argv[1]); 13 | int cmdid = atoi(argv[2]); 14 | 15 | elbClient client; 16 | 17 | std::vector > route; 18 | int ret = client.apiGetRoute(modid, cmdid, route); 19 | if (ret == 0) 20 | { 21 | std::cout << "route for " << modid << "," << cmdid << ":" << std::endl; 22 | if (route.size() == 0) 23 | std::cout << "No route right now" << std::endl; 24 | for (unsigned i = 0;i < route.size(); ++i) 25 | { 26 | std::pair host = route[i]; 27 | std::cout << host.first << ":" << host.second << std::endl; 28 | } 29 | } 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /mod-manager/ModOperator.py: -------------------------------------------------------------------------------- 1 | #encoding=utf-8 2 | import time 3 | import sys 4 | import MySQLdb 5 | 6 | db = MySQLdb.connect(host='localhost', port = 3306, user='root', passwd='?????????', db ='dnsserver') 7 | cur = db.cursor() 8 | 9 | op = sys.argv[1] 10 | modid = sys.argv[2] 11 | cmdid = sys.argv[3] 12 | ip = sys.argv[4] 13 | port = sys.argv[5] 14 | 15 | ts = int(time.time()) 16 | 17 | if op == 'online':#online some node 18 | cur.execute('INSERT INTO DnsServerRoute(modid, cmdid, serverip, serverport) VALUES(%s, %s, %s, %s)' % (modid, cmdid, ip, port)) 19 | cur.execute('UPDATE RouteVersion SET version = %d WHERE id = 1' % ts) 20 | cur.execute('INSERT INTO ChangeLog(modid, cmdid, version) VALUES(%s, %s, %d)' % (modid, cmdid, ts)) 21 | elif op == 'offline':#offline some node 22 | cur.execute('DELETE FROM DnsServerRoute WHERE modid = %s and cmdid = %s and serverip = %s and serverport = %s' % (modid, cmdid, ip, port)) 23 | cur.execute('UPDATE RouteVersion SET version = %d WHERE id = 1' % ts) 24 | cur.execute('INSERT INTO ChangeLog(modid, cmdid, version) VALUES(%s, %s, %d)' % (modid, cmdid, ts)) 25 | 26 | cur.close() 27 | db.commit() 28 | db.close() 29 | -------------------------------------------------------------------------------- /pictures/arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeechanX/Easy-Load-Balancer/64bc1a74f7655dfb1968145ecfdf86537acbcd06/pictures/arch.png -------------------------------------------------------------------------------- /reporter/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = bin/reporter.prog 2 | CXX = g++ 3 | CFLAGS = -g -O2 -Wall 4 | 5 | COMMON = ../common 6 | BASE = $(COMMON)/base 7 | BASE_H = $(BASE)/include 8 | MYSQL = $(COMMON)/mysql-connector-c 9 | MYSQL_H = $(MYSQL)/include 10 | MYSQL_LIB = $(MYSQL)/lib/libmysqlclient.a 11 | PROTOBUF = $(COMMON)/protobuf 12 | PROTOBUF_LIB = $(PROTOBUF)/lib -lprotobuf 13 | OTHER_LIB = -lpthread -ldl 14 | EASYREACTOR = $(COMMON)/Easy-Reactor 15 | EASYREACTOR_H = $(EASYREACTOR)/include 16 | EASYREACTOR_LIB = $(EASYREACTOR)/lib -lereactor -lrt 17 | 18 | PROTO_H = $(COMMON)/proto 19 | 20 | INC = -Iinclude -I$(MYSQL_H) -I$(BASE_H) -I$(EASYREACTOR_H) -I$(PROTO_H) 21 | LIB = $(MYSQL_LIB) -L$(PROTOBUF_LIB) -L$(EASYREACTOR_LIB) $(OTHER_LIB) 22 | 23 | OBJS = $(addsuffix .o, $(basename $(wildcard src/*.cc))) 24 | OBJS += $(PROTO_H)/elb.pb.o $(BASE)/src/log.o 25 | 26 | $(TARGET): $(OBJS) 27 | -mkdir -p bin 28 | $(CXX) $(CFLAGS) -o $(TARGET) $(OBJS) $(INC) $(LIB) 29 | 30 | -include $(OBJS:.o=.d) 31 | 32 | %.o: %.cc 33 | $(CXX) $(CFLAGS) -c -o $@ $< $(INC) 34 | @$(CXX) -MM $*.cc $(INC) > $*.d 35 | @mv -f $*.d $*.d.tmp 36 | @sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d 37 | @sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \ 38 | sed -e 's/^ *//' -e 's/$$/:/' >> $*.d 39 | @rm -f $*.d.tmp 40 | 41 | .PHONY: clean 42 | 43 | clean: 44 | -rm -f $(OBJS) src/*.d $(PROTO_H)/elb.pb.d $(BASE)/src/log.d $(TARGET) 45 | -------------------------------------------------------------------------------- /reporter/README.md: -------------------------------------------------------------------------------- 1 | ## Reporter Presentation 2 | ### **feature** 3 | 负责接收各agent对某modid、cmdid下节点的调用状态的上报 4 | 5 | 请求内容包括: 6 | >modid,cmdid,上报者agent的ip,上报时间,是否过载,以及其下所有节点的调用结果:成功个数,失败个数 7 | 8 | ### **principle arch** 9 | 10 | ![Reporter-Arch](pictures/Reporter-Arch.png) 11 | 12 | ### **server model** 13 | 14 | Reporter服务模型采用了single thread TCP服务器 + 线程池处理请求 15 | 16 | - 主线程Reporter负责接收agent请求,并根据请求中携带的`modid`和`cmdid`,拼接后进行`murmurHash`,分配到某个线程的MQ上 17 | - Thread 1~N们负责处理请求:把MQ上的请求中的数据同步更新到MySQL数据表 18 | 19 | 由于agent上报给Reporter的信息是携带时间的,且仅作为前台展示方便查看服务的过载情况,故通信仅有请求没有响应 20 | 21 | 于是Reporter服务只要可以高效读取请求即可,后端写数据库的实时性能要求不高 22 | -------------------------------------------------------------------------------- /reporter/conf/reporter.ini: -------------------------------------------------------------------------------- 1 | [mysql] 2 | db_host=10.118.15.126 3 | db_port=6646 4 | db_user=dnsserver_x 5 | db_passwd=??? 6 | db_name=dnsserver 7 | ;上报状态到MySQL的线程数 8 | thread_cnt = 3 9 | [log] 10 | level=3 11 | [reactor] 12 | ;服务器线程池的线程个数 13 | ;threadNum = 0 14 | ;最大连接数 15 | ;maxConns = 1024 16 | ip=0.0.0.0 17 | port=12316 18 | -------------------------------------------------------------------------------- /reporter/include/CallStatis.h: -------------------------------------------------------------------------------- 1 | #ifndef __CALLSTATIS_H__ 2 | #define __CALLSTATIS_H__ 3 | 4 | #include "mysql.h" 5 | #include "elb.pb.h" 6 | 7 | class CallStatis 8 | { 9 | public: 10 | CallStatis(); 11 | //no need to implement destructor 12 | //~CallStatis(); 13 | void report(elb::ReportStatusReq& req); 14 | 15 | //多线程使用Mysql需要先调用mysql_library_init 16 | static void libraryInit() { mysql_library_init(0, NULL, NULL); } 17 | private: 18 | MYSQL _dbConn; 19 | }; 20 | 21 | #endif -------------------------------------------------------------------------------- /reporter/include/Server.h: -------------------------------------------------------------------------------- 1 | #ifndef __SERVER_H__ 2 | #define __SERVER_H__ 3 | 4 | #include "elb.pb.h" 5 | #include "easy_reactor.h" 6 | 7 | extern void* report2MySql(void* args); 8 | extern int threadCnt; 9 | extern thread_queue** rptQueues; 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /reporter/pictures/Reporter-Arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeechanX/Easy-Load-Balancer/64bc1a74f7655dfb1968145ecfdf86537acbcd06/reporter/pictures/Reporter-Arch.png -------------------------------------------------------------------------------- /reporter/src/CallStatis.cc: -------------------------------------------------------------------------------- 1 | #include "log.h" 2 | #include "CallStatis.h" 3 | #include "easy_reactor.h" 4 | #include "config_reader.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | CallStatis::CallStatis() 12 | { 13 | //connection DBconn 14 | const char* dbHost = config_reader::ins()->GetString("mysql", "db_host", "127.0.0.1").c_str(); 15 | uint16_t dbPort = config_reader::ins()->GetNumber("mysql", "db_port", 3306); 16 | const char* dbUser = config_reader::ins()->GetString("mysql", "db_user", "").c_str(); 17 | const char* dbPasswd = config_reader::ins()->GetString("mysql", "db_passwd", "").c_str(); 18 | const char* dbName = config_reader::ins()->GetString("mysql", "db_name", "dnsserver").c_str(); 19 | 20 | mysql_init(&_dbConn); 21 | mysql_options(&_dbConn, MYSQL_OPT_CONNECT_TIMEOUT, "30"); 22 | 23 | //when close down, let mysql_ping auto reconnect 24 | my_bool reconnect = 1; 25 | mysql_options(&_dbConn, MYSQL_OPT_RECONNECT, &reconnect); 26 | 27 | if (!mysql_real_connect(&_dbConn, dbHost, dbUser, dbPasswd, dbName, dbPort, NULL, 0)) 28 | { 29 | log_error("Failed to connect to MySQL[%s:%u %s %s]: %s\n", dbHost, dbPort, dbUser, dbName, mysql_error(&_dbConn)); 30 | ::exit(1); 31 | } 32 | } 33 | 34 | void CallStatis::report(elb::ReportStatusReq& req) 35 | { 36 | for (int i = 0;i < req.results_size(); ++i) 37 | { 38 | const elb::HostCallResult& result = req.results(i); 39 | int overload = result.overload() ? 1: 0; 40 | char sql[3072]; 41 | snprintf(sql, 3072, "INSERT INTO ServerCallStatus" 42 | "(modid, cmdid, ip, port, caller, succ_cnt, err_cnt, ts, overload) " 43 | "VALUES (%d, %d, %u, %u, %u, %u, %u, %u, %d) ON DUPLICATE KEY " 44 | "UPDATE succ_cnt = %u, err_cnt = %u, ts = %u, overload = %d", 45 | req.modid(), req.cmdid(), result.ip(), result.port(), req.caller(), 46 | result.succ(), result.err(), req.ts(), overload, 47 | result.succ(), result.err(), req.ts(), overload); 48 | 49 | mysql_ping(&_dbConn);//if close down, auto reconnect 50 | int ret = mysql_real_query(&_dbConn, sql, strlen(sql)); 51 | if (ret) 52 | { 53 | log_error("Failed to find any records and caused an error: %s\n", mysql_error(&_dbConn)); 54 | } 55 | } 56 | } 57 | 58 | struct Args 59 | { 60 | thread_queue* arg1; 61 | CallStatis* arg2; 62 | }; 63 | 64 | static void newReportReq(event_loop* loop, int fd, void *args) 65 | { 66 | thread_queue* rptQueue = ((Args*)args)->arg1; 67 | CallStatis* callStat = ((Args*)args)->arg2; 68 | 69 | std::queue msgs; 70 | rptQueue->recv_msg(msgs); 71 | while (!msgs.empty()) 72 | { 73 | elb::ReportStatusReq req = msgs.front(); 74 | msgs.pop(); 75 | callStat->report(req); 76 | } 77 | } 78 | 79 | void* report2MySql(void* args) 80 | { 81 | thread_queue* rptQueue = (thread_queue*)args; 82 | 83 | CallStatis callStat; 84 | event_loop loop; 85 | //loop install message queue's messge coming event 86 | Args cbArgs; 87 | cbArgs.arg1 = rptQueue; 88 | cbArgs.arg2 = &callStat; 89 | rptQueue->set_loop(&loop, newReportReq, &cbArgs); 90 | //run loop 91 | loop.process_evs(); 92 | return NULL; 93 | } -------------------------------------------------------------------------------- /reporter/src/Server.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "log.h" 5 | #include "logo.h" 6 | #include "util.h" 7 | #include "Server.h" 8 | #include "elb.pb.h" 9 | #include "CallStatis.h" 10 | #include "easy_reactor.h" 11 | 12 | int threadCnt = 0; 13 | thread_queue** rptQueues = NULL; 14 | 15 | void reportStatus(const char* data, uint32_t len, int msgid, net_commu* commu, void* usr_data) 16 | { 17 | elb::ReportStatusReq req; 18 | req.ParseFromArray(data, len);//解包,data[0:len)保证是一个完整包 19 | 20 | if (!req.ParseFromArray(data, len)) 21 | { 22 | log_error("request decode error"); 23 | return ; 24 | } 25 | int modid = req.modid(); 26 | int cmdid = req.cmdid(); 27 | uint64_t key = ((uint64_t)modid<<32) + cmdid; 28 | int index = HASHTO(&key, threadCnt); 29 | rptQueues[index]->send_msg(req); 30 | } 31 | 32 | int main() 33 | { 34 | event_loop loop; 35 | 36 | config_reader::setPath("reporter.ini"); 37 | std::string ip = config_reader::ins()->GetString("reactor", "ip", "0.0.0.0"); 38 | short port = config_reader::ins()->GetNumber("reactor", "port", 12316); 39 | 40 | dispLogo(); 41 | 42 | tcp_server server(&loop, ip.c_str(), port);//创建TCP服务器 43 | server.add_msg_cb(elb::ReportStatusReqId, reportStatus);//设置:当收到消息id = ReportStatusReqId (即上报调用结果)的消息调用的回调函数 44 | 45 | _init_log_("reporter", "."); 46 | int log_level = config_reader::ins()->GetNumber("log", "level", 3); 47 | _set_log_level_(log_level); 48 | 49 | threadCnt = config_reader::ins()->GetNumber("mysql", "thread_cnt", 3); 50 | rptQueues = new thread_queue*[threadCnt]; 51 | if (!rptQueues) 52 | { 53 | log_error("no space to create thread_queue*[%d]", threadCnt); 54 | return 1; 55 | } 56 | //多线程使用Mysql需要先调用mysql_library_init 57 | CallStatis::libraryInit(); 58 | for (int i = 0;i < threadCnt; ++i) 59 | { 60 | rptQueues[i] = new thread_queue(); 61 | if (!rptQueues[i]) 62 | { 63 | log_error("no space to create thread_queue"); 64 | return 1; 65 | } 66 | pthread_t tid; 67 | int ret = ::pthread_create(&tid, NULL, report2MySql, rptQueues[i]); 68 | if (ret == -1) 69 | { 70 | perror("pthread_create"); 71 | ::exit(1); 72 | } 73 | ::pthread_detach(tid); 74 | } 75 | 76 | loop.process_evs(); 77 | return 0; 78 | } 79 | -------------------------------------------------------------------------------- /reporter/test/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = reporter-cli.prog 2 | CXX = g++ 3 | CFLAGS = -g -O2 -Wall 4 | 5 | COMMON = ../../common 6 | PROTOBUF = $(COMMON)/protobuf 7 | PROTOBUF_LIB = $(PROTOBUF)/lib -lprotobuf 8 | OTHER_LIB = -lpthread -ldl 9 | EASYREACTOR = $(COMMON)/Easy-Reactor 10 | EASYREACTOR_H = $(EASYREACTOR)/include 11 | EASYREACTOR_LIB = $(EASYREACTOR)/lib -lereactor -lrt 12 | 13 | PROTO_H = $(COMMON)/proto 14 | 15 | INC = -Iinclude -I$(EASYREACTOR_H) -I$(PROTO_H) 16 | LIB = -L$(PROTOBUF_LIB) -L$(EASYREACTOR_LIB) $(OTHER_LIB) 17 | 18 | OBJS = rptClient.o 19 | OBJS += $(PROTO_H)/elb.pb.o 20 | 21 | $(TARGET): $(OBJS) 22 | $(CXX) $(CFLAGS) -o $(TARGET) $(OBJS) $(INC) $(LIB) 23 | 24 | -include $(OBJS:.o=.d) 25 | 26 | %.o: %.cc 27 | $(CXX) $(CFLAGS) -c -o $@ $< $(INC) 28 | @$(CXX) -MM $*.cc $(INC) > $*.d 29 | @mv -f $*.d $*.d.tmp 30 | @sed -e 's|.*:|$*.o:|' < $*.d.tmp > $*.d 31 | @sed -e 's/.*://' -e 's/\\$$//' < $*.d.tmp | fmt -1 | \ 32 | sed -e 's/^ *//' -e 's/$$/:/' >> $*.d 33 | @rm -f $*.d.tmp 34 | 35 | .PHONY: clean 36 | 37 | clean: 38 | -rm -f *.o *.d $(TARGET) 39 | -------------------------------------------------------------------------------- /reporter/test/rptClient.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "elb.pb.h" 5 | #include "easy_reactor.h" 6 | 7 | void reportStatus(event_loop* loop, void* usr_data) 8 | { 9 | tcp_client* client = (tcp_client*)usr_data; 10 | 11 | elb::ReportStatusReq req; 12 | req.set_modid(rand() % 3 + 1); 13 | req.set_cmdid(1); 14 | req.set_caller(123); 15 | req.set_ts(time(NULL)); 16 | for (int i = 0;i < 3; ++i) 17 | { 18 | elb::HostCallResult res; 19 | res.set_ip(i + 1); 20 | res.set_port((i + 1) * (i + 1)); 21 | res.set_succ(100); 22 | res.set_err(3); 23 | res.set_overload(true); 24 | req.add_results()->CopyFrom(res); 25 | } 26 | 27 | std::string reqStr; 28 | req.SerializeToString(&reqStr); 29 | client->send_data(reqStr.c_str(), reqStr.size(), elb::ReportStatusReqId);//主动发送消息 30 | } 31 | 32 | void whenConnectDone(tcp_client* client, void* args) 33 | { 34 | event_loop* loop = client->loop(); 35 | loop->run_every(reportStatus, client, 1); 36 | } 37 | 38 | int main(int argc, char const *argv[]) 39 | { 40 | srand(time(NULL)); 41 | event_loop loop; 42 | tcp_client client(&loop, "127.0.0.1", 12316);//创建TCP客户端 43 | client.onConnection(whenConnectDone);//install:当连接建立,调用whenConnectionDone函数 44 | loop.process_evs(); 45 | return 0; 46 | } 47 | --------------------------------------------------------------------------------