diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..53e64d6 --- /dev/null +++ b/README.md @@ -0,0 +1,156 @@ +# octo-ns + +## 背景及概念 + + octo-ns + 是美团octo服务治理体系中负责命名服务的系列模块,包括[c++ sdk](sdk/mns-sdk/docs/mns_sdk_api.md)、[java + sdk](sdk/mns-invoker)、 + [基础代理sgagent](sg_agent)、[命名服务缓存nsc](nsc)、[健康检查服务scanner](scanner)、[zookeeper](https://zookeeper.apache.org/) + ,搭配管理平台 [octo-portal](https://github.com/Meituan-Dianping/octo-portal) 用户能够便捷的进行服务运营交互。 + + octo-ns + 基于服务描述信息(tags+weight)实现服务注册/发现、路由分组、负载均衡、健康检测等功能,利用这些服务治理功能用户可以专注于业务逻辑开发、能够追踪线上服务状态、快速处置异常风险。octo-ns提升了业务对于服务的运营能力,其总体架构图如下: + +
+ +* 服务service + + 通过自定义接口提供给消费端的软件功能,octo目前支持rpc、http服务。 + +* 服务名 servicename + + 服务标识,可映射到指定服务;octo体系中通过appkey字段表示服务名。 + +* 服务提供者 service provider + + 是指提供服务的被调用一方。 + +* 服务消费者 service consumer + + 是指发起对某个服务调用的一方。 + +* 注册中心 + + 注册中心存储服务描述信息用以实现命名服务整个功能。服务在启动时将服务信息上报到注册中心,服务消费者从注册中心获取对应的服务提供者信息。健康检查组件会根据对服务节点的检测结果更新注册中心服务状态信息。 + +* 服务注册(service registry) + + 服务提供者启用后向注册中心上报服务信息的流程。 + +* 服务发现(service discovery) + + 服务消费者获取服务提供者信息的流程。 + +* 权重 + + 浮点数,是负载均衡抉择服务端流量配比的重要指标;业务和路由规则会对权重进行调整。 + +* 服务分组(service group) + + 是业务自定义的服务提供者和服务消费者之间的调用约束关系。 + +* 健康检查(health check) + + 服务节点的端口/进程存活状态的检查。octo-ns体系中通过scanner执行健康扫描,并更新服务描述信息到注册中心。 + +## 架构特点 +* 模块解耦功能拆分 + + 通信框架(c++版本whale、java版本dorado)、服务治理代理(sgagent)、健康检查服务(scanner)、服务治理平台(octo-portal)。 + +* 代理模式轻量化框架 + + 服务治理策略实现下移到代理组件sgagent,精简框架功能,提升框架稳定性。 + +
+ + + +* 水平扩展的代理模块(sgagent) + 如上所述,sgagent实现了服务治理如注册、发现、路由、策略等重要功能,简化服务消费者和服务提供者使用的通信框架。 + + 服务治理代理从部署上分为本地和哨兵模式两种,当本地sdk到sgagent不可用时可切换到哨兵集群,保证服务平滑扩展。 + +* 统一服务状态检查服务(scanner) + + scanner以周期扫描形式对服务进行探活检测,并更新服务状态到注册中心。 + +* 高可用 + + 调用链容灾:octo-ns各组件的本地缓存机制,提升了整体系统的容灾能力。链路中后台的某个组件发生故障时,可以使用缓存正常提供服务治理功能。 + + 哨兵模式:本地sgagent不可用时,降级(fallback)到哨兵集群进行服务治理。 + +## 架构介绍 + +
+ octo-ns由sdk、sgagent、nsc、scanner和zookeeper组成,使用octo-portal管理端实现可视化服务营运操作,例如更改服务提供者状态、调整权重。服务提供者启动后,通信框架主动发起注册操作,上报服务描述信息接入octo-ns。接下来分模块对octo-ns进行介绍。 + + +### 服务治理代理sgagent + + **服务注册/发现**:这是命名服务的基本功能,注册是提供者上报服务描述信息;发现是消费者根据appkey获取对应服务描述信息。分为增量和通用两种方式,通用方式是指添加provider的服务描述信息到对应appkey下面,为服务列表增加新的成员;增量方式是指一个包含多种servicename接口类型的apppkey,通过在注册中心建立servicename和appkey的双向映射,可实现servicename粒度的服务注册/发现功能。 + + **服务分组**:根据分组信息,sgagent调整服务节点权重,定制化流量负载。用户可根据需求自定义分组规则,服务分组需要进行事先配置,启动后方能生效。不同分组规则根据优先级排序,优先级高者生效。执行服务分组规则时,对于服务列表中匹配失败的节点进行降权处理,流量极低概率进入降权后的节点(未来管理页面将提供可选按钮,决定降权还是删除规则外服务节点)。目前支持的服务分组策略如下: + + a.自定义路由分组:在服务端配置该策略后,可定向指定上游打入下游规则范围内的服务节点 + + b.同机房优先分组:开启后,服务列表中与调用方非同机房的服务节点被降权 + + c.同中心优先分组:开启后,服务列表中与调用方非同中心的服务节点被降权 + + d.同城市路由分组:开启后,服务列表中与调用方非同城的服务节点被降权 + + **标签隔离**:依据服务节点中标识的不同标签,实现灵活的流量和链路隔离。服务注册时在服务描述信息中携带标签信息,服务发现时过滤服务列表中持有标签的服务提供者。例如:用以隔离测试的泳道标签,用以单元化部署和灰度链路的单元化标签。 + +### 缓存服务nsc + + 缓存注册到octo-ns的服务描述信息,一方面提供批量服务数据缓存与预处理功能,提升服务发现性能;另一方面增强服务治理链路的容灾能力,本地sgagent不可用的场景下该模块通过http形式提供远程哨兵服务列表。 +### 服务健康scanner + + 健康检查模块负责实时检查注册中心的服务提供者健康状况,一旦发现服务提供者不可用就将其置为未启动状态,及时摘除流量;当服务提供者恢复正常时,scanner会及时将服务提供者的状态置为正常状态,恢复流量。服务整个生命周期内,octo-ns利用scanner实现自动化的流量摘除和恢复,无需业务手动介入。为了提高检查的准确性,scanner支持octo自定义的心跳协议来进行应用层检查,octo体系内的通信框架默认支持,无需额外配置。 + +### 功能流程 + +* 服务注册 + + 业务进程启动后,通信框架发起服务注册,依赖sgagent上报服务描述信息到注册中心。本地sgagent失效时,sdk通过nsc服务获取远程sgagent哨兵机器列表信息,注册请求fallback到哨兵集群完成整个流程。服务提供者服务描述信息数据存入注册中心后,可从octo-portal管理页面进行查阅和修改。 + + +
+ +* 服务发现 + + octo-ns支持基于http和rpc的服务发现,服务消费者可通过调用sgagent服务发现接口获取服务提供者列表。sgagent会优先从nsc + 进行服务发现,从nsc服务发现失败时会降级从zookeeper获取服务提供者数据。 + +* 健康检查 + + scanner运行时会不断扫描注册中心的服务节点,依次检查每个服务提供者状态情况,按需修改服务描述信息。 + +
+ +## 使用文档 + +* [快速开始](/docs/ns-quick-start.md) + + +## 未来规划 + +* 注册中心ap化:将注册中心从目前基于zookeeper的cp系统演进为ap系统,在保证最终一致性的前提下以可用性为优先目标。 +* service mesh:sgagent借鉴时下盛行的mesh理念,进一步简化通信框架和SDK功能逻辑。 + + + +**Copyright and License** + +[Apache 2.0 License](/LICENSE) + + +##### 联系我们 + + * Mail: inf.octo.os@meituan.com +- [**Issues**](https://github.com/Meituan-Dianping/octo-ns/issues) + + + diff --git a/common/gen-cpp/MNSCacheService.cpp b/common/gen-cpp/MNSCacheService.cpp new file mode 100644 index 0000000..289776a --- /dev/null +++ b/common/gen-cpp/MNSCacheService.cpp @@ -0,0 +1,1786 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "MNSCacheService.h" + +namespace meituan_mns { + +uint32_t MNSCacheService_getMNSCache_args::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->appkey); + this->__isset.appkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->version); + this->__isset.version = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->env); + this->__isset.env = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MNSCacheService_getMNSCache_args::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("MNSCacheService_getMNSCache_args"); + xfer += oprot->writeFieldBegin("appkey", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->appkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("version", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString(this->version); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("env", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString(this->env); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t MNSCacheService_getMNSCache_pargs::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("MNSCacheService_getMNSCache_pargs"); + xfer += oprot->writeFieldBegin("appkey", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString((*(this->appkey))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("version", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString((*(this->version))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("env", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString((*(this->env))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t MNSCacheService_getMNSCache_result::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->success.read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MNSCacheService_getMNSCache_result::write(::apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("MNSCacheService_getMNSCache_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_STRUCT, 0); + xfer += this->success.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t MNSCacheService_getMNSCache_presult::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += (*(this->success)).read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MNSCacheService_getMNSCacheHttp_args::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->appkey); + this->__isset.appkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->version); + this->__isset.version = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->env); + this->__isset.env = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MNSCacheService_getMNSCacheHttp_args::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("MNSCacheService_getMNSCacheHttp_args"); + xfer += oprot->writeFieldBegin("appkey", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->appkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("version", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString(this->version); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("env", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString(this->env); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t MNSCacheService_getMNSCacheHttp_pargs::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("MNSCacheService_getMNSCacheHttp_pargs"); + xfer += oprot->writeFieldBegin("appkey", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString((*(this->appkey))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("version", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString((*(this->version))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("env", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString((*(this->env))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t MNSCacheService_getMNSCacheHttp_result::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->success.read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MNSCacheService_getMNSCacheHttp_result::write(::apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("MNSCacheService_getMNSCacheHttp_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_STRUCT, 0); + xfer += this->success.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t MNSCacheService_getMNSCacheHttp_presult::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += (*(this->success)).read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MNSCacheService_getMNSCacheWithVersionCheck_args::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->req.read(iprot); + this->__isset.req = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MNSCacheService_getMNSCacheWithVersionCheck_args::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("MNSCacheService_getMNSCacheWithVersionCheck_args"); + xfer += oprot->writeFieldBegin("req", ::apache::thrift::protocol::T_STRUCT, 1); + xfer += this->req.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t MNSCacheService_getMNSCacheWithVersionCheck_pargs::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("MNSCacheService_getMNSCacheWithVersionCheck_pargs"); + xfer += oprot->writeFieldBegin("req", ::apache::thrift::protocol::T_STRUCT, 1); + xfer += (*(this->req)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t MNSCacheService_getMNSCacheWithVersionCheck_result::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->success.read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MNSCacheService_getMNSCacheWithVersionCheck_result::write(::apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("MNSCacheService_getMNSCacheWithVersionCheck_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_STRUCT, 0); + xfer += this->success.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t MNSCacheService_getMNSCacheWithVersionCheck_presult::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += (*(this->success)).read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MNSCacheService_getMNSCacheByAppkeys_args::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->appkeys.clear(); + uint32_t _size0; + ::apache::thrift::protocol::TType _etype3; + iprot->readListBegin(_etype3, _size0); + this->appkeys.resize(_size0); + uint32_t _i4; + for (_i4 = 0; _i4 < _size0; ++_i4) + { + xfer += iprot->readString(this->appkeys[_i4]); + } + iprot->readListEnd(); + } + this->__isset.appkeys = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->protocol); + this->__isset.protocol = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MNSCacheService_getMNSCacheByAppkeys_args::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("MNSCacheService_getMNSCacheByAppkeys_args"); + xfer += oprot->writeFieldBegin("appkeys", ::apache::thrift::protocol::T_LIST, 1); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast(this->appkeys.size())); + std::vector ::const_iterator _iter5; + for (_iter5 = this->appkeys.begin(); _iter5 != this->appkeys.end(); ++_iter5) + { + xfer += oprot->writeString((*_iter5)); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("protocol", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString(this->protocol); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t MNSCacheService_getMNSCacheByAppkeys_pargs::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("MNSCacheService_getMNSCacheByAppkeys_pargs"); + xfer += oprot->writeFieldBegin("appkeys", ::apache::thrift::protocol::T_LIST, 1); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast((*(this->appkeys)).size())); + std::vector ::const_iterator _iter6; + for (_iter6 = (*(this->appkeys)).begin(); _iter6 != (*(this->appkeys)).end(); ++_iter6) + { + xfer += oprot->writeString((*_iter6)); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("protocol", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString((*(this->protocol))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t MNSCacheService_getMNSCacheByAppkeys_result::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->success.read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MNSCacheService_getMNSCacheByAppkeys_result::write(::apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("MNSCacheService_getMNSCacheByAppkeys_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_STRUCT, 0); + xfer += this->success.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t MNSCacheService_getMNSCacheByAppkeys_presult::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += (*(this->success)).read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MNSCacheService_getProvidersByIP_args::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->ip); + this->__isset.ip = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MNSCacheService_getProvidersByIP_args::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("MNSCacheService_getProvidersByIP_args"); + xfer += oprot->writeFieldBegin("ip", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->ip); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t MNSCacheService_getProvidersByIP_pargs::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("MNSCacheService_getProvidersByIP_pargs"); + xfer += oprot->writeFieldBegin("ip", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString((*(this->ip))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t MNSCacheService_getProvidersByIP_result::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->success.read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MNSCacheService_getProvidersByIP_result::write(::apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("MNSCacheService_getProvidersByIP_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_STRUCT, 0); + xfer += this->success.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t MNSCacheService_getProvidersByIP_presult::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += (*(this->success)).read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MNSCacheService_getAppkeyListByIP_args::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->ip); + this->__isset.ip = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MNSCacheService_getAppkeyListByIP_args::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("MNSCacheService_getAppkeyListByIP_args"); + xfer += oprot->writeFieldBegin("ip", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->ip); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t MNSCacheService_getAppkeyListByIP_pargs::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("MNSCacheService_getAppkeyListByIP_pargs"); + xfer += oprot->writeFieldBegin("ip", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString((*(this->ip))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t MNSCacheService_getAppkeyListByIP_result::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->success.read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MNSCacheService_getAppkeyListByIP_result::write(::apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("MNSCacheService_getAppkeyListByIP_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_STRUCT, 0); + xfer += this->success.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t MNSCacheService_getAppkeyListByIP_presult::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += (*(this->success)).read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +void MNSCacheServiceClient::getMNSCache(MNSResponse& _return, const std::string& appkey, const std::string& version, const std::string& env) +{ + send_getMNSCache(appkey, version, env); + recv_getMNSCache(_return); +} + +void MNSCacheServiceClient::send_getMNSCache(const std::string& appkey, const std::string& version, const std::string& env) +{ + int32_t cseqid = 0; + oprot_->writeMessageBegin("getMNSCache", ::apache::thrift::protocol::T_CALL, cseqid); + + MNSCacheService_getMNSCache_pargs args; + args.appkey = &appkey; + args.version = &version; + args.env = &env; + args.write(oprot_); + + oprot_->writeMessageEnd(); + oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); +} + +void MNSCacheServiceClient::recv_getMNSCache(MNSResponse& _return) +{ + + int32_t rseqid = 0; + std::string fname; + ::apache::thrift::protocol::TMessageType mtype; + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { + ::apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != ::apache::thrift::protocol::T_REPLY) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + if (fname.compare("getMNSCache") != 0) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + MNSCacheService_getMNSCache_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + + if (result.__isset.success) { + // _return pointer has now been filled + return; + } + throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "getMNSCache failed: unknown result"); +} + +void MNSCacheServiceClient::getMNSCacheHttp(MNSResponse& _return, const std::string& appkey, const std::string& version, const std::string& env) +{ + send_getMNSCacheHttp(appkey, version, env); + recv_getMNSCacheHttp(_return); +} + +void MNSCacheServiceClient::send_getMNSCacheHttp(const std::string& appkey, const std::string& version, const std::string& env) +{ + int32_t cseqid = 0; + oprot_->writeMessageBegin("getMNSCacheHttp", ::apache::thrift::protocol::T_CALL, cseqid); + + MNSCacheService_getMNSCacheHttp_pargs args; + args.appkey = &appkey; + args.version = &version; + args.env = &env; + args.write(oprot_); + + oprot_->writeMessageEnd(); + oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); +} + +void MNSCacheServiceClient::recv_getMNSCacheHttp(MNSResponse& _return) +{ + + int32_t rseqid = 0; + std::string fname; + ::apache::thrift::protocol::TMessageType mtype; + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { + ::apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != ::apache::thrift::protocol::T_REPLY) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + if (fname.compare("getMNSCacheHttp") != 0) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + MNSCacheService_getMNSCacheHttp_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + + if (result.__isset.success) { + // _return pointer has now been filled + return; + } + throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "getMNSCacheHttp failed: unknown result"); +} + +void MNSCacheServiceClient::getMNSCacheWithVersionCheck(MNSResponse& _return, const MnsRequest& req) +{ + send_getMNSCacheWithVersionCheck(req); + recv_getMNSCacheWithVersionCheck(_return); +} + +void MNSCacheServiceClient::send_getMNSCacheWithVersionCheck(const MnsRequest& req) +{ + int32_t cseqid = 0; + oprot_->writeMessageBegin("getMNSCacheWithVersionCheck", ::apache::thrift::protocol::T_CALL, cseqid); + + MNSCacheService_getMNSCacheWithVersionCheck_pargs args; + args.req = &req; + args.write(oprot_); + + oprot_->writeMessageEnd(); + oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); +} + +void MNSCacheServiceClient::recv_getMNSCacheWithVersionCheck(MNSResponse& _return) +{ + + int32_t rseqid = 0; + std::string fname; + ::apache::thrift::protocol::TMessageType mtype; + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { + ::apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != ::apache::thrift::protocol::T_REPLY) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + if (fname.compare("getMNSCacheWithVersionCheck") != 0) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + MNSCacheService_getMNSCacheWithVersionCheck_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + + if (result.__isset.success) { + // _return pointer has now been filled + return; + } + throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "getMNSCacheWithVersionCheck failed: unknown result"); +} + +void MNSCacheServiceClient::getMNSCacheByAppkeys(MNSBatchResponse& _return, const std::vector & appkeys, const std::string& protocol) +{ + send_getMNSCacheByAppkeys(appkeys, protocol); + recv_getMNSCacheByAppkeys(_return); +} + +void MNSCacheServiceClient::send_getMNSCacheByAppkeys(const std::vector & appkeys, const std::string& protocol) +{ + int32_t cseqid = 0; + oprot_->writeMessageBegin("getMNSCacheByAppkeys", ::apache::thrift::protocol::T_CALL, cseqid); + + MNSCacheService_getMNSCacheByAppkeys_pargs args; + args.appkeys = &appkeys; + args.protocol = &protocol; + args.write(oprot_); + + oprot_->writeMessageEnd(); + oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); +} + +void MNSCacheServiceClient::recv_getMNSCacheByAppkeys(MNSBatchResponse& _return) +{ + + int32_t rseqid = 0; + std::string fname; + ::apache::thrift::protocol::TMessageType mtype; + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { + ::apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != ::apache::thrift::protocol::T_REPLY) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + if (fname.compare("getMNSCacheByAppkeys") != 0) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + MNSCacheService_getMNSCacheByAppkeys_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + + if (result.__isset.success) { + // _return pointer has now been filled + return; + } + throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "getMNSCacheByAppkeys failed: unknown result"); +} + +void MNSCacheServiceClient::getProvidersByIP(MNSResponse& _return, const std::string& ip) +{ + send_getProvidersByIP(ip); + recv_getProvidersByIP(_return); +} + +void MNSCacheServiceClient::send_getProvidersByIP(const std::string& ip) +{ + int32_t cseqid = 0; + oprot_->writeMessageBegin("getProvidersByIP", ::apache::thrift::protocol::T_CALL, cseqid); + + MNSCacheService_getProvidersByIP_pargs args; + args.ip = &ip; + args.write(oprot_); + + oprot_->writeMessageEnd(); + oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); +} + +void MNSCacheServiceClient::recv_getProvidersByIP(MNSResponse& _return) +{ + + int32_t rseqid = 0; + std::string fname; + ::apache::thrift::protocol::TMessageType mtype; + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { + ::apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != ::apache::thrift::protocol::T_REPLY) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + if (fname.compare("getProvidersByIP") != 0) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + MNSCacheService_getProvidersByIP_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + + if (result.__isset.success) { + // _return pointer has now been filled + return; + } + throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "getProvidersByIP failed: unknown result"); +} + +void MNSCacheServiceClient::getAppkeyListByIP(AppKeyListResponse& _return, const std::string& ip) +{ + send_getAppkeyListByIP(ip); + recv_getAppkeyListByIP(_return); +} + +void MNSCacheServiceClient::send_getAppkeyListByIP(const std::string& ip) +{ + int32_t cseqid = 0; + oprot_->writeMessageBegin("getAppkeyListByIP", ::apache::thrift::protocol::T_CALL, cseqid); + + MNSCacheService_getAppkeyListByIP_pargs args; + args.ip = &ip; + args.write(oprot_); + + oprot_->writeMessageEnd(); + oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); +} + +void MNSCacheServiceClient::recv_getAppkeyListByIP(AppKeyListResponse& _return) +{ + + int32_t rseqid = 0; + std::string fname; + ::apache::thrift::protocol::TMessageType mtype; + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { + ::apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != ::apache::thrift::protocol::T_REPLY) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + if (fname.compare("getAppkeyListByIP") != 0) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + MNSCacheService_getAppkeyListByIP_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + + if (result.__isset.success) { + // _return pointer has now been filled + return; + } + throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "getAppkeyListByIP failed: unknown result"); +} + +bool MNSCacheServiceProcessor::process(boost::shared_ptr piprot, boost::shared_ptr poprot, void* callContext) { + + ::apache::thrift::protocol::TProtocol* iprot = piprot.get(); + ::apache::thrift::protocol::TProtocol* oprot = poprot.get(); + std::string fname; + ::apache::thrift::protocol::TMessageType mtype; + int32_t seqid; + + iprot->readMessageBegin(fname, mtype, seqid); + + if (mtype != ::apache::thrift::protocol::T_CALL && mtype != ::apache::thrift::protocol::T_ONEWAY) { + iprot->skip(::apache::thrift::protocol::T_STRUCT); + iprot->readMessageEnd(); + iprot->getTransport()->readEnd(); + ::apache::thrift::TApplicationException x(::apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + oprot->writeMessageBegin(fname, ::apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return true; + } + + return process_fn(iprot, oprot, fname, seqid, callContext); +} + +bool MNSCacheServiceProcessor::process_fn(apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, std::string& fname, int32_t seqid, void* callContext) { + std::map::iterator pfn; + pfn = processMap_.find(fname); + if (pfn == processMap_.end()) { + iprot->skip(apache::thrift::protocol::T_STRUCT); + iprot->readMessageEnd(); + iprot->getTransport()->readEnd(); + ::apache::thrift::TApplicationException x(::apache::thrift::TApplicationException::UNKNOWN_METHOD, "Invalid method name: '"+fname+"'"); + oprot->writeMessageBegin(fname, ::apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return true; + } + (this->*(pfn->second))(seqid, iprot, oprot, callContext); + return true; +} + +void MNSCacheServiceProcessor::process_getMNSCache(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext) +{ + void* ctx = NULL; + if (this->eventHandler_.get() != NULL) { + ctx = this->eventHandler_->getContext("MNSCacheService.getMNSCache", callContext); + } + apache::thrift::TProcessorContextFreer freer(this->eventHandler_.get(), ctx, "MNSCacheService.getMNSCache"); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preRead(ctx, "MNSCacheService.getMNSCache"); + } + + MNSCacheService_getMNSCache_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postRead(ctx, "MNSCacheService.getMNSCache", bytes); + } + + MNSCacheService_getMNSCache_result result; + try { + iface_->getMNSCache(result.success, args.appkey, args.version, args.env); + result.__isset.success = true; + } catch (const std::exception& e) { + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->handlerError(ctx, "MNSCacheService.getMNSCache"); + } + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("getMNSCache", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preWrite(ctx, "MNSCacheService.getMNSCache"); + } + + oprot->writeMessageBegin("getMNSCache", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postWrite(ctx, "MNSCacheService.getMNSCache", bytes); + } +} + +void MNSCacheServiceProcessor::process_getMNSCacheHttp(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext) +{ + void* ctx = NULL; + if (this->eventHandler_.get() != NULL) { + ctx = this->eventHandler_->getContext("MNSCacheService.getMNSCacheHttp", callContext); + } + apache::thrift::TProcessorContextFreer freer(this->eventHandler_.get(), ctx, "MNSCacheService.getMNSCacheHttp"); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preRead(ctx, "MNSCacheService.getMNSCacheHttp"); + } + + MNSCacheService_getMNSCacheHttp_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postRead(ctx, "MNSCacheService.getMNSCacheHttp", bytes); + } + + MNSCacheService_getMNSCacheHttp_result result; + try { + iface_->getMNSCacheHttp(result.success, args.appkey, args.version, args.env); + result.__isset.success = true; + } catch (const std::exception& e) { + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->handlerError(ctx, "MNSCacheService.getMNSCacheHttp"); + } + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("getMNSCacheHttp", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preWrite(ctx, "MNSCacheService.getMNSCacheHttp"); + } + + oprot->writeMessageBegin("getMNSCacheHttp", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postWrite(ctx, "MNSCacheService.getMNSCacheHttp", bytes); + } +} + +void MNSCacheServiceProcessor::process_getMNSCacheWithVersionCheck(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext) +{ + void* ctx = NULL; + if (this->eventHandler_.get() != NULL) { + ctx = this->eventHandler_->getContext("MNSCacheService.getMNSCacheWithVersionCheck", callContext); + } + apache::thrift::TProcessorContextFreer freer(this->eventHandler_.get(), ctx, "MNSCacheService.getMNSCacheWithVersionCheck"); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preRead(ctx, "MNSCacheService.getMNSCacheWithVersionCheck"); + } + + MNSCacheService_getMNSCacheWithVersionCheck_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postRead(ctx, "MNSCacheService.getMNSCacheWithVersionCheck", bytes); + } + + MNSCacheService_getMNSCacheWithVersionCheck_result result; + try { + iface_->getMNSCacheWithVersionCheck(result.success, args.req); + result.__isset.success = true; + } catch (const std::exception& e) { + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->handlerError(ctx, "MNSCacheService.getMNSCacheWithVersionCheck"); + } + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("getMNSCacheWithVersionCheck", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preWrite(ctx, "MNSCacheService.getMNSCacheWithVersionCheck"); + } + + oprot->writeMessageBegin("getMNSCacheWithVersionCheck", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postWrite(ctx, "MNSCacheService.getMNSCacheWithVersionCheck", bytes); + } +} + +void MNSCacheServiceProcessor::process_getMNSCacheByAppkeys(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext) +{ + void* ctx = NULL; + if (this->eventHandler_.get() != NULL) { + ctx = this->eventHandler_->getContext("MNSCacheService.getMNSCacheByAppkeys", callContext); + } + apache::thrift::TProcessorContextFreer freer(this->eventHandler_.get(), ctx, "MNSCacheService.getMNSCacheByAppkeys"); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preRead(ctx, "MNSCacheService.getMNSCacheByAppkeys"); + } + + MNSCacheService_getMNSCacheByAppkeys_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postRead(ctx, "MNSCacheService.getMNSCacheByAppkeys", bytes); + } + + MNSCacheService_getMNSCacheByAppkeys_result result; + try { + iface_->getMNSCacheByAppkeys(result.success, args.appkeys, args.protocol); + result.__isset.success = true; + } catch (const std::exception& e) { + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->handlerError(ctx, "MNSCacheService.getMNSCacheByAppkeys"); + } + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("getMNSCacheByAppkeys", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preWrite(ctx, "MNSCacheService.getMNSCacheByAppkeys"); + } + + oprot->writeMessageBegin("getMNSCacheByAppkeys", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postWrite(ctx, "MNSCacheService.getMNSCacheByAppkeys", bytes); + } +} + +void MNSCacheServiceProcessor::process_getProvidersByIP(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext) +{ + void* ctx = NULL; + if (this->eventHandler_.get() != NULL) { + ctx = this->eventHandler_->getContext("MNSCacheService.getProvidersByIP", callContext); + } + apache::thrift::TProcessorContextFreer freer(this->eventHandler_.get(), ctx, "MNSCacheService.getProvidersByIP"); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preRead(ctx, "MNSCacheService.getProvidersByIP"); + } + + MNSCacheService_getProvidersByIP_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postRead(ctx, "MNSCacheService.getProvidersByIP", bytes); + } + + MNSCacheService_getProvidersByIP_result result; + try { + iface_->getProvidersByIP(result.success, args.ip); + result.__isset.success = true; + } catch (const std::exception& e) { + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->handlerError(ctx, "MNSCacheService.getProvidersByIP"); + } + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("getProvidersByIP", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preWrite(ctx, "MNSCacheService.getProvidersByIP"); + } + + oprot->writeMessageBegin("getProvidersByIP", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postWrite(ctx, "MNSCacheService.getProvidersByIP", bytes); + } +} + +void MNSCacheServiceProcessor::process_getAppkeyListByIP(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext) +{ + void* ctx = NULL; + if (this->eventHandler_.get() != NULL) { + ctx = this->eventHandler_->getContext("MNSCacheService.getAppkeyListByIP", callContext); + } + apache::thrift::TProcessorContextFreer freer(this->eventHandler_.get(), ctx, "MNSCacheService.getAppkeyListByIP"); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preRead(ctx, "MNSCacheService.getAppkeyListByIP"); + } + + MNSCacheService_getAppkeyListByIP_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postRead(ctx, "MNSCacheService.getAppkeyListByIP", bytes); + } + + MNSCacheService_getAppkeyListByIP_result result; + try { + iface_->getAppkeyListByIP(result.success, args.ip); + result.__isset.success = true; + } catch (const std::exception& e) { + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->handlerError(ctx, "MNSCacheService.getAppkeyListByIP"); + } + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("getAppkeyListByIP", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preWrite(ctx, "MNSCacheService.getAppkeyListByIP"); + } + + oprot->writeMessageBegin("getAppkeyListByIP", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postWrite(ctx, "MNSCacheService.getAppkeyListByIP", bytes); + } +} + +::boost::shared_ptr< ::apache::thrift::TProcessor > MNSCacheServiceProcessorFactory::getProcessor(const ::apache::thrift::TConnectionInfo& connInfo) { + ::apache::thrift::ReleaseHandler< MNSCacheServiceIfFactory > cleanup(handlerFactory_); + ::boost::shared_ptr< MNSCacheServiceIf > handler(handlerFactory_->getHandler(connInfo), cleanup); + ::boost::shared_ptr< ::apache::thrift::TProcessor > processor(new MNSCacheServiceProcessor(handler)); + return processor; +} +} // namespace + diff --git a/common/gen-cpp/MNSCacheService.h b/common/gen-cpp/MNSCacheService.h new file mode 100644 index 0000000..0601c18 --- /dev/null +++ b/common/gen-cpp/MNSCacheService.h @@ -0,0 +1,937 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef MNSCacheService_H +#define MNSCacheService_H + +#include +#include "mnsc_service_types.h" + +namespace meituan_mns { + +class MNSCacheServiceIf { + public: + virtual ~MNSCacheServiceIf() {} + virtual void getMNSCache(MNSResponse& _return, const std::string& appkey, const std::string& version, const std::string& env) = 0; + virtual void getMNSCacheHttp(MNSResponse& _return, const std::string& appkey, const std::string& version, const std::string& env) = 0; + virtual void getMNSCacheWithVersionCheck(MNSResponse& _return, const MnsRequest& req) = 0; + virtual void getMNSCacheByAppkeys(MNSBatchResponse& _return, const std::vector & appkeys, const std::string& protocol) = 0; + virtual void getProvidersByIP(MNSResponse& _return, const std::string& ip) = 0; + virtual void getAppkeyListByIP(AppKeyListResponse& _return, const std::string& ip) = 0; +}; + +class MNSCacheServiceIfFactory { + public: + typedef MNSCacheServiceIf Handler; + + virtual ~MNSCacheServiceIfFactory() {} + + virtual MNSCacheServiceIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo) = 0; + virtual void releaseHandler(MNSCacheServiceIf* /* handler */) = 0; +}; + +class MNSCacheServiceIfSingletonFactory : virtual public MNSCacheServiceIfFactory { + public: + MNSCacheServiceIfSingletonFactory(const boost::shared_ptr& iface) : iface_(iface) {} + virtual ~MNSCacheServiceIfSingletonFactory() {} + + virtual MNSCacheServiceIf* getHandler(const ::apache::thrift::TConnectionInfo&) { + return iface_.get(); + } + virtual void releaseHandler(MNSCacheServiceIf* /* handler */) {} + + protected: + boost::shared_ptr iface_; +}; + +class MNSCacheServiceNull : virtual public MNSCacheServiceIf { + public: + virtual ~MNSCacheServiceNull() {} + void getMNSCache(MNSResponse& /* _return */, const std::string& /* appkey */, const std::string& /* version */, const std::string& /* env */) { + return; + } + void getMNSCacheHttp(MNSResponse& /* _return */, const std::string& /* appkey */, const std::string& /* version */, const std::string& /* env */) { + return; + } + void getMNSCacheWithVersionCheck(MNSResponse& /* _return */, const MnsRequest& /* req */) { + return; + } + void getMNSCacheByAppkeys(MNSBatchResponse& /* _return */, const std::vector & /* appkeys */, const std::string& /* protocol */) { + return; + } + void getProvidersByIP(MNSResponse& /* _return */, const std::string& /* ip */) { + return; + } + void getAppkeyListByIP(AppKeyListResponse& /* _return */, const std::string& /* ip */) { + return; + } +}; + +typedef struct _MNSCacheService_getMNSCache_args__isset { + _MNSCacheService_getMNSCache_args__isset() : appkey(false), version(false), env(false) {} + bool appkey; + bool version; + bool env; +} _MNSCacheService_getMNSCache_args__isset; + +class MNSCacheService_getMNSCache_args { + public: + + MNSCacheService_getMNSCache_args() : appkey(""), version(""), env("") { + } + + virtual ~MNSCacheService_getMNSCache_args() throw() {} + + std::string appkey; + std::string version; + std::string env; + + _MNSCacheService_getMNSCache_args__isset __isset; + + void __set_appkey(const std::string& val) { + appkey = val; + } + + void __set_version(const std::string& val) { + version = val; + } + + void __set_env(const std::string& val) { + env = val; + } + + bool operator == (const MNSCacheService_getMNSCache_args & rhs) const + { + if (!(appkey == rhs.appkey)) + return false; + if (!(version == rhs.version)) + return false; + if (!(env == rhs.env)) + return false; + return true; + } + bool operator != (const MNSCacheService_getMNSCache_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getMNSCache_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class MNSCacheService_getMNSCache_pargs { + public: + + + virtual ~MNSCacheService_getMNSCache_pargs() throw() {} + + const std::string* appkey; + const std::string* version; + const std::string* env; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getMNSCache_result__isset { + _MNSCacheService_getMNSCache_result__isset() : success(false) {} + bool success; +} _MNSCacheService_getMNSCache_result__isset; + +class MNSCacheService_getMNSCache_result { + public: + + MNSCacheService_getMNSCache_result() { + } + + virtual ~MNSCacheService_getMNSCache_result() throw() {} + + MNSResponse success; + + _MNSCacheService_getMNSCache_result__isset __isset; + + void __set_success(const MNSResponse& val) { + success = val; + } + + bool operator == (const MNSCacheService_getMNSCache_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const MNSCacheService_getMNSCache_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getMNSCache_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getMNSCache_presult__isset { + _MNSCacheService_getMNSCache_presult__isset() : success(false) {} + bool success; +} _MNSCacheService_getMNSCache_presult__isset; + +class MNSCacheService_getMNSCache_presult { + public: + + + virtual ~MNSCacheService_getMNSCache_presult() throw() {} + + MNSResponse* success; + + _MNSCacheService_getMNSCache_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +typedef struct _MNSCacheService_getMNSCacheHttp_args__isset { + _MNSCacheService_getMNSCacheHttp_args__isset() : appkey(false), version(false), env(false) {} + bool appkey; + bool version; + bool env; +} _MNSCacheService_getMNSCacheHttp_args__isset; + +class MNSCacheService_getMNSCacheHttp_args { + public: + + MNSCacheService_getMNSCacheHttp_args() : appkey(""), version(""), env("") { + } + + virtual ~MNSCacheService_getMNSCacheHttp_args() throw() {} + + std::string appkey; + std::string version; + std::string env; + + _MNSCacheService_getMNSCacheHttp_args__isset __isset; + + void __set_appkey(const std::string& val) { + appkey = val; + } + + void __set_version(const std::string& val) { + version = val; + } + + void __set_env(const std::string& val) { + env = val; + } + + bool operator == (const MNSCacheService_getMNSCacheHttp_args & rhs) const + { + if (!(appkey == rhs.appkey)) + return false; + if (!(version == rhs.version)) + return false; + if (!(env == rhs.env)) + return false; + return true; + } + bool operator != (const MNSCacheService_getMNSCacheHttp_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getMNSCacheHttp_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class MNSCacheService_getMNSCacheHttp_pargs { + public: + + + virtual ~MNSCacheService_getMNSCacheHttp_pargs() throw() {} + + const std::string* appkey; + const std::string* version; + const std::string* env; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getMNSCacheHttp_result__isset { + _MNSCacheService_getMNSCacheHttp_result__isset() : success(false) {} + bool success; +} _MNSCacheService_getMNSCacheHttp_result__isset; + +class MNSCacheService_getMNSCacheHttp_result { + public: + + MNSCacheService_getMNSCacheHttp_result() { + } + + virtual ~MNSCacheService_getMNSCacheHttp_result() throw() {} + + MNSResponse success; + + _MNSCacheService_getMNSCacheHttp_result__isset __isset; + + void __set_success(const MNSResponse& val) { + success = val; + } + + bool operator == (const MNSCacheService_getMNSCacheHttp_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const MNSCacheService_getMNSCacheHttp_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getMNSCacheHttp_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getMNSCacheHttp_presult__isset { + _MNSCacheService_getMNSCacheHttp_presult__isset() : success(false) {} + bool success; +} _MNSCacheService_getMNSCacheHttp_presult__isset; + +class MNSCacheService_getMNSCacheHttp_presult { + public: + + + virtual ~MNSCacheService_getMNSCacheHttp_presult() throw() {} + + MNSResponse* success; + + _MNSCacheService_getMNSCacheHttp_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +typedef struct _MNSCacheService_getMNSCacheWithVersionCheck_args__isset { + _MNSCacheService_getMNSCacheWithVersionCheck_args__isset() : req(false) {} + bool req; +} _MNSCacheService_getMNSCacheWithVersionCheck_args__isset; + +class MNSCacheService_getMNSCacheWithVersionCheck_args { + public: + + MNSCacheService_getMNSCacheWithVersionCheck_args() { + } + + virtual ~MNSCacheService_getMNSCacheWithVersionCheck_args() throw() {} + + MnsRequest req; + + _MNSCacheService_getMNSCacheWithVersionCheck_args__isset __isset; + + void __set_req(const MnsRequest& val) { + req = val; + } + + bool operator == (const MNSCacheService_getMNSCacheWithVersionCheck_args & rhs) const + { + if (!(req == rhs.req)) + return false; + return true; + } + bool operator != (const MNSCacheService_getMNSCacheWithVersionCheck_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getMNSCacheWithVersionCheck_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class MNSCacheService_getMNSCacheWithVersionCheck_pargs { + public: + + + virtual ~MNSCacheService_getMNSCacheWithVersionCheck_pargs() throw() {} + + const MnsRequest* req; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getMNSCacheWithVersionCheck_result__isset { + _MNSCacheService_getMNSCacheWithVersionCheck_result__isset() : success(false) {} + bool success; +} _MNSCacheService_getMNSCacheWithVersionCheck_result__isset; + +class MNSCacheService_getMNSCacheWithVersionCheck_result { + public: + + MNSCacheService_getMNSCacheWithVersionCheck_result() { + } + + virtual ~MNSCacheService_getMNSCacheWithVersionCheck_result() throw() {} + + MNSResponse success; + + _MNSCacheService_getMNSCacheWithVersionCheck_result__isset __isset; + + void __set_success(const MNSResponse& val) { + success = val; + } + + bool operator == (const MNSCacheService_getMNSCacheWithVersionCheck_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const MNSCacheService_getMNSCacheWithVersionCheck_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getMNSCacheWithVersionCheck_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getMNSCacheWithVersionCheck_presult__isset { + _MNSCacheService_getMNSCacheWithVersionCheck_presult__isset() : success(false) {} + bool success; +} _MNSCacheService_getMNSCacheWithVersionCheck_presult__isset; + +class MNSCacheService_getMNSCacheWithVersionCheck_presult { + public: + + + virtual ~MNSCacheService_getMNSCacheWithVersionCheck_presult() throw() {} + + MNSResponse* success; + + _MNSCacheService_getMNSCacheWithVersionCheck_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +typedef struct _MNSCacheService_getMNSCacheByAppkeys_args__isset { + _MNSCacheService_getMNSCacheByAppkeys_args__isset() : appkeys(false), protocol(false) {} + bool appkeys; + bool protocol; +} _MNSCacheService_getMNSCacheByAppkeys_args__isset; + +class MNSCacheService_getMNSCacheByAppkeys_args { + public: + + MNSCacheService_getMNSCacheByAppkeys_args() : protocol("") { + } + + virtual ~MNSCacheService_getMNSCacheByAppkeys_args() throw() {} + + std::vector appkeys; + std::string protocol; + + _MNSCacheService_getMNSCacheByAppkeys_args__isset __isset; + + void __set_appkeys(const std::vector & val) { + appkeys = val; + } + + void __set_protocol(const std::string& val) { + protocol = val; + } + + bool operator == (const MNSCacheService_getMNSCacheByAppkeys_args & rhs) const + { + if (!(appkeys == rhs.appkeys)) + return false; + if (!(protocol == rhs.protocol)) + return false; + return true; + } + bool operator != (const MNSCacheService_getMNSCacheByAppkeys_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getMNSCacheByAppkeys_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class MNSCacheService_getMNSCacheByAppkeys_pargs { + public: + + + virtual ~MNSCacheService_getMNSCacheByAppkeys_pargs() throw() {} + + const std::vector * appkeys; + const std::string* protocol; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getMNSCacheByAppkeys_result__isset { + _MNSCacheService_getMNSCacheByAppkeys_result__isset() : success(false) {} + bool success; +} _MNSCacheService_getMNSCacheByAppkeys_result__isset; + +class MNSCacheService_getMNSCacheByAppkeys_result { + public: + + MNSCacheService_getMNSCacheByAppkeys_result() { + } + + virtual ~MNSCacheService_getMNSCacheByAppkeys_result() throw() {} + + MNSBatchResponse success; + + _MNSCacheService_getMNSCacheByAppkeys_result__isset __isset; + + void __set_success(const MNSBatchResponse& val) { + success = val; + } + + bool operator == (const MNSCacheService_getMNSCacheByAppkeys_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const MNSCacheService_getMNSCacheByAppkeys_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getMNSCacheByAppkeys_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getMNSCacheByAppkeys_presult__isset { + _MNSCacheService_getMNSCacheByAppkeys_presult__isset() : success(false) {} + bool success; +} _MNSCacheService_getMNSCacheByAppkeys_presult__isset; + +class MNSCacheService_getMNSCacheByAppkeys_presult { + public: + + + virtual ~MNSCacheService_getMNSCacheByAppkeys_presult() throw() {} + + MNSBatchResponse* success; + + _MNSCacheService_getMNSCacheByAppkeys_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +typedef struct _MNSCacheService_getProvidersByIP_args__isset { + _MNSCacheService_getProvidersByIP_args__isset() : ip(false) {} + bool ip; +} _MNSCacheService_getProvidersByIP_args__isset; + +class MNSCacheService_getProvidersByIP_args { + public: + + MNSCacheService_getProvidersByIP_args() : ip("") { + } + + virtual ~MNSCacheService_getProvidersByIP_args() throw() {} + + std::string ip; + + _MNSCacheService_getProvidersByIP_args__isset __isset; + + void __set_ip(const std::string& val) { + ip = val; + } + + bool operator == (const MNSCacheService_getProvidersByIP_args & rhs) const + { + if (!(ip == rhs.ip)) + return false; + return true; + } + bool operator != (const MNSCacheService_getProvidersByIP_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getProvidersByIP_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class MNSCacheService_getProvidersByIP_pargs { + public: + + + virtual ~MNSCacheService_getProvidersByIP_pargs() throw() {} + + const std::string* ip; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getProvidersByIP_result__isset { + _MNSCacheService_getProvidersByIP_result__isset() : success(false) {} + bool success; +} _MNSCacheService_getProvidersByIP_result__isset; + +class MNSCacheService_getProvidersByIP_result { + public: + + MNSCacheService_getProvidersByIP_result() { + } + + virtual ~MNSCacheService_getProvidersByIP_result() throw() {} + + MNSResponse success; + + _MNSCacheService_getProvidersByIP_result__isset __isset; + + void __set_success(const MNSResponse& val) { + success = val; + } + + bool operator == (const MNSCacheService_getProvidersByIP_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const MNSCacheService_getProvidersByIP_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getProvidersByIP_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getProvidersByIP_presult__isset { + _MNSCacheService_getProvidersByIP_presult__isset() : success(false) {} + bool success; +} _MNSCacheService_getProvidersByIP_presult__isset; + +class MNSCacheService_getProvidersByIP_presult { + public: + + + virtual ~MNSCacheService_getProvidersByIP_presult() throw() {} + + MNSResponse* success; + + _MNSCacheService_getProvidersByIP_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +typedef struct _MNSCacheService_getAppkeyListByIP_args__isset { + _MNSCacheService_getAppkeyListByIP_args__isset() : ip(false) {} + bool ip; +} _MNSCacheService_getAppkeyListByIP_args__isset; + +class MNSCacheService_getAppkeyListByIP_args { + public: + + MNSCacheService_getAppkeyListByIP_args() : ip("") { + } + + virtual ~MNSCacheService_getAppkeyListByIP_args() throw() {} + + std::string ip; + + _MNSCacheService_getAppkeyListByIP_args__isset __isset; + + void __set_ip(const std::string& val) { + ip = val; + } + + bool operator == (const MNSCacheService_getAppkeyListByIP_args & rhs) const + { + if (!(ip == rhs.ip)) + return false; + return true; + } + bool operator != (const MNSCacheService_getAppkeyListByIP_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getAppkeyListByIP_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class MNSCacheService_getAppkeyListByIP_pargs { + public: + + + virtual ~MNSCacheService_getAppkeyListByIP_pargs() throw() {} + + const std::string* ip; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getAppkeyListByIP_result__isset { + _MNSCacheService_getAppkeyListByIP_result__isset() : success(false) {} + bool success; +} _MNSCacheService_getAppkeyListByIP_result__isset; + +class MNSCacheService_getAppkeyListByIP_result { + public: + + MNSCacheService_getAppkeyListByIP_result() { + } + + virtual ~MNSCacheService_getAppkeyListByIP_result() throw() {} + + AppKeyListResponse success; + + _MNSCacheService_getAppkeyListByIP_result__isset __isset; + + void __set_success(const AppKeyListResponse& val) { + success = val; + } + + bool operator == (const MNSCacheService_getAppkeyListByIP_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const MNSCacheService_getAppkeyListByIP_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getAppkeyListByIP_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getAppkeyListByIP_presult__isset { + _MNSCacheService_getAppkeyListByIP_presult__isset() : success(false) {} + bool success; +} _MNSCacheService_getAppkeyListByIP_presult__isset; + +class MNSCacheService_getAppkeyListByIP_presult { + public: + + + virtual ~MNSCacheService_getAppkeyListByIP_presult() throw() {} + + AppKeyListResponse* success; + + _MNSCacheService_getAppkeyListByIP_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +class MNSCacheServiceClient : virtual public MNSCacheServiceIf { + public: + MNSCacheServiceClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> prot) : + piprot_(prot), + poprot_(prot) { + iprot_ = prot.get(); + oprot_ = prot.get(); + } + MNSCacheServiceClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> iprot, boost::shared_ptr< ::apache::thrift::protocol::TProtocol> oprot) : + piprot_(iprot), + poprot_(oprot) { + iprot_ = iprot.get(); + oprot_ = oprot.get(); + } + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol() { + return piprot_; + } + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol() { + return poprot_; + } + void getMNSCache(MNSResponse& _return, const std::string& appkey, const std::string& version, const std::string& env); + void send_getMNSCache(const std::string& appkey, const std::string& version, const std::string& env); + void recv_getMNSCache(MNSResponse& _return); + void getMNSCacheHttp(MNSResponse& _return, const std::string& appkey, const std::string& version, const std::string& env); + void send_getMNSCacheHttp(const std::string& appkey, const std::string& version, const std::string& env); + void recv_getMNSCacheHttp(MNSResponse& _return); + void getMNSCacheWithVersionCheck(MNSResponse& _return, const MnsRequest& req); + void send_getMNSCacheWithVersionCheck(const MnsRequest& req); + void recv_getMNSCacheWithVersionCheck(MNSResponse& _return); + void getMNSCacheByAppkeys(MNSBatchResponse& _return, const std::vector & appkeys, const std::string& protocol); + void send_getMNSCacheByAppkeys(const std::vector & appkeys, const std::string& protocol); + void recv_getMNSCacheByAppkeys(MNSBatchResponse& _return); + void getProvidersByIP(MNSResponse& _return, const std::string& ip); + void send_getProvidersByIP(const std::string& ip); + void recv_getProvidersByIP(MNSResponse& _return); + void getAppkeyListByIP(AppKeyListResponse& _return, const std::string& ip); + void send_getAppkeyListByIP(const std::string& ip); + void recv_getAppkeyListByIP(AppKeyListResponse& _return); + protected: + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> piprot_; + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> poprot_; + ::apache::thrift::protocol::TProtocol* iprot_; + ::apache::thrift::protocol::TProtocol* oprot_; +}; + +class MNSCacheServiceProcessor : public ::apache::thrift::TProcessor { + protected: + boost::shared_ptr iface_; + virtual bool process_fn(apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, std::string& fname, int32_t seqid, void* callContext); + private: + std::map processMap_; + void process_getMNSCache(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_getMNSCacheHttp(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_getMNSCacheWithVersionCheck(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_getMNSCacheByAppkeys(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_getProvidersByIP(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_getAppkeyListByIP(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + public: + MNSCacheServiceProcessor(boost::shared_ptr iface) : + iface_(iface) { + processMap_["getMNSCache"] = &MNSCacheServiceProcessor::process_getMNSCache; + processMap_["getMNSCacheHttp"] = &MNSCacheServiceProcessor::process_getMNSCacheHttp; + processMap_["getMNSCacheWithVersionCheck"] = &MNSCacheServiceProcessor::process_getMNSCacheWithVersionCheck; + processMap_["getMNSCacheByAppkeys"] = &MNSCacheServiceProcessor::process_getMNSCacheByAppkeys; + processMap_["getProvidersByIP"] = &MNSCacheServiceProcessor::process_getProvidersByIP; + processMap_["getAppkeyListByIP"] = &MNSCacheServiceProcessor::process_getAppkeyListByIP; + } + + virtual bool process(boost::shared_ptr piprot, boost::shared_ptr poprot, void* callContext); + virtual ~MNSCacheServiceProcessor() {} +}; + +class MNSCacheServiceProcessorFactory : public ::apache::thrift::TProcessorFactory { + public: + MNSCacheServiceProcessorFactory(const ::boost::shared_ptr< MNSCacheServiceIfFactory >& handlerFactory) : + handlerFactory_(handlerFactory) {} + + ::boost::shared_ptr< ::apache::thrift::TProcessor > getProcessor(const ::apache::thrift::TConnectionInfo& connInfo); + + protected: + ::boost::shared_ptr< MNSCacheServiceIfFactory > handlerFactory_; +}; + +class MNSCacheServiceMultiface : virtual public MNSCacheServiceIf { + public: + MNSCacheServiceMultiface(std::vector >& ifaces) : ifaces_(ifaces) { + } + virtual ~MNSCacheServiceMultiface() {} + protected: + std::vector > ifaces_; + MNSCacheServiceMultiface() {} + void add(boost::shared_ptr iface) { + ifaces_.push_back(iface); + } + public: + void getMNSCache(MNSResponse& _return, const std::string& appkey, const std::string& version, const std::string& env) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getMNSCache(_return, appkey, version, env); + return; + } else { + ifaces_[i]->getMNSCache(_return, appkey, version, env); + } + } + } + + void getMNSCacheHttp(MNSResponse& _return, const std::string& appkey, const std::string& version, const std::string& env) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getMNSCacheHttp(_return, appkey, version, env); + return; + } else { + ifaces_[i]->getMNSCacheHttp(_return, appkey, version, env); + } + } + } + + void getMNSCacheWithVersionCheck(MNSResponse& _return, const MnsRequest& req) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getMNSCacheWithVersionCheck(_return, req); + return; + } else { + ifaces_[i]->getMNSCacheWithVersionCheck(_return, req); + } + } + } + + void getMNSCacheByAppkeys(MNSBatchResponse& _return, const std::vector & appkeys, const std::string& protocol) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getMNSCacheByAppkeys(_return, appkeys, protocol); + return; + } else { + ifaces_[i]->getMNSCacheByAppkeys(_return, appkeys, protocol); + } + } + } + + void getProvidersByIP(MNSResponse& _return, const std::string& ip) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getProvidersByIP(_return, ip); + return; + } else { + ifaces_[i]->getProvidersByIP(_return, ip); + } + } + } + + void getAppkeyListByIP(AppKeyListResponse& _return, const std::string& ip) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getAppkeyListByIP(_return, ip); + return; + } else { + ifaces_[i]->getAppkeyListByIP(_return, ip); + } + } + } + +}; + +} // namespace + +#endif diff --git a/common/gen-cpp/ServiceAgent.cpp b/common/gen-cpp/ServiceAgent.cpp new file mode 100644 index 0000000..4aee0f3 --- /dev/null +++ b/common/gen-cpp/ServiceAgent.cpp @@ -0,0 +1,1428 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "ServiceAgent.h" + +namespace meituan_mns { + +uint32_t ServiceAgent_getServiceListByProtocol_args::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->req.read(iprot); + this->__isset.req = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ServiceAgent_getServiceListByProtocol_args::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ServiceAgent_getServiceListByProtocol_args"); + xfer += oprot->writeFieldBegin("req", ::apache::thrift::protocol::T_STRUCT, 1); + xfer += this->req.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t ServiceAgent_getServiceListByProtocol_pargs::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ServiceAgent_getServiceListByProtocol_pargs"); + xfer += oprot->writeFieldBegin("req", ::apache::thrift::protocol::T_STRUCT, 1); + xfer += (*(this->req)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t ServiceAgent_getServiceListByProtocol_result::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->success.read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ServiceAgent_getServiceListByProtocol_result::write(::apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("ServiceAgent_getServiceListByProtocol_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_STRUCT, 0); + xfer += this->success.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t ServiceAgent_getServiceListByProtocol_presult::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += (*(this->success)).read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ServiceAgent_getOriginServiceList_args::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->req.read(iprot); + this->__isset.req = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ServiceAgent_getOriginServiceList_args::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ServiceAgent_getOriginServiceList_args"); + xfer += oprot->writeFieldBegin("req", ::apache::thrift::protocol::T_STRUCT, 1); + xfer += this->req.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t ServiceAgent_getOriginServiceList_pargs::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ServiceAgent_getOriginServiceList_pargs"); + xfer += oprot->writeFieldBegin("req", ::apache::thrift::protocol::T_STRUCT, 1); + xfer += (*(this->req)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t ServiceAgent_getOriginServiceList_result::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->success.read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ServiceAgent_getOriginServiceList_result::write(::apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("ServiceAgent_getOriginServiceList_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_STRUCT, 0); + xfer += this->success.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t ServiceAgent_getOriginServiceList_presult::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += (*(this->success)).read(iprot); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ServiceAgent_registService_args::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->oService.read(iprot); + this->__isset.oService = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ServiceAgent_registService_args::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ServiceAgent_registService_args"); + xfer += oprot->writeFieldBegin("oService", ::apache::thrift::protocol::T_STRUCT, 1); + xfer += this->oService.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t ServiceAgent_registService_pargs::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ServiceAgent_registService_pargs"); + xfer += oprot->writeFieldBegin("oService", ::apache::thrift::protocol::T_STRUCT, 1); + xfer += (*(this->oService)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t ServiceAgent_registService_result::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->success); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ServiceAgent_registService_result::write(::apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("ServiceAgent_registService_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_I32, 0); + xfer += oprot->writeI32(this->success); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t ServiceAgent_registService_presult::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32((*(this->success))); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ServiceAgent_registServicewithCmd_args::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->uptCmd); + this->__isset.uptCmd = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->oService.read(iprot); + this->__isset.oService = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ServiceAgent_registServicewithCmd_args::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ServiceAgent_registServicewithCmd_args"); + xfer += oprot->writeFieldBegin("uptCmd", ::apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32(this->uptCmd); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("oService", ::apache::thrift::protocol::T_STRUCT, 2); + xfer += this->oService.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t ServiceAgent_registServicewithCmd_pargs::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ServiceAgent_registServicewithCmd_pargs"); + xfer += oprot->writeFieldBegin("uptCmd", ::apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32((*(this->uptCmd))); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("oService", ::apache::thrift::protocol::T_STRUCT, 2); + xfer += (*(this->oService)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t ServiceAgent_registServicewithCmd_result::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->success); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ServiceAgent_registServicewithCmd_result::write(::apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("ServiceAgent_registServicewithCmd_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_I32, 0); + xfer += oprot->writeI32(this->success); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t ServiceAgent_registServicewithCmd_presult::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32((*(this->success))); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ServiceAgent_unRegistService_args::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->oService.read(iprot); + this->__isset.oService = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ServiceAgent_unRegistService_args::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ServiceAgent_unRegistService_args"); + xfer += oprot->writeFieldBegin("oService", ::apache::thrift::protocol::T_STRUCT, 1); + xfer += this->oService.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t ServiceAgent_unRegistService_pargs::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ServiceAgent_unRegistService_pargs"); + xfer += oprot->writeFieldBegin("oService", ::apache::thrift::protocol::T_STRUCT, 1); + xfer += (*(this->oService)).write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t ServiceAgent_unRegistService_result::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->success); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ServiceAgent_unRegistService_result::write(::apache::thrift::protocol::TProtocol* oprot) const { + + uint32_t xfer = 0; + + xfer += oprot->writeStructBegin("ServiceAgent_unRegistService_result"); + + if (this->__isset.success) { + xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_I32, 0); + xfer += oprot->writeI32(this->success); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +uint32_t ServiceAgent_unRegistService_presult::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 0: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32((*(this->success))); + this->__isset.success = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +void ServiceAgentClient::getServiceListByProtocol(ProtocolResponse& _return, const ProtocolRequest& req) +{ + send_getServiceListByProtocol(req); + recv_getServiceListByProtocol(_return); +} + +void ServiceAgentClient::send_getServiceListByProtocol(const ProtocolRequest& req) +{ + int32_t cseqid = 0; + oprot_->writeMessageBegin("getServiceListByProtocol", ::apache::thrift::protocol::T_CALL, cseqid); + + ServiceAgent_getServiceListByProtocol_pargs args; + args.req = &req; + args.write(oprot_); + + oprot_->writeMessageEnd(); + oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); +} + +void ServiceAgentClient::recv_getServiceListByProtocol(ProtocolResponse& _return) +{ + + int32_t rseqid = 0; + std::string fname; + ::apache::thrift::protocol::TMessageType mtype; + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { + ::apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != ::apache::thrift::protocol::T_REPLY) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + if (fname.compare("getServiceListByProtocol") != 0) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + ServiceAgent_getServiceListByProtocol_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + + if (result.__isset.success) { + // _return pointer has now been filled + return; + } + throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "getServiceListByProtocol failed: unknown result"); +} + +void ServiceAgentClient::getOriginServiceList(ProtocolResponse& _return, const ProtocolRequest& req) +{ + send_getOriginServiceList(req); + recv_getOriginServiceList(_return); +} + +void ServiceAgentClient::send_getOriginServiceList(const ProtocolRequest& req) +{ + int32_t cseqid = 0; + oprot_->writeMessageBegin("getOriginServiceList", ::apache::thrift::protocol::T_CALL, cseqid); + + ServiceAgent_getOriginServiceList_pargs args; + args.req = &req; + args.write(oprot_); + + oprot_->writeMessageEnd(); + oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); +} + +void ServiceAgentClient::recv_getOriginServiceList(ProtocolResponse& _return) +{ + + int32_t rseqid = 0; + std::string fname; + ::apache::thrift::protocol::TMessageType mtype; + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { + ::apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != ::apache::thrift::protocol::T_REPLY) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + if (fname.compare("getOriginServiceList") != 0) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + ServiceAgent_getOriginServiceList_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + + if (result.__isset.success) { + // _return pointer has now been filled + return; + } + throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "getOriginServiceList failed: unknown result"); +} + +int32_t ServiceAgentClient::registService(const SGService& oService) +{ + send_registService(oService); + return recv_registService(); +} + +void ServiceAgentClient::send_registService(const SGService& oService) +{ + int32_t cseqid = 0; + oprot_->writeMessageBegin("registService", ::apache::thrift::protocol::T_CALL, cseqid); + + ServiceAgent_registService_pargs args; + args.oService = &oService; + args.write(oprot_); + + oprot_->writeMessageEnd(); + oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); +} + +int32_t ServiceAgentClient::recv_registService() +{ + + int32_t rseqid = 0; + std::string fname; + ::apache::thrift::protocol::TMessageType mtype; + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { + ::apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != ::apache::thrift::protocol::T_REPLY) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + if (fname.compare("registService") != 0) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + int32_t _return; + ServiceAgent_registService_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + + if (result.__isset.success) { + return _return; + } + throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "registService failed: unknown result"); +} + +int32_t ServiceAgentClient::registServicewithCmd(const int32_t uptCmd, const SGService& oService) +{ + send_registServicewithCmd(uptCmd, oService); + return recv_registServicewithCmd(); +} + +void ServiceAgentClient::send_registServicewithCmd(const int32_t uptCmd, const SGService& oService) +{ + int32_t cseqid = 0; + oprot_->writeMessageBegin("registServicewithCmd", ::apache::thrift::protocol::T_CALL, cseqid); + + ServiceAgent_registServicewithCmd_pargs args; + args.uptCmd = &uptCmd; + args.oService = &oService; + args.write(oprot_); + + oprot_->writeMessageEnd(); + oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); +} + +int32_t ServiceAgentClient::recv_registServicewithCmd() +{ + + int32_t rseqid = 0; + std::string fname; + ::apache::thrift::protocol::TMessageType mtype; + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { + ::apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != ::apache::thrift::protocol::T_REPLY) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + if (fname.compare("registServicewithCmd") != 0) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + int32_t _return; + ServiceAgent_registServicewithCmd_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + + if (result.__isset.success) { + return _return; + } + throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "registServicewithCmd failed: unknown result"); +} + +int32_t ServiceAgentClient::unRegistService(const SGService& oService) +{ + send_unRegistService(oService); + return recv_unRegistService(); +} + +void ServiceAgentClient::send_unRegistService(const SGService& oService) +{ + int32_t cseqid = 0; + oprot_->writeMessageBegin("unRegistService", ::apache::thrift::protocol::T_CALL, cseqid); + + ServiceAgent_unRegistService_pargs args; + args.oService = &oService; + args.write(oprot_); + + oprot_->writeMessageEnd(); + oprot_->getTransport()->writeEnd(); + oprot_->getTransport()->flush(); +} + +int32_t ServiceAgentClient::recv_unRegistService() +{ + + int32_t rseqid = 0; + std::string fname; + ::apache::thrift::protocol::TMessageType mtype; + + iprot_->readMessageBegin(fname, mtype, rseqid); + if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { + ::apache::thrift::TApplicationException x; + x.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + throw x; + } + if (mtype != ::apache::thrift::protocol::T_REPLY) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + if (fname.compare("unRegistService") != 0) { + iprot_->skip(::apache::thrift::protocol::T_STRUCT); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + } + int32_t _return; + ServiceAgent_unRegistService_presult result; + result.success = &_return; + result.read(iprot_); + iprot_->readMessageEnd(); + iprot_->getTransport()->readEnd(); + + if (result.__isset.success) { + return _return; + } + throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "unRegistService failed: unknown result"); +} + +bool ServiceAgentProcessor::process(boost::shared_ptr piprot, boost::shared_ptr poprot, void* callContext) { + + ::apache::thrift::protocol::TProtocol* iprot = piprot.get(); + ::apache::thrift::protocol::TProtocol* oprot = poprot.get(); + std::string fname; + ::apache::thrift::protocol::TMessageType mtype; + int32_t seqid; + + iprot->readMessageBegin(fname, mtype, seqid); + + if (mtype != ::apache::thrift::protocol::T_CALL && mtype != ::apache::thrift::protocol::T_ONEWAY) { + iprot->skip(::apache::thrift::protocol::T_STRUCT); + iprot->readMessageEnd(); + iprot->getTransport()->readEnd(); + ::apache::thrift::TApplicationException x(::apache::thrift::TApplicationException::INVALID_MESSAGE_TYPE); + oprot->writeMessageBegin(fname, ::apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return true; + } + + return process_fn(iprot, oprot, fname, seqid, callContext); +} + +bool ServiceAgentProcessor::process_fn(apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, std::string& fname, int32_t seqid, void* callContext) { + std::map::iterator pfn; + pfn = processMap_.find(fname); + if (pfn == processMap_.end()) { + iprot->skip(apache::thrift::protocol::T_STRUCT); + iprot->readMessageEnd(); + iprot->getTransport()->readEnd(); + ::apache::thrift::TApplicationException x(::apache::thrift::TApplicationException::UNKNOWN_METHOD, "Invalid method name: '"+fname+"'"); + oprot->writeMessageBegin(fname, ::apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return true; + } + (this->*(pfn->second))(seqid, iprot, oprot, callContext); + return true; +} + +void ServiceAgentProcessor::process_getServiceListByProtocol(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext) +{ + void* ctx = NULL; + if (this->eventHandler_.get() != NULL) { + ctx = this->eventHandler_->getContext("ServiceAgent.getServiceListByProtocol", callContext); + } + apache::thrift::TProcessorContextFreer freer(this->eventHandler_.get(), ctx, "ServiceAgent.getServiceListByProtocol"); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preRead(ctx, "ServiceAgent.getServiceListByProtocol"); + } + + ServiceAgent_getServiceListByProtocol_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postRead(ctx, "ServiceAgent.getServiceListByProtocol", bytes); + } + + ServiceAgent_getServiceListByProtocol_result result; + try { + iface_->getServiceListByProtocol(result.success, args.req); + result.__isset.success = true; + } catch (const std::exception& e) { + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->handlerError(ctx, "ServiceAgent.getServiceListByProtocol"); + } + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("getServiceListByProtocol", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preWrite(ctx, "ServiceAgent.getServiceListByProtocol"); + } + + oprot->writeMessageBegin("getServiceListByProtocol", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postWrite(ctx, "ServiceAgent.getServiceListByProtocol", bytes); + } +} + +void ServiceAgentProcessor::process_getOriginServiceList(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext) +{ + void* ctx = NULL; + if (this->eventHandler_.get() != NULL) { + ctx = this->eventHandler_->getContext("ServiceAgent.getOriginServiceList", callContext); + } + apache::thrift::TProcessorContextFreer freer(this->eventHandler_.get(), ctx, "ServiceAgent.getOriginServiceList"); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preRead(ctx, "ServiceAgent.getOriginServiceList"); + } + + ServiceAgent_getOriginServiceList_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postRead(ctx, "ServiceAgent.getOriginServiceList", bytes); + } + + ServiceAgent_getOriginServiceList_result result; + try { + iface_->getOriginServiceList(result.success, args.req); + result.__isset.success = true; + } catch (const std::exception& e) { + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->handlerError(ctx, "ServiceAgent.getOriginServiceList"); + } + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("getOriginServiceList", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preWrite(ctx, "ServiceAgent.getOriginServiceList"); + } + + oprot->writeMessageBegin("getOriginServiceList", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postWrite(ctx, "ServiceAgent.getOriginServiceList", bytes); + } +} + +void ServiceAgentProcessor::process_registService(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext) +{ + void* ctx = NULL; + if (this->eventHandler_.get() != NULL) { + ctx = this->eventHandler_->getContext("ServiceAgent.registService", callContext); + } + apache::thrift::TProcessorContextFreer freer(this->eventHandler_.get(), ctx, "ServiceAgent.registService"); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preRead(ctx, "ServiceAgent.registService"); + } + + ServiceAgent_registService_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postRead(ctx, "ServiceAgent.registService", bytes); + } + + ServiceAgent_registService_result result; + try { + result.success = iface_->registService(args.oService); + result.__isset.success = true; + } catch (const std::exception& e) { + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->handlerError(ctx, "ServiceAgent.registService"); + } + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("registService", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preWrite(ctx, "ServiceAgent.registService"); + } + + oprot->writeMessageBegin("registService", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postWrite(ctx, "ServiceAgent.registService", bytes); + } +} + +void ServiceAgentProcessor::process_registServicewithCmd(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext) +{ + void* ctx = NULL; + if (this->eventHandler_.get() != NULL) { + ctx = this->eventHandler_->getContext("ServiceAgent.registServicewithCmd", callContext); + } + apache::thrift::TProcessorContextFreer freer(this->eventHandler_.get(), ctx, "ServiceAgent.registServicewithCmd"); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preRead(ctx, "ServiceAgent.registServicewithCmd"); + } + + ServiceAgent_registServicewithCmd_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postRead(ctx, "ServiceAgent.registServicewithCmd", bytes); + } + + ServiceAgent_registServicewithCmd_result result; + try { + result.success = iface_->registServicewithCmd(args.uptCmd, args.oService); + result.__isset.success = true; + } catch (const std::exception& e) { + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->handlerError(ctx, "ServiceAgent.registServicewithCmd"); + } + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("registServicewithCmd", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preWrite(ctx, "ServiceAgent.registServicewithCmd"); + } + + oprot->writeMessageBegin("registServicewithCmd", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postWrite(ctx, "ServiceAgent.registServicewithCmd", bytes); + } +} + +void ServiceAgentProcessor::process_unRegistService(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext) +{ + void* ctx = NULL; + if (this->eventHandler_.get() != NULL) { + ctx = this->eventHandler_->getContext("ServiceAgent.unRegistService", callContext); + } + apache::thrift::TProcessorContextFreer freer(this->eventHandler_.get(), ctx, "ServiceAgent.unRegistService"); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preRead(ctx, "ServiceAgent.unRegistService"); + } + + ServiceAgent_unRegistService_args args; + args.read(iprot); + iprot->readMessageEnd(); + uint32_t bytes = iprot->getTransport()->readEnd(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postRead(ctx, "ServiceAgent.unRegistService", bytes); + } + + ServiceAgent_unRegistService_result result; + try { + result.success = iface_->unRegistService(args.oService); + result.__isset.success = true; + } catch (const std::exception& e) { + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->handlerError(ctx, "ServiceAgent.unRegistService"); + } + + apache::thrift::TApplicationException x(e.what()); + oprot->writeMessageBegin("unRegistService", apache::thrift::protocol::T_EXCEPTION, seqid); + x.write(oprot); + oprot->writeMessageEnd(); + oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + return; + } + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->preWrite(ctx, "ServiceAgent.unRegistService"); + } + + oprot->writeMessageBegin("unRegistService", apache::thrift::protocol::T_REPLY, seqid); + result.write(oprot); + oprot->writeMessageEnd(); + bytes = oprot->getTransport()->writeEnd(); + oprot->getTransport()->flush(); + + if (this->eventHandler_.get() != NULL) { + this->eventHandler_->postWrite(ctx, "ServiceAgent.unRegistService", bytes); + } +} + +::boost::shared_ptr< ::apache::thrift::TProcessor > ServiceAgentProcessorFactory::getProcessor(const ::apache::thrift::TConnectionInfo& connInfo) { + ::apache::thrift::ReleaseHandler< ServiceAgentIfFactory > cleanup(handlerFactory_); + ::boost::shared_ptr< ServiceAgentIf > handler(handlerFactory_->getHandler(connInfo), cleanup); + ::boost::shared_ptr< ::apache::thrift::TProcessor > processor(new ServiceAgentProcessor(handler)); + return processor; +} +} // namespace + diff --git a/common/gen-cpp/ServiceAgent.h b/common/gen-cpp/ServiceAgent.h new file mode 100644 index 0000000..b20dd69 --- /dev/null +++ b/common/gen-cpp/ServiceAgent.h @@ -0,0 +1,772 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef ServiceAgent_H +#define ServiceAgent_H + +#include +#include "naming_service_types.h" + +namespace meituan_mns { + +class ServiceAgentIf { + public: + virtual ~ServiceAgentIf() {} + virtual void getServiceListByProtocol(ProtocolResponse& _return, const ProtocolRequest& req) = 0; + virtual void getOriginServiceList(ProtocolResponse& _return, const ProtocolRequest& req) = 0; + virtual int32_t registService(const SGService& oService) = 0; + virtual int32_t registServicewithCmd(const int32_t uptCmd, const SGService& oService) = 0; + virtual int32_t unRegistService(const SGService& oService) = 0; +}; + +class ServiceAgentIfFactory { + public: + typedef ServiceAgentIf Handler; + + virtual ~ServiceAgentIfFactory() {} + + virtual ServiceAgentIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo) = 0; + virtual void releaseHandler(ServiceAgentIf* /* handler */) = 0; +}; + +class ServiceAgentIfSingletonFactory : virtual public ServiceAgentIfFactory { + public: + ServiceAgentIfSingletonFactory(const boost::shared_ptr& iface) : iface_(iface) {} + virtual ~ServiceAgentIfSingletonFactory() {} + + virtual ServiceAgentIf* getHandler(const ::apache::thrift::TConnectionInfo&) { + return iface_.get(); + } + virtual void releaseHandler(ServiceAgentIf* /* handler */) {} + + protected: + boost::shared_ptr iface_; +}; + +class ServiceAgentNull : virtual public ServiceAgentIf { + public: + virtual ~ServiceAgentNull() {} + void getServiceListByProtocol(ProtocolResponse& /* _return */, const ProtocolRequest& /* req */) { + return; + } + void getOriginServiceList(ProtocolResponse& /* _return */, const ProtocolRequest& /* req */) { + return; + } + int32_t registService(const SGService& /* oService */) { + int32_t _return = 0; + return _return; + } + int32_t registServicewithCmd(const int32_t /* uptCmd */, const SGService& /* oService */) { + int32_t _return = 0; + return _return; + } + int32_t unRegistService(const SGService& /* oService */) { + int32_t _return = 0; + return _return; + } +}; + +typedef struct _ServiceAgent_getServiceListByProtocol_args__isset { + _ServiceAgent_getServiceListByProtocol_args__isset() : req(false) {} + bool req; +} _ServiceAgent_getServiceListByProtocol_args__isset; + +class ServiceAgent_getServiceListByProtocol_args { + public: + + ServiceAgent_getServiceListByProtocol_args() { + } + + virtual ~ServiceAgent_getServiceListByProtocol_args() throw() {} + + ProtocolRequest req; + + _ServiceAgent_getServiceListByProtocol_args__isset __isset; + + void __set_req(const ProtocolRequest& val) { + req = val; + } + + bool operator == (const ServiceAgent_getServiceListByProtocol_args & rhs) const + { + if (!(req == rhs.req)) + return false; + return true; + } + bool operator != (const ServiceAgent_getServiceListByProtocol_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_getServiceListByProtocol_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class ServiceAgent_getServiceListByProtocol_pargs { + public: + + + virtual ~ServiceAgent_getServiceListByProtocol_pargs() throw() {} + + const ProtocolRequest* req; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_getServiceListByProtocol_result__isset { + _ServiceAgent_getServiceListByProtocol_result__isset() : success(false) {} + bool success; +} _ServiceAgent_getServiceListByProtocol_result__isset; + +class ServiceAgent_getServiceListByProtocol_result { + public: + + ServiceAgent_getServiceListByProtocol_result() { + } + + virtual ~ServiceAgent_getServiceListByProtocol_result() throw() {} + + ProtocolResponse success; + + _ServiceAgent_getServiceListByProtocol_result__isset __isset; + + void __set_success(const ProtocolResponse& val) { + success = val; + } + + bool operator == (const ServiceAgent_getServiceListByProtocol_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const ServiceAgent_getServiceListByProtocol_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_getServiceListByProtocol_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_getServiceListByProtocol_presult__isset { + _ServiceAgent_getServiceListByProtocol_presult__isset() : success(false) {} + bool success; +} _ServiceAgent_getServiceListByProtocol_presult__isset; + +class ServiceAgent_getServiceListByProtocol_presult { + public: + + + virtual ~ServiceAgent_getServiceListByProtocol_presult() throw() {} + + ProtocolResponse* success; + + _ServiceAgent_getServiceListByProtocol_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +typedef struct _ServiceAgent_getOriginServiceList_args__isset { + _ServiceAgent_getOriginServiceList_args__isset() : req(false) {} + bool req; +} _ServiceAgent_getOriginServiceList_args__isset; + +class ServiceAgent_getOriginServiceList_args { + public: + + ServiceAgent_getOriginServiceList_args() { + } + + virtual ~ServiceAgent_getOriginServiceList_args() throw() {} + + ProtocolRequest req; + + _ServiceAgent_getOriginServiceList_args__isset __isset; + + void __set_req(const ProtocolRequest& val) { + req = val; + } + + bool operator == (const ServiceAgent_getOriginServiceList_args & rhs) const + { + if (!(req == rhs.req)) + return false; + return true; + } + bool operator != (const ServiceAgent_getOriginServiceList_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_getOriginServiceList_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class ServiceAgent_getOriginServiceList_pargs { + public: + + + virtual ~ServiceAgent_getOriginServiceList_pargs() throw() {} + + const ProtocolRequest* req; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_getOriginServiceList_result__isset { + _ServiceAgent_getOriginServiceList_result__isset() : success(false) {} + bool success; +} _ServiceAgent_getOriginServiceList_result__isset; + +class ServiceAgent_getOriginServiceList_result { + public: + + ServiceAgent_getOriginServiceList_result() { + } + + virtual ~ServiceAgent_getOriginServiceList_result() throw() {} + + ProtocolResponse success; + + _ServiceAgent_getOriginServiceList_result__isset __isset; + + void __set_success(const ProtocolResponse& val) { + success = val; + } + + bool operator == (const ServiceAgent_getOriginServiceList_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const ServiceAgent_getOriginServiceList_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_getOriginServiceList_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_getOriginServiceList_presult__isset { + _ServiceAgent_getOriginServiceList_presult__isset() : success(false) {} + bool success; +} _ServiceAgent_getOriginServiceList_presult__isset; + +class ServiceAgent_getOriginServiceList_presult { + public: + + + virtual ~ServiceAgent_getOriginServiceList_presult() throw() {} + + ProtocolResponse* success; + + _ServiceAgent_getOriginServiceList_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +typedef struct _ServiceAgent_registService_args__isset { + _ServiceAgent_registService_args__isset() : oService(false) {} + bool oService; +} _ServiceAgent_registService_args__isset; + +class ServiceAgent_registService_args { + public: + + ServiceAgent_registService_args() { + } + + virtual ~ServiceAgent_registService_args() throw() {} + + SGService oService; + + _ServiceAgent_registService_args__isset __isset; + + void __set_oService(const SGService& val) { + oService = val; + } + + bool operator == (const ServiceAgent_registService_args & rhs) const + { + if (!(oService == rhs.oService)) + return false; + return true; + } + bool operator != (const ServiceAgent_registService_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_registService_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class ServiceAgent_registService_pargs { + public: + + + virtual ~ServiceAgent_registService_pargs() throw() {} + + const SGService* oService; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_registService_result__isset { + _ServiceAgent_registService_result__isset() : success(false) {} + bool success; +} _ServiceAgent_registService_result__isset; + +class ServiceAgent_registService_result { + public: + + ServiceAgent_registService_result() : success(0) { + } + + virtual ~ServiceAgent_registService_result() throw() {} + + int32_t success; + + _ServiceAgent_registService_result__isset __isset; + + void __set_success(const int32_t val) { + success = val; + } + + bool operator == (const ServiceAgent_registService_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const ServiceAgent_registService_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_registService_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_registService_presult__isset { + _ServiceAgent_registService_presult__isset() : success(false) {} + bool success; +} _ServiceAgent_registService_presult__isset; + +class ServiceAgent_registService_presult { + public: + + + virtual ~ServiceAgent_registService_presult() throw() {} + + int32_t* success; + + _ServiceAgent_registService_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +typedef struct _ServiceAgent_registServicewithCmd_args__isset { + _ServiceAgent_registServicewithCmd_args__isset() : uptCmd(false), oService(false) {} + bool uptCmd; + bool oService; +} _ServiceAgent_registServicewithCmd_args__isset; + +class ServiceAgent_registServicewithCmd_args { + public: + + ServiceAgent_registServicewithCmd_args() : uptCmd(0) { + } + + virtual ~ServiceAgent_registServicewithCmd_args() throw() {} + + int32_t uptCmd; + SGService oService; + + _ServiceAgent_registServicewithCmd_args__isset __isset; + + void __set_uptCmd(const int32_t val) { + uptCmd = val; + } + + void __set_oService(const SGService& val) { + oService = val; + } + + bool operator == (const ServiceAgent_registServicewithCmd_args & rhs) const + { + if (!(uptCmd == rhs.uptCmd)) + return false; + if (!(oService == rhs.oService)) + return false; + return true; + } + bool operator != (const ServiceAgent_registServicewithCmd_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_registServicewithCmd_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class ServiceAgent_registServicewithCmd_pargs { + public: + + + virtual ~ServiceAgent_registServicewithCmd_pargs() throw() {} + + const int32_t* uptCmd; + const SGService* oService; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_registServicewithCmd_result__isset { + _ServiceAgent_registServicewithCmd_result__isset() : success(false) {} + bool success; +} _ServiceAgent_registServicewithCmd_result__isset; + +class ServiceAgent_registServicewithCmd_result { + public: + + ServiceAgent_registServicewithCmd_result() : success(0) { + } + + virtual ~ServiceAgent_registServicewithCmd_result() throw() {} + + int32_t success; + + _ServiceAgent_registServicewithCmd_result__isset __isset; + + void __set_success(const int32_t val) { + success = val; + } + + bool operator == (const ServiceAgent_registServicewithCmd_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const ServiceAgent_registServicewithCmd_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_registServicewithCmd_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_registServicewithCmd_presult__isset { + _ServiceAgent_registServicewithCmd_presult__isset() : success(false) {} + bool success; +} _ServiceAgent_registServicewithCmd_presult__isset; + +class ServiceAgent_registServicewithCmd_presult { + public: + + + virtual ~ServiceAgent_registServicewithCmd_presult() throw() {} + + int32_t* success; + + _ServiceAgent_registServicewithCmd_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +typedef struct _ServiceAgent_unRegistService_args__isset { + _ServiceAgent_unRegistService_args__isset() : oService(false) {} + bool oService; +} _ServiceAgent_unRegistService_args__isset; + +class ServiceAgent_unRegistService_args { + public: + + ServiceAgent_unRegistService_args() { + } + + virtual ~ServiceAgent_unRegistService_args() throw() {} + + SGService oService; + + _ServiceAgent_unRegistService_args__isset __isset; + + void __set_oService(const SGService& val) { + oService = val; + } + + bool operator == (const ServiceAgent_unRegistService_args & rhs) const + { + if (!(oService == rhs.oService)) + return false; + return true; + } + bool operator != (const ServiceAgent_unRegistService_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_unRegistService_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class ServiceAgent_unRegistService_pargs { + public: + + + virtual ~ServiceAgent_unRegistService_pargs() throw() {} + + const SGService* oService; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_unRegistService_result__isset { + _ServiceAgent_unRegistService_result__isset() : success(false) {} + bool success; +} _ServiceAgent_unRegistService_result__isset; + +class ServiceAgent_unRegistService_result { + public: + + ServiceAgent_unRegistService_result() : success(0) { + } + + virtual ~ServiceAgent_unRegistService_result() throw() {} + + int32_t success; + + _ServiceAgent_unRegistService_result__isset __isset; + + void __set_success(const int32_t val) { + success = val; + } + + bool operator == (const ServiceAgent_unRegistService_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const ServiceAgent_unRegistService_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_unRegistService_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_unRegistService_presult__isset { + _ServiceAgent_unRegistService_presult__isset() : success(false) {} + bool success; +} _ServiceAgent_unRegistService_presult__isset; + +class ServiceAgent_unRegistService_presult { + public: + + + virtual ~ServiceAgent_unRegistService_presult() throw() {} + + int32_t* success; + + _ServiceAgent_unRegistService_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +class ServiceAgentClient : virtual public ServiceAgentIf { + public: + ServiceAgentClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> prot) : + piprot_(prot), + poprot_(prot) { + iprot_ = prot.get(); + oprot_ = prot.get(); + } + ServiceAgentClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> iprot, boost::shared_ptr< ::apache::thrift::protocol::TProtocol> oprot) : + piprot_(iprot), + poprot_(oprot) { + iprot_ = iprot.get(); + oprot_ = oprot.get(); + } + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol() { + return piprot_; + } + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol() { + return poprot_; + } + void getServiceListByProtocol(ProtocolResponse& _return, const ProtocolRequest& req); + void send_getServiceListByProtocol(const ProtocolRequest& req); + void recv_getServiceListByProtocol(ProtocolResponse& _return); + void getOriginServiceList(ProtocolResponse& _return, const ProtocolRequest& req); + void send_getOriginServiceList(const ProtocolRequest& req); + void recv_getOriginServiceList(ProtocolResponse& _return); + int32_t registService(const SGService& oService); + void send_registService(const SGService& oService); + int32_t recv_registService(); + int32_t registServicewithCmd(const int32_t uptCmd, const SGService& oService); + void send_registServicewithCmd(const int32_t uptCmd, const SGService& oService); + int32_t recv_registServicewithCmd(); + int32_t unRegistService(const SGService& oService); + void send_unRegistService(const SGService& oService); + int32_t recv_unRegistService(); + protected: + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> piprot_; + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> poprot_; + ::apache::thrift::protocol::TProtocol* iprot_; + ::apache::thrift::protocol::TProtocol* oprot_; +}; + +class ServiceAgentProcessor : public ::apache::thrift::TProcessor { + protected: + boost::shared_ptr iface_; + virtual bool process_fn(apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, std::string& fname, int32_t seqid, void* callContext); + private: + std::map processMap_; + void process_getServiceListByProtocol(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_getOriginServiceList(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_registService(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_registServicewithCmd(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_unRegistService(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + public: + ServiceAgentProcessor(boost::shared_ptr iface) : + iface_(iface) { + processMap_["getServiceListByProtocol"] = &ServiceAgentProcessor::process_getServiceListByProtocol; + processMap_["getOriginServiceList"] = &ServiceAgentProcessor::process_getOriginServiceList; + processMap_["registService"] = &ServiceAgentProcessor::process_registService; + processMap_["registServicewithCmd"] = &ServiceAgentProcessor::process_registServicewithCmd; + processMap_["unRegistService"] = &ServiceAgentProcessor::process_unRegistService; + } + + virtual bool process(boost::shared_ptr piprot, boost::shared_ptr poprot, void* callContext); + virtual ~ServiceAgentProcessor() {} +}; + +class ServiceAgentProcessorFactory : public ::apache::thrift::TProcessorFactory { + public: + ServiceAgentProcessorFactory(const ::boost::shared_ptr< ServiceAgentIfFactory >& handlerFactory) : + handlerFactory_(handlerFactory) {} + + ::boost::shared_ptr< ::apache::thrift::TProcessor > getProcessor(const ::apache::thrift::TConnectionInfo& connInfo); + + protected: + ::boost::shared_ptr< ServiceAgentIfFactory > handlerFactory_; +}; + +class ServiceAgentMultiface : virtual public ServiceAgentIf { + public: + ServiceAgentMultiface(std::vector >& ifaces) : ifaces_(ifaces) { + } + virtual ~ServiceAgentMultiface() {} + protected: + std::vector > ifaces_; + ServiceAgentMultiface() {} + void add(boost::shared_ptr iface) { + ifaces_.push_back(iface); + } + public: + void getServiceListByProtocol(ProtocolResponse& _return, const ProtocolRequest& req) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getServiceListByProtocol(_return, req); + return; + } else { + ifaces_[i]->getServiceListByProtocol(_return, req); + } + } + } + + void getOriginServiceList(ProtocolResponse& _return, const ProtocolRequest& req) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getOriginServiceList(_return, req); + return; + } else { + ifaces_[i]->getOriginServiceList(_return, req); + } + } + } + + int32_t registService(const SGService& oService) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + return ifaces_[i]->registService(oService); + } else { + ifaces_[i]->registService(oService); + } + } + } + + int32_t registServicewithCmd(const int32_t uptCmd, const SGService& oService) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + return ifaces_[i]->registServicewithCmd(uptCmd, oService); + } else { + ifaces_[i]->registServicewithCmd(uptCmd, oService); + } + } + } + + int32_t unRegistService(const SGService& oService) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + return ifaces_[i]->unRegistService(oService); + } else { + ifaces_[i]->unRegistService(oService); + } + } + } + +}; + +} // namespace + +#endif diff --git a/common/gen-cpp/ServiceAgent_server.skeleton.cpp b/common/gen-cpp/ServiceAgent_server.skeleton.cpp new file mode 100644 index 0000000..311d1e7 --- /dev/null +++ b/common/gen-cpp/ServiceAgent_server.skeleton.cpp @@ -0,0 +1,64 @@ +// This autogenerated skeleton file illustrates how to build a server. +// You should copy it to another filename to avoid overwriting it. + +#include "ServiceAgent.h" +#include +#include +#include +#include + +using namespace ::apache::thrift; +using namespace ::apache::thrift::protocol; +using namespace ::apache::thrift::transport; +using namespace ::apache::thrift::server; + +using boost::shared_ptr; + +using namespace ::meituan_mns; + +class ServiceAgentHandler : virtual public ServiceAgentIf { + public: + ServiceAgentHandler() { + // Your initialization goes here + } + + void getServiceListByProtocol(ProtocolResponse& _return, const ProtocolRequest& req) { + // Your implementation goes here + printf("getServiceListByProtocol\n"); + } + + void getOriginServiceList(ProtocolResponse& _return, const ProtocolRequest& req) { + // Your implementation goes here + printf("getOriginServiceList\n"); + } + + int32_t registService(const SGService& oService) { + // Your implementation goes here + printf("registService\n"); + } + + int32_t registServicewithCmd(const int32_t uptCmd, const SGService& oService) { + // Your implementation goes here + printf("registServicewithCmd\n"); + } + + int32_t unRegistService(const SGService& oService) { + // Your implementation goes here + printf("unRegistService\n"); + } + +}; + +int main(int argc, char **argv) { + int port = 9090; + shared_ptr handler(new ServiceAgentHandler()); + shared_ptr processor(new ServiceAgentProcessor(handler)); + shared_ptr serverTransport(new TServerSocket(port)); + shared_ptr transportFactory(new TBufferedTransportFactory()); + shared_ptr protocolFactory(new TBinaryProtocolFactory()); + + TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory); + server.serve(); + return 0; +} + diff --git a/common/gen-cpp/ThriftSpans_constants.cpp b/common/gen-cpp/ThriftSpans_constants.cpp new file mode 100644 index 0000000..7c9f006 --- /dev/null +++ b/common/gen-cpp/ThriftSpans_constants.cpp @@ -0,0 +1,17 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "ThriftSpans_constants.h" + + + +const ThriftSpansConstants g_ThriftSpans_constants; + +ThriftSpansConstants::ThriftSpansConstants() { +} + + + diff --git a/common/gen-cpp/ThriftSpans_constants.h b/common/gen-cpp/ThriftSpans_constants.h new file mode 100644 index 0000000..d5d80b9 --- /dev/null +++ b/common/gen-cpp/ThriftSpans_constants.h @@ -0,0 +1,24 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef ThriftSpans_CONSTANTS_H +#define ThriftSpans_CONSTANTS_H + +#include "ThriftSpans_types.h" + + + +class ThriftSpansConstants { + public: + ThriftSpansConstants(); + +}; + +extern const ThriftSpansConstants g_ThriftSpans_constants; + + + +#endif diff --git a/common/gen-cpp/ThriftSpans_types.cpp b/common/gen-cpp/ThriftSpans_types.cpp new file mode 100644 index 0000000..eebe512 --- /dev/null +++ b/common/gen-cpp/ThriftSpans_types.cpp @@ -0,0 +1,669 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "ThriftSpans_types.h" + + + +int _kStatusCodeValues[] = { + StatusCode::SUCCESS, + StatusCode::EXCEPTION, + StatusCode::TIMEOUT, + StatusCode::DROP +}; +const char* _kStatusCodeNames[] = { + "SUCCESS", + "EXCEPTION", + "TIMEOUT", + "DROP" +}; +const std::map _StatusCode_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(4, _kStatusCodeValues, _kStatusCodeNames), ::apache::thrift::TEnumIterator(-1, NULL, NULL)); + +const char* Endpoint::ascii_fingerprint = "C7D2D58463AC91C552EE8B325EA2ACCC"; +const uint8_t Endpoint::binary_fingerprint[16] = {0xC7,0xD2,0xD5,0x84,0x63,0xAC,0x91,0xC5,0x52,0xEE,0x8B,0x32,0x5E,0xA2,0xAC,0xCC}; + +uint32_t Endpoint::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + bool isset_ip = false; + bool isset_port = false; + bool isset_appKey = false; + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->ip); + isset_ip = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_I16) { + xfer += iprot->readI16(this->port); + isset_port = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->appKey); + isset_appKey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + if (!isset_ip) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_port) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_appKey) + throw TProtocolException(TProtocolException::INVALID_DATA); + return xfer; +} + +uint32_t Endpoint::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("Endpoint"); + xfer += oprot->writeFieldBegin("ip", ::apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32(this->ip); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("port", ::apache::thrift::protocol::T_I16, 2); + xfer += oprot->writeI16(this->port); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("appKey", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString(this->appKey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* Annotation::ascii_fingerprint = "CE5BE9A8A7BD398538F703F899B08A94"; +const uint8_t Annotation::binary_fingerprint[16] = {0xCE,0x5B,0xE9,0xA8,0xA7,0xBD,0x39,0x85,0x38,0xF7,0x03,0xF8,0x99,0xB0,0x8A,0x94}; + +uint32_t Annotation::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + bool isset_value = false; + bool isset_timestamp = false; + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->value); + isset_value = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->timestamp); + isset_timestamp = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->duration); + this->__isset.duration = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + if (!isset_value) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_timestamp) + throw TProtocolException(TProtocolException::INVALID_DATA); + return xfer; +} + +uint32_t Annotation::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("Annotation"); + xfer += oprot->writeFieldBegin("value", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->value); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("timestamp", ::apache::thrift::protocol::T_I64, 2); + xfer += oprot->writeI64(this->timestamp); + xfer += oprot->writeFieldEnd(); + if (this->__isset.duration) { + xfer += oprot->writeFieldBegin("duration", ::apache::thrift::protocol::T_I32, 3); + xfer += oprot->writeI32(this->duration); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* KVAnnotation::ascii_fingerprint = "07A9615F837F7D0A952B595DD3020972"; +const uint8_t KVAnnotation::binary_fingerprint[16] = {0x07,0xA9,0x61,0x5F,0x83,0x7F,0x7D,0x0A,0x95,0x2B,0x59,0x5D,0xD3,0x02,0x09,0x72}; + +uint32_t KVAnnotation::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + bool isset_key = false; + bool isset_value = false; + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->key); + isset_key = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->value); + isset_value = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + if (!isset_key) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_value) + throw TProtocolException(TProtocolException::INVALID_DATA); + return xfer; +} + +uint32_t KVAnnotation::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("KVAnnotation"); + xfer += oprot->writeFieldBegin("key", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->key); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("value", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString(this->value); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* ThriftSpan::ascii_fingerprint = "B08D60902E6EF2A6DF2C5746A48261F4"; +const uint8_t ThriftSpan::binary_fingerprint[16] = {0xB0,0x8D,0x60,0x90,0x2E,0x6E,0xF2,0xA6,0xDF,0x2C,0x57,0x46,0xA4,0x82,0x61,0xF4}; + +uint32_t ThriftSpan::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + bool isset_traceId = false; + bool isset_spanId = false; + bool isset_spanName = false; + bool isset_local = false; + bool isset_remote = false; + bool isset_start = false; + bool isset_duration = false; + bool isset_clientSide = false; + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->traceId); + isset_traceId = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->spanId); + isset_spanId = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->spanName); + isset_spanName = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->local.read(iprot); + isset_local = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 5: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->remote.read(iprot); + isset_remote = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 6: + if (ftype == ::apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->start); + isset_start = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 7: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->duration); + isset_duration = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 8: + if (ftype == ::apache::thrift::protocol::T_BOOL) { + xfer += iprot->readBool(this->clientSide); + isset_clientSide = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 9: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->annotations.clear(); + uint32_t _size0; + ::apache::thrift::protocol::TType _etype3; + iprot->readListBegin(_etype3, _size0); + this->annotations.resize(_size0); + uint32_t _i4; + for (_i4 = 0; _i4 < _size0; ++_i4) + { + xfer += this->annotations[_i4].read(iprot); + } + iprot->readListEnd(); + } + this->__isset.annotations = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 10: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->type); + this->__isset.type = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 11: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->packageSize); + this->__isset.packageSize = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 12: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->infraName); + this->__isset.infraName = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 13: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->infraVersion); + this->__isset.infraVersion = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 14: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->kvAnnotations.clear(); + uint32_t _size5; + ::apache::thrift::protocol::TType _etype8; + iprot->readListBegin(_etype8, _size5); + this->kvAnnotations.resize(_size5); + uint32_t _i9; + for (_i9 = 0; _i9 < _size5; ++_i9) + { + xfer += this->kvAnnotations[_i9].read(iprot); + } + iprot->readListEnd(); + } + this->__isset.kvAnnotations = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 15: + if (ftype == ::apache::thrift::protocol::T_I32) { + int32_t ecast10; + xfer += iprot->readI32(ecast10); + this->status = (StatusCode::type)ecast10; + this->__isset.status = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 16: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->mask); + this->__isset.mask = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + if (!isset_traceId) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_spanId) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_spanName) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_local) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_remote) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_start) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_duration) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_clientSide) + throw TProtocolException(TProtocolException::INVALID_DATA); + return xfer; +} + +uint32_t ThriftSpan::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ThriftSpan"); + xfer += oprot->writeFieldBegin("traceId", ::apache::thrift::protocol::T_I64, 1); + xfer += oprot->writeI64(this->traceId); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("spanId", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString(this->spanId); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("spanName", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString(this->spanName); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("local", ::apache::thrift::protocol::T_STRUCT, 4); + xfer += this->local.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("remote", ::apache::thrift::protocol::T_STRUCT, 5); + xfer += this->remote.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("start", ::apache::thrift::protocol::T_I64, 6); + xfer += oprot->writeI64(this->start); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("duration", ::apache::thrift::protocol::T_I32, 7); + xfer += oprot->writeI32(this->duration); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("clientSide", ::apache::thrift::protocol::T_BOOL, 8); + xfer += oprot->writeBool(this->clientSide); + xfer += oprot->writeFieldEnd(); + if (this->__isset.annotations) { + xfer += oprot->writeFieldBegin("annotations", ::apache::thrift::protocol::T_LIST, 9); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->annotations.size())); + std::vector ::const_iterator _iter11; + for (_iter11 = this->annotations.begin(); _iter11 != this->annotations.end(); ++_iter11) + { + xfer += (*_iter11).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.type) { + xfer += oprot->writeFieldBegin("type", ::apache::thrift::protocol::T_STRING, 10); + xfer += oprot->writeString(this->type); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.packageSize) { + xfer += oprot->writeFieldBegin("packageSize", ::apache::thrift::protocol::T_I32, 11); + xfer += oprot->writeI32(this->packageSize); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.infraName) { + xfer += oprot->writeFieldBegin("infraName", ::apache::thrift::protocol::T_STRING, 12); + xfer += oprot->writeString(this->infraName); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.infraVersion) { + xfer += oprot->writeFieldBegin("infraVersion", ::apache::thrift::protocol::T_STRING, 13); + xfer += oprot->writeString(this->infraVersion); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.kvAnnotations) { + xfer += oprot->writeFieldBegin("kvAnnotations", ::apache::thrift::protocol::T_LIST, 14); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->kvAnnotations.size())); + std::vector ::const_iterator _iter12; + for (_iter12 = this->kvAnnotations.begin(); _iter12 != this->kvAnnotations.end(); ++_iter12) + { + xfer += (*_iter12).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.status) { + xfer += oprot->writeFieldBegin("status", ::apache::thrift::protocol::T_I32, 15); + xfer += oprot->writeI32((int32_t)this->status); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.mask) { + xfer += oprot->writeFieldBegin("mask", ::apache::thrift::protocol::T_I32, 16); + xfer += oprot->writeI32(this->mask); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* ThriftSpanList::ascii_fingerprint = "01BB7DF5DC125F694C08EE3ED02BB420"; +const uint8_t ThriftSpanList::binary_fingerprint[16] = {0x01,0xBB,0x7D,0xF5,0xDC,0x12,0x5F,0x69,0x4C,0x08,0xEE,0x3E,0xD0,0x2B,0xB4,0x20}; + +uint32_t ThriftSpanList::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + bool isset_spans = false; + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->spans.clear(); + uint32_t _size13; + ::apache::thrift::protocol::TType _etype16; + iprot->readListBegin(_etype16, _size13); + this->spans.resize(_size13); + uint32_t _i17; + for (_i17 = 0; _i17 < _size13; ++_i17) + { + xfer += this->spans[_i17].read(iprot); + } + iprot->readListEnd(); + } + isset_spans = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->var1); + this->__isset.var1 = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->var2); + this->__isset.var2 = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + if (!isset_spans) + throw TProtocolException(TProtocolException::INVALID_DATA); + return xfer; +} + +uint32_t ThriftSpanList::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ThriftSpanList"); + xfer += oprot->writeFieldBegin("spans", ::apache::thrift::protocol::T_LIST, 1); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->spans.size())); + std::vector ::const_iterator _iter18; + for (_iter18 = this->spans.begin(); _iter18 != this->spans.end(); ++_iter18) + { + xfer += (*_iter18).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + if (this->__isset.var1) { + xfer += oprot->writeFieldBegin("var1", ::apache::thrift::protocol::T_I32, 2); + xfer += oprot->writeI32(this->var1); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.var2) { + xfer += oprot->writeFieldBegin("var2", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString(this->var2); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + + diff --git a/common/gen-cpp/ThriftSpans_types.h b/common/gen-cpp/ThriftSpans_types.h new file mode 100644 index 0000000..74b7ead --- /dev/null +++ b/common/gen-cpp/ThriftSpans_types.h @@ -0,0 +1,420 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef ThriftSpans_TYPES_H +#define ThriftSpans_TYPES_H + +#include +#include +#include +#include + + + + + +struct StatusCode { + enum type { + SUCCESS = 0, + EXCEPTION = 1, + TIMEOUT = 2, + DROP = 3 + }; +}; + +extern const std::map _StatusCode_VALUES_TO_NAMES; + + +class Endpoint { + public: + + static const char* ascii_fingerprint; // = "C7D2D58463AC91C552EE8B325EA2ACCC"; + static const uint8_t binary_fingerprint[16]; // = {0xC7,0xD2,0xD5,0x84,0x63,0xAC,0x91,0xC5,0x52,0xEE,0x8B,0x32,0x5E,0xA2,0xAC,0xCC}; + + Endpoint() : ip(0), port(0), appKey("") { + } + + virtual ~Endpoint() throw() {} + + int32_t ip; + int16_t port; + std::string appKey; + + void __set_ip(const int32_t val) { + ip = val; + } + + void __set_port(const int16_t val) { + port = val; + } + + void __set_appKey(const std::string& val) { + appKey = val; + } + + bool operator == (const Endpoint & rhs) const + { + if (!(ip == rhs.ip)) + return false; + if (!(port == rhs.port)) + return false; + if (!(appKey == rhs.appKey)) + return false; + return true; + } + bool operator != (const Endpoint &rhs) const { + return !(*this == rhs); + } + + bool operator < (const Endpoint & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _Annotation__isset { + _Annotation__isset() : duration(false) {} + bool duration; +} _Annotation__isset; + +class Annotation { + public: + + static const char* ascii_fingerprint; // = "CE5BE9A8A7BD398538F703F899B08A94"; + static const uint8_t binary_fingerprint[16]; // = {0xCE,0x5B,0xE9,0xA8,0xA7,0xBD,0x39,0x85,0x38,0xF7,0x03,0xF8,0x99,0xB0,0x8A,0x94}; + + Annotation() : value(""), timestamp(0), duration(0) { + } + + virtual ~Annotation() throw() {} + + std::string value; + int64_t timestamp; + int32_t duration; + + _Annotation__isset __isset; + + void __set_value(const std::string& val) { + value = val; + } + + void __set_timestamp(const int64_t val) { + timestamp = val; + } + + void __set_duration(const int32_t val) { + duration = val; + __isset.duration = true; + } + + bool operator == (const Annotation & rhs) const + { + if (!(value == rhs.value)) + return false; + if (!(timestamp == rhs.timestamp)) + return false; + if (__isset.duration != rhs.__isset.duration) + return false; + else if (__isset.duration && !(duration == rhs.duration)) + return false; + return true; + } + bool operator != (const Annotation &rhs) const { + return !(*this == rhs); + } + + bool operator < (const Annotation & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class KVAnnotation { + public: + + static const char* ascii_fingerprint; // = "07A9615F837F7D0A952B595DD3020972"; + static const uint8_t binary_fingerprint[16]; // = {0x07,0xA9,0x61,0x5F,0x83,0x7F,0x7D,0x0A,0x95,0x2B,0x59,0x5D,0xD3,0x02,0x09,0x72}; + + KVAnnotation() : key(""), value("") { + } + + virtual ~KVAnnotation() throw() {} + + std::string key; + std::string value; + + void __set_key(const std::string& val) { + key = val; + } + + void __set_value(const std::string& val) { + value = val; + } + + bool operator == (const KVAnnotation & rhs) const + { + if (!(key == rhs.key)) + return false; + if (!(value == rhs.value)) + return false; + return true; + } + bool operator != (const KVAnnotation &rhs) const { + return !(*this == rhs); + } + + bool operator < (const KVAnnotation & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ThriftSpan__isset { + _ThriftSpan__isset() : annotations(false), type(false), packageSize(false), infraName(false), infraVersion(false), kvAnnotations(false), status(false), mask(false) {} + bool annotations; + bool type; + bool packageSize; + bool infraName; + bool infraVersion; + bool kvAnnotations; + bool status; + bool mask; +} _ThriftSpan__isset; + +class ThriftSpan { + public: + + static const char* ascii_fingerprint; // = "B08D60902E6EF2A6DF2C5746A48261F4"; + static const uint8_t binary_fingerprint[16]; // = {0xB0,0x8D,0x60,0x90,0x2E,0x6E,0xF2,0xA6,0xDF,0x2C,0x57,0x46,0xA4,0x82,0x61,0xF4}; + + ThriftSpan() : traceId(0), spanId(""), spanName(""), start(0), duration(0), clientSide(0), type(""), packageSize(0), infraName(""), infraVersion(""), status((StatusCode::type)0), mask(0) { + } + + virtual ~ThriftSpan() throw() {} + + int64_t traceId; + std::string spanId; + std::string spanName; + Endpoint local; + Endpoint remote; + int64_t start; + int32_t duration; + bool clientSide; + std::vector annotations; + std::string type; + int32_t packageSize; + std::string infraName; + std::string infraVersion; + std::vector kvAnnotations; + StatusCode::type status; + int32_t mask; + + _ThriftSpan__isset __isset; + + void __set_traceId(const int64_t val) { + traceId = val; + } + + void __set_spanId(const std::string& val) { + spanId = val; + } + + void __set_spanName(const std::string& val) { + spanName = val; + } + + void __set_local(const Endpoint& val) { + local = val; + } + + void __set_remote(const Endpoint& val) { + remote = val; + } + + void __set_start(const int64_t val) { + start = val; + } + + void __set_duration(const int32_t val) { + duration = val; + } + + void __set_clientSide(const bool val) { + clientSide = val; + } + + void __set_annotations(const std::vector & val) { + annotations = val; + __isset.annotations = true; + } + + void __set_type(const std::string& val) { + type = val; + __isset.type = true; + } + + void __set_packageSize(const int32_t val) { + packageSize = val; + __isset.packageSize = true; + } + + void __set_infraName(const std::string& val) { + infraName = val; + __isset.infraName = true; + } + + void __set_infraVersion(const std::string& val) { + infraVersion = val; + __isset.infraVersion = true; + } + + void __set_kvAnnotations(const std::vector & val) { + kvAnnotations = val; + __isset.kvAnnotations = true; + } + + void __set_status(const StatusCode::type val) { + status = val; + __isset.status = true; + } + + void __set_mask(const int32_t val) { + mask = val; + __isset.mask = true; + } + + bool operator == (const ThriftSpan & rhs) const + { + if (!(traceId == rhs.traceId)) + return false; + if (!(spanId == rhs.spanId)) + return false; + if (!(spanName == rhs.spanName)) + return false; + if (!(local == rhs.local)) + return false; + if (!(remote == rhs.remote)) + return false; + if (!(start == rhs.start)) + return false; + if (!(duration == rhs.duration)) + return false; + if (!(clientSide == rhs.clientSide)) + return false; + if (__isset.annotations != rhs.__isset.annotations) + return false; + else if (__isset.annotations && !(annotations == rhs.annotations)) + return false; + if (__isset.type != rhs.__isset.type) + return false; + else if (__isset.type && !(type == rhs.type)) + return false; + if (__isset.packageSize != rhs.__isset.packageSize) + return false; + else if (__isset.packageSize && !(packageSize == rhs.packageSize)) + return false; + if (__isset.infraName != rhs.__isset.infraName) + return false; + else if (__isset.infraName && !(infraName == rhs.infraName)) + return false; + if (__isset.infraVersion != rhs.__isset.infraVersion) + return false; + else if (__isset.infraVersion && !(infraVersion == rhs.infraVersion)) + return false; + if (__isset.kvAnnotations != rhs.__isset.kvAnnotations) + return false; + else if (__isset.kvAnnotations && !(kvAnnotations == rhs.kvAnnotations)) + return false; + if (__isset.status != rhs.__isset.status) + return false; + else if (__isset.status && !(status == rhs.status)) + return false; + if (__isset.mask != rhs.__isset.mask) + return false; + else if (__isset.mask && !(mask == rhs.mask)) + return false; + return true; + } + bool operator != (const ThriftSpan &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ThriftSpan & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ThriftSpanList__isset { + _ThriftSpanList__isset() : var1(false), var2(false) {} + bool var1; + bool var2; +} _ThriftSpanList__isset; + +class ThriftSpanList { + public: + + static const char* ascii_fingerprint; // = "01BB7DF5DC125F694C08EE3ED02BB420"; + static const uint8_t binary_fingerprint[16]; // = {0x01,0xBB,0x7D,0xF5,0xDC,0x12,0x5F,0x69,0x4C,0x08,0xEE,0x3E,0xD0,0x2B,0xB4,0x20}; + + ThriftSpanList() : var1(0), var2("") { + } + + virtual ~ThriftSpanList() throw() {} + + std::vector spans; + int32_t var1; + std::string var2; + + _ThriftSpanList__isset __isset; + + void __set_spans(const std::vector & val) { + spans = val; + } + + void __set_var1(const int32_t val) { + var1 = val; + __isset.var1 = true; + } + + void __set_var2(const std::string& val) { + var2 = val; + __isset.var2 = true; + } + + bool operator == (const ThriftSpanList & rhs) const + { + if (!(spans == rhs.spans)) + return false; + if (__isset.var1 != rhs.__isset.var1) + return false; + else if (__isset.var1 && !(var1 == rhs.var1)) + return false; + if (__isset.var2 != rhs.__isset.var2) + return false; + else if (__isset.var2 && !(var2 == rhs.var2)) + return false; + return true; + } + bool operator != (const ThriftSpanList &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ThriftSpanList & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + + +#endif diff --git a/common/gen-cpp/mnsc_data_constants.cpp b/common/gen-cpp/mnsc_data_constants.cpp new file mode 100644 index 0000000..41cc863 --- /dev/null +++ b/common/gen-cpp/mnsc_data_constants.cpp @@ -0,0 +1,35 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "mnsc_data_constants.h" + +namespace meituan_mns { + +const mnsc_dataConstants g_mnsc_data_constants; + +mnsc_dataConstants::mnsc_dataConstants() { + PROD = "prod"; + + STAGE = "stage"; + + TEST = "test"; + + SUCCESS = 200; + + MNSCache_UPDATE = 500; + + TIMEOUT_ERROR = 400; + + ILLEGAL_ARGUMENT = 400; + + NOT_FOUND = 404; + + NOT_MODIFIED = 304; + +} + +} // namespace + diff --git a/common/gen-cpp/mnsc_data_constants.h b/common/gen-cpp/mnsc_data_constants.h new file mode 100644 index 0000000..77fc7ab --- /dev/null +++ b/common/gen-cpp/mnsc_data_constants.h @@ -0,0 +1,33 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef mnsc_data_CONSTANTS_H +#define mnsc_data_CONSTANTS_H + +#include "mnsc_data_types.h" + +namespace meituan_mns { + +class mnsc_dataConstants { + public: + mnsc_dataConstants(); + + std::string PROD; + std::string STAGE; + std::string TEST; + int32_t SUCCESS; + int32_t MNSCache_UPDATE; + int32_t TIMEOUT_ERROR; + int32_t ILLEGAL_ARGUMENT; + int32_t NOT_FOUND; + int32_t NOT_MODIFIED; +}; + +extern const mnsc_dataConstants g_mnsc_data_constants; + +} // namespace + +#endif diff --git a/common/gen-cpp/mnsc_data_types.cpp b/common/gen-cpp/mnsc_data_types.cpp new file mode 100644 index 0000000..d82ac98 --- /dev/null +++ b/common/gen-cpp/mnsc_data_types.cpp @@ -0,0 +1,430 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "mnsc_data_types.h" + +namespace meituan_mns { + +int _kProtocolsValues[] = { + Protocols::THRIFT, + Protocols::HTTP +}; +const char* _kProtocolsNames[] = { + "THRIFT", + "HTTP" +}; +const std::map _Protocols_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(2, _kProtocolsValues, _kProtocolsNames), ::apache::thrift::TEnumIterator(-1, NULL, NULL)); + +const char* MNSResponse::ascii_fingerprint = "262B7A6EE88301D8EA2B9CBECB4AF401"; +const uint8_t MNSResponse::binary_fingerprint[16] = {0x26,0x2B,0x7A,0x6E,0xE8,0x83,0x01,0xD8,0xEA,0x2B,0x9C,0xBE,0xCB,0x4A,0xF4,0x01}; + +uint32_t MNSResponse::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + bool isset_code = false; + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->code); + isset_code = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->defaultMNSCache.clear(); + uint32_t _size0; + ::apache::thrift::protocol::TType _etype3; + iprot->readListBegin(_etype3, _size0); + this->defaultMNSCache.resize(_size0); + uint32_t _i4; + for (_i4 = 0; _i4 < _size0; ++_i4) + { + xfer += this->defaultMNSCache[_i4].read(iprot); + } + iprot->readListEnd(); + } + this->__isset.defaultMNSCache = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->version); + this->__isset.version = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + if (!isset_code) + throw TProtocolException(TProtocolException::INVALID_DATA); + return xfer; +} + +uint32_t MNSResponse::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("MNSResponse"); + xfer += oprot->writeFieldBegin("code", ::apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32(this->code); + xfer += oprot->writeFieldEnd(); + if (this->__isset.defaultMNSCache) { + xfer += oprot->writeFieldBegin("defaultMNSCache", ::apache::thrift::protocol::T_LIST, 2); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->defaultMNSCache.size())); + std::vector ::const_iterator _iter5; + for (_iter5 = this->defaultMNSCache.begin(); _iter5 != this->defaultMNSCache.end(); ++_iter5) + { + xfer += (*_iter5).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.version) { + xfer += oprot->writeFieldBegin("version", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString(this->version); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* MNSBatchResponse::ascii_fingerprint = "C0A3C40A83F3EC7069EF8B80B7669355"; +const uint8_t MNSBatchResponse::binary_fingerprint[16] = {0xC0,0xA3,0xC4,0x0A,0x83,0xF3,0xEC,0x70,0x69,0xEF,0x8B,0x80,0xB7,0x66,0x93,0x55}; + +uint32_t MNSBatchResponse::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + bool isset_code = false; + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->code); + isset_code = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_MAP) { + { + this->cache.clear(); + uint32_t _size6; + ::apache::thrift::protocol::TType _ktype7; + ::apache::thrift::protocol::TType _vtype8; + iprot->readMapBegin(_ktype7, _vtype8, _size6); + uint32_t _i10; + for (_i10 = 0; _i10 < _size6; ++_i10) + { + std::string _key11; + xfer += iprot->readString(_key11); + std::map > & _val12 = this->cache[_key11]; + { + _val12.clear(); + uint32_t _size13; + ::apache::thrift::protocol::TType _ktype14; + ::apache::thrift::protocol::TType _vtype15; + iprot->readMapBegin(_ktype14, _vtype15, _size13); + uint32_t _i17; + for (_i17 = 0; _i17 < _size13; ++_i17) + { + std::string _key18; + xfer += iprot->readString(_key18); + std::vector & _val19 = _val12[_key18]; + { + _val19.clear(); + uint32_t _size20; + ::apache::thrift::protocol::TType _etype23; + iprot->readListBegin(_etype23, _size20); + _val19.resize(_size20); + uint32_t _i24; + for (_i24 = 0; _i24 < _size20; ++_i24) + { + xfer += _val19[_i24].read(iprot); + } + iprot->readListEnd(); + } + } + iprot->readMapEnd(); + } + } + iprot->readMapEnd(); + } + this->__isset.cache = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + if (!isset_code) + throw TProtocolException(TProtocolException::INVALID_DATA); + return xfer; +} + +uint32_t MNSBatchResponse::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("MNSBatchResponse"); + xfer += oprot->writeFieldBegin("code", ::apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32(this->code); + xfer += oprot->writeFieldEnd(); + if (this->__isset.cache) { + xfer += oprot->writeFieldBegin("cache", ::apache::thrift::protocol::T_MAP, 2); + { + xfer += oprot->writeMapBegin(::apache::thrift::protocol::T_STRING, ::apache::thrift::protocol::T_MAP, static_cast(this->cache.size())); + std::map > > ::const_iterator _iter25; + for (_iter25 = this->cache.begin(); _iter25 != this->cache.end(); ++_iter25) + { + xfer += oprot->writeString(_iter25->first); + { + xfer += oprot->writeMapBegin(::apache::thrift::protocol::T_STRING, ::apache::thrift::protocol::T_LIST, static_cast(_iter25->second.size())); + std::map > ::const_iterator _iter26; + for (_iter26 = _iter25->second.begin(); _iter26 != _iter25->second.end(); ++_iter26) + { + xfer += oprot->writeString(_iter26->first); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(_iter26->second.size())); + std::vector ::const_iterator _iter27; + for (_iter27 = _iter26->second.begin(); _iter27 != _iter26->second.end(); ++_iter27) + { + xfer += (*_iter27).write(oprot); + } + xfer += oprot->writeListEnd(); + } + } + xfer += oprot->writeMapEnd(); + } + } + xfer += oprot->writeMapEnd(); + } + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* AppKeyListResponse::ascii_fingerprint = "93CC3D1E71866966C22792AABF4C3815"; +const uint8_t AppKeyListResponse::binary_fingerprint[16] = {0x93,0xCC,0x3D,0x1E,0x71,0x86,0x69,0x66,0xC2,0x27,0x92,0xAA,0xBF,0x4C,0x38,0x15}; + +uint32_t AppKeyListResponse::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + bool isset_code = false; + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->code); + isset_code = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->appKeyList.clear(); + uint32_t _size28; + ::apache::thrift::protocol::TType _etype31; + iprot->readListBegin(_etype31, _size28); + this->appKeyList.resize(_size28); + uint32_t _i32; + for (_i32 = 0; _i32 < _size28; ++_i32) + { + xfer += iprot->readString(this->appKeyList[_i32]); + } + iprot->readListEnd(); + } + this->__isset.appKeyList = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + if (!isset_code) + throw TProtocolException(TProtocolException::INVALID_DATA); + return xfer; +} + +uint32_t AppKeyListResponse::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("AppKeyListResponse"); + xfer += oprot->writeFieldBegin("code", ::apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32(this->code); + xfer += oprot->writeFieldEnd(); + if (this->__isset.appKeyList) { + xfer += oprot->writeFieldBegin("appKeyList", ::apache::thrift::protocol::T_LIST, 2); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast(this->appKeyList.size())); + std::vector ::const_iterator _iter33; + for (_iter33 = this->appKeyList.begin(); _iter33 != this->appKeyList.end(); ++_iter33) + { + xfer += oprot->writeString((*_iter33)); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* MnsRequest::ascii_fingerprint = "38C252E94E93B69D04EB3A6EE2F9EDFB"; +const uint8_t MnsRequest::binary_fingerprint[16] = {0x38,0xC2,0x52,0xE9,0x4E,0x93,0xB6,0x9D,0x04,0xEB,0x3A,0x6E,0xE2,0xF9,0xED,0xFB}; + +uint32_t MnsRequest::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_I32) { + int32_t ecast34; + xfer += iprot->readI32(ecast34); + this->protoctol = (Protocols::type)ecast34; + this->__isset.protoctol = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->appkey); + this->__isset.appkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->env); + this->__isset.env = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t MnsRequest::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("MnsRequest"); + xfer += oprot->writeFieldBegin("protoctol", ::apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32((int32_t)this->protoctol); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("appkey", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString(this->appkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("env", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString(this->env); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +} // namespace diff --git a/common/gen-cpp/mnsc_data_types.h b/common/gen-cpp/mnsc_data_types.h new file mode 100644 index 0000000..5835c20 --- /dev/null +++ b/common/gen-cpp/mnsc_data_types.h @@ -0,0 +1,254 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef mnsc_data_TYPES_H +#define mnsc_data_TYPES_H + +#include +#include +#include +#include + +#include "naming_common_types.h" + + +namespace meituan_mns { + +struct Protocols { + enum type { + THRIFT = 0, + HTTP = 1 + }; +}; + +extern const std::map _Protocols_VALUES_TO_NAMES; + +typedef class ::meituan_mns::SGService SGService; + +typedef struct _MNSResponse__isset { + _MNSResponse__isset() : defaultMNSCache(false), version(false) {} + bool defaultMNSCache; + bool version; +} _MNSResponse__isset; + +class MNSResponse { + public: + + static const char* ascii_fingerprint; // = "262B7A6EE88301D8EA2B9CBECB4AF401"; + static const uint8_t binary_fingerprint[16]; // = {0x26,0x2B,0x7A,0x6E,0xE8,0x83,0x01,0xD8,0xEA,0x2B,0x9C,0xBE,0xCB,0x4A,0xF4,0x01}; + + MNSResponse() : code(200), version("") { + } + + virtual ~MNSResponse() throw() {} + + int32_t code; + std::vector defaultMNSCache; + std::string version; + + _MNSResponse__isset __isset; + + void __set_code(const int32_t val) { + code = val; + } + + void __set_defaultMNSCache(const std::vector & val) { + defaultMNSCache = val; + __isset.defaultMNSCache = true; + } + + void __set_version(const std::string& val) { + version = val; + __isset.version = true; + } + + bool operator == (const MNSResponse & rhs) const + { + if (!(code == rhs.code)) + return false; + if (__isset.defaultMNSCache != rhs.__isset.defaultMNSCache) + return false; + else if (__isset.defaultMNSCache && !(defaultMNSCache == rhs.defaultMNSCache)) + return false; + if (__isset.version != rhs.__isset.version) + return false; + else if (__isset.version && !(version == rhs.version)) + return false; + return true; + } + bool operator != (const MNSResponse &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSResponse & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSBatchResponse__isset { + _MNSBatchResponse__isset() : cache(false) {} + bool cache; +} _MNSBatchResponse__isset; + +class MNSBatchResponse { + public: + + static const char* ascii_fingerprint; // = "C0A3C40A83F3EC7069EF8B80B7669355"; + static const uint8_t binary_fingerprint[16]; // = {0xC0,0xA3,0xC4,0x0A,0x83,0xF3,0xEC,0x70,0x69,0xEF,0x8B,0x80,0xB7,0x66,0x93,0x55}; + + MNSBatchResponse() : code(200) { + } + + virtual ~MNSBatchResponse() throw() {} + + int32_t code; + std::map > > cache; + + _MNSBatchResponse__isset __isset; + + void __set_code(const int32_t val) { + code = val; + } + + void __set_cache(const std::map > > & val) { + cache = val; + __isset.cache = true; + } + + bool operator == (const MNSBatchResponse & rhs) const + { + if (!(code == rhs.code)) + return false; + if (__isset.cache != rhs.__isset.cache) + return false; + else if (__isset.cache && !(cache == rhs.cache)) + return false; + return true; + } + bool operator != (const MNSBatchResponse &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSBatchResponse & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _AppKeyListResponse__isset { + _AppKeyListResponse__isset() : appKeyList(false) {} + bool appKeyList; +} _AppKeyListResponse__isset; + +class AppKeyListResponse { + public: + + static const char* ascii_fingerprint; // = "93CC3D1E71866966C22792AABF4C3815"; + static const uint8_t binary_fingerprint[16]; // = {0x93,0xCC,0x3D,0x1E,0x71,0x86,0x69,0x66,0xC2,0x27,0x92,0xAA,0xBF,0x4C,0x38,0x15}; + + AppKeyListResponse() : code(200) { + } + + virtual ~AppKeyListResponse() throw() {} + + int32_t code; + std::vector appKeyList; + + _AppKeyListResponse__isset __isset; + + void __set_code(const int32_t val) { + code = val; + } + + void __set_appKeyList(const std::vector & val) { + appKeyList = val; + __isset.appKeyList = true; + } + + bool operator == (const AppKeyListResponse & rhs) const + { + if (!(code == rhs.code)) + return false; + if (__isset.appKeyList != rhs.__isset.appKeyList) + return false; + else if (__isset.appKeyList && !(appKeyList == rhs.appKeyList)) + return false; + return true; + } + bool operator != (const AppKeyListResponse &rhs) const { + return !(*this == rhs); + } + + bool operator < (const AppKeyListResponse & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MnsRequest__isset { + _MnsRequest__isset() : protoctol(false), appkey(false), env(false) {} + bool protoctol; + bool appkey; + bool env; +} _MnsRequest__isset; + +class MnsRequest { + public: + + static const char* ascii_fingerprint; // = "38C252E94E93B69D04EB3A6EE2F9EDFB"; + static const uint8_t binary_fingerprint[16]; // = {0x38,0xC2,0x52,0xE9,0x4E,0x93,0xB6,0x9D,0x04,0xEB,0x3A,0x6E,0xE2,0xF9,0xED,0xFB}; + + MnsRequest() : protoctol((Protocols::type)0), appkey(""), env("") { + } + + virtual ~MnsRequest() throw() {} + + Protocols::type protoctol; + std::string appkey; + std::string env; + + _MnsRequest__isset __isset; + + void __set_protoctol(const Protocols::type val) { + protoctol = val; + } + + void __set_appkey(const std::string& val) { + appkey = val; + } + + void __set_env(const std::string& val) { + env = val; + } + + bool operator == (const MnsRequest & rhs) const + { + if (!(protoctol == rhs.protoctol)) + return false; + if (!(appkey == rhs.appkey)) + return false; + if (!(env == rhs.env)) + return false; + return true; + } + bool operator != (const MnsRequest &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MnsRequest & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +} // namespace + +#endif diff --git a/common/gen-cpp/mnsc_service_constants.cpp b/common/gen-cpp/mnsc_service_constants.cpp new file mode 100644 index 0000000..5db972d --- /dev/null +++ b/common/gen-cpp/mnsc_service_constants.cpp @@ -0,0 +1,17 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "mnsc_service_constants.h" + +namespace meituan_mns { + +const mnsc_serviceConstants g_mnsc_service_constants; + +mnsc_serviceConstants::mnsc_serviceConstants() { +} + +} // namespace + diff --git a/common/gen-cpp/mnsc_service_constants.h b/common/gen-cpp/mnsc_service_constants.h new file mode 100644 index 0000000..7c99008 --- /dev/null +++ b/common/gen-cpp/mnsc_service_constants.h @@ -0,0 +1,24 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef mnsc_service_CONSTANTS_H +#define mnsc_service_CONSTANTS_H + +#include "mnsc_service_types.h" + +namespace meituan_mns { + +class mnsc_serviceConstants { + public: + mnsc_serviceConstants(); + +}; + +extern const mnsc_serviceConstants g_mnsc_service_constants; + +} // namespace + +#endif diff --git a/common/gen-cpp/mnsc_service_types.cpp b/common/gen-cpp/mnsc_service_types.cpp new file mode 100644 index 0000000..bd77e33 --- /dev/null +++ b/common/gen-cpp/mnsc_service_types.cpp @@ -0,0 +1,11 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "mnsc_service_types.h" + +namespace meituan_mns { + +} // namespace diff --git a/common/gen-cpp/mnsc_service_types.h b/common/gen-cpp/mnsc_service_types.h new file mode 100644 index 0000000..6a0bbd0 --- /dev/null +++ b/common/gen-cpp/mnsc_service_types.h @@ -0,0 +1,32 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef mnsc_service_TYPES_H +#define mnsc_service_TYPES_H + +#include +#include +#include +#include + +#include "mnsc_data_types.h" + + +namespace meituan_mns { + +typedef class ::meituan_mns::MNSResponse MNSResponse; + +typedef class ::meituan_mns::MNSBatchResponse MNSBatchResponse; + +typedef class ::meituan_mns::AppKeyListResponse AppKeyListResponse; + +typedef class ::meituan_mns::MnsRequest MnsRequest; + +typedef ::meituan_mns::SGService SGService; + +} // namespace + +#endif diff --git a/common/gen-cpp/naming_common_constants.cpp b/common/gen-cpp/naming_common_constants.cpp new file mode 100644 index 0000000..e35a4b4 --- /dev/null +++ b/common/gen-cpp/naming_common_constants.cpp @@ -0,0 +1,17 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "naming_common_constants.h" + +namespace meituan_mns { + +const naming_commonConstants g_naming_common_constants; + +naming_commonConstants::naming_commonConstants() { +} + +} // namespace + diff --git a/common/gen-cpp/naming_common_constants.h b/common/gen-cpp/naming_common_constants.h new file mode 100644 index 0000000..abc434b --- /dev/null +++ b/common/gen-cpp/naming_common_constants.h @@ -0,0 +1,24 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef naming_common_CONSTANTS_H +#define naming_common_CONSTANTS_H + +#include "naming_common_types.h" + +namespace meituan_mns { + +class naming_commonConstants { + public: + naming_commonConstants(); + +}; + +extern const naming_commonConstants g_naming_common_constants; + +} // namespace + +#endif diff --git a/common/gen-cpp/naming_common_types.cpp b/common/gen-cpp/naming_common_types.cpp new file mode 100644 index 0000000..439598e --- /dev/null +++ b/common/gen-cpp/naming_common_types.cpp @@ -0,0 +1,1106 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "naming_common_types.h" + +namespace meituan_mns { + +int _kUptCmdValues[] = { + UptCmd::RESET, + UptCmd::ADD, + UptCmd::DELETE +}; +const char* _kUptCmdNames[] = { + "RESET", + "ADD", + "DELETE" +}; +const std::map _UptCmd_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(3, _kUptCmdValues, _kUptCmdNames), ::apache::thrift::TEnumIterator(-1, NULL, NULL)); + +int _kfb_statusValues[] = { + fb_status::DEAD, + fb_status::STARTING, + fb_status::ALIVE, + fb_status::STOPPING, + fb_status::STOPPED, + fb_status::WARNING +}; +const char* _kfb_statusNames[] = { + "DEAD", + "STARTING", + "ALIVE", + "STOPPING", + "STOPPED", + "WARNING" +}; +const std::map _fb_status_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(6, _kfb_statusValues, _kfb_statusNames), ::apache::thrift::TEnumIterator(-1, NULL, NULL)); + +int _kHeartbeatSupportTypeValues[] = { + HeartbeatSupportType::NoSupport, + HeartbeatSupportType::P2POnly, + HeartbeatSupportType::ScannerOnly, + HeartbeatSupportType::BothSupport +}; +const char* _kHeartbeatSupportTypeNames[] = { + "NoSupport", + "P2POnly", + "ScannerOnly", + "BothSupport" +}; +const std::map _HeartbeatSupportType_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(4, _kHeartbeatSupportTypeValues, _kHeartbeatSupportTypeNames), ::apache::thrift::TEnumIterator(-1, NULL, NULL)); + +const char* ServiceDetail::ascii_fingerprint = "5892306F7B861249AE8E27C8ED619593"; +const uint8_t ServiceDetail::binary_fingerprint[16] = {0x58,0x92,0x30,0x6F,0x7B,0x86,0x12,0x49,0xAE,0x8E,0x27,0xC8,0xED,0x61,0x95,0x93}; + +uint32_t ServiceDetail::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_BOOL) { + xfer += iprot->readBool(this->unifiedProto); + this->__isset.unifiedProto = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ServiceDetail::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ServiceDetail"); + xfer += oprot->writeFieldBegin("unifiedProto", ::apache::thrift::protocol::T_BOOL, 1); + xfer += oprot->writeBool(this->unifiedProto); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* SGService::ascii_fingerprint = "BE473A6FD5DE924200DDD8D539C779C1"; +const uint8_t SGService::binary_fingerprint[16] = {0xBE,0x47,0x3A,0x6F,0xD5,0xDE,0x92,0x42,0x00,0xDD,0xD8,0xD5,0x39,0xC7,0x79,0xC1}; + +uint32_t SGService::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->appkey); + this->__isset.appkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->version); + this->__isset.version = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->ip); + this->__isset.ip = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->port); + this->__isset.port = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 5: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->weight); + this->__isset.weight = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 6: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->status); + this->__isset.status = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 7: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->role); + this->__isset.role = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 8: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->envir); + this->__isset.envir = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 9: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->lastUpdateTime); + this->__isset.lastUpdateTime = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 10: + if (ftype == ::apache::thrift::protocol::T_DOUBLE) { + xfer += iprot->readDouble(this->fweight); + this->__isset.fweight = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 11: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->serverType); + this->__isset.serverType = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 12: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->protocol); + this->__isset.protocol = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 13: + if (ftype == ::apache::thrift::protocol::T_MAP) { + { + this->serviceInfo.clear(); + uint32_t _size0; + ::apache::thrift::protocol::TType _ktype1; + ::apache::thrift::protocol::TType _vtype2; + iprot->readMapBegin(_ktype1, _vtype2, _size0); + uint32_t _i4; + for (_i4 = 0; _i4 < _size0; ++_i4) + { + std::string _key5; + xfer += iprot->readString(_key5); + ServiceDetail& _val6 = this->serviceInfo[_key5]; + xfer += _val6.read(iprot); + } + iprot->readMapEnd(); + } + this->__isset.serviceInfo = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 14: + if (ftype == ::apache::thrift::protocol::T_BYTE) { + xfer += iprot->readByte(this->heartbeatSupport); + this->__isset.heartbeatSupport = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 15: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->warmup); + this->__isset.warmup = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t SGService::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("SGService"); + xfer += oprot->writeFieldBegin("appkey", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->appkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("version", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString(this->version); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("ip", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString(this->ip); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("port", ::apache::thrift::protocol::T_I32, 4); + xfer += oprot->writeI32(this->port); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("weight", ::apache::thrift::protocol::T_I32, 5); + xfer += oprot->writeI32(this->weight); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("status", ::apache::thrift::protocol::T_I32, 6); + xfer += oprot->writeI32(this->status); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("role", ::apache::thrift::protocol::T_I32, 7); + xfer += oprot->writeI32(this->role); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("envir", ::apache::thrift::protocol::T_I32, 8); + xfer += oprot->writeI32(this->envir); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("lastUpdateTime", ::apache::thrift::protocol::T_I32, 9); + xfer += oprot->writeI32(this->lastUpdateTime); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("fweight", ::apache::thrift::protocol::T_DOUBLE, 10); + xfer += oprot->writeDouble(this->fweight); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("serverType", ::apache::thrift::protocol::T_I32, 11); + xfer += oprot->writeI32(this->serverType); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("protocol", ::apache::thrift::protocol::T_STRING, 12); + xfer += oprot->writeString(this->protocol); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("serviceInfo", ::apache::thrift::protocol::T_MAP, 13); + { + xfer += oprot->writeMapBegin(::apache::thrift::protocol::T_STRING, ::apache::thrift::protocol::T_STRUCT, static_cast(this->serviceInfo.size())); + std::map ::const_iterator _iter7; + for (_iter7 = this->serviceInfo.begin(); _iter7 != this->serviceInfo.end(); ++_iter7) + { + xfer += oprot->writeString(_iter7->first); + xfer += _iter7->second.write(oprot); + } + xfer += oprot->writeMapEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("heartbeatSupport", ::apache::thrift::protocol::T_BYTE, 14); + xfer += oprot->writeByte(this->heartbeatSupport); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("warmup", ::apache::thrift::protocol::T_I32, 15); + xfer += oprot->writeI32(this->warmup); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* ServiceNode::ascii_fingerprint = "E6EB76A1BCBAF7124A43817D5BC322F7"; +const uint8_t ServiceNode::binary_fingerprint[16] = {0xE6,0xEB,0x76,0xA1,0xBC,0xBA,0xF7,0x12,0x4A,0x43,0x81,0x7D,0x5B,0xC3,0x22,0xF7}; + +uint32_t ServiceNode::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->serviceName); + this->__isset.serviceName = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_SET) { + { + this->appkeys.clear(); + uint32_t _size8; + ::apache::thrift::protocol::TType _etype11; + iprot->readSetBegin(_etype11, _size8); + uint32_t _i12; + for (_i12 = 0; _i12 < _size8; ++_i12) + { + std::string _elem13; + xfer += iprot->readString(_elem13); + this->appkeys.insert(_elem13); + } + iprot->readSetEnd(); + } + this->__isset.appkeys = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->lastUpdateTime); + this->__isset.lastUpdateTime = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ServiceNode::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ServiceNode"); + xfer += oprot->writeFieldBegin("serviceName", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->serviceName); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("appkeys", ::apache::thrift::protocol::T_SET, 2); + { + xfer += oprot->writeSetBegin(::apache::thrift::protocol::T_STRING, static_cast(this->appkeys.size())); + std::set ::const_iterator _iter14; + for (_iter14 = this->appkeys.begin(); _iter14 != this->appkeys.end(); ++_iter14) + { + xfer += oprot->writeString((*_iter14)); + } + xfer += oprot->writeSetEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("lastUpdateTime", ::apache::thrift::protocol::T_I32, 3); + xfer += oprot->writeI32(this->lastUpdateTime); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* Consumer::ascii_fingerprint = "AA819045335EAFAB5C2FE456B4B9CC1C"; +const uint8_t Consumer::binary_fingerprint[16] = {0xAA,0x81,0x90,0x45,0x33,0x5E,0xAF,0xAB,0x5C,0x2F,0xE4,0x56,0xB4,0xB9,0xCC,0x1C}; + +uint32_t Consumer::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->ips.clear(); + uint32_t _size15; + ::apache::thrift::protocol::TType _etype18; + iprot->readListBegin(_etype18, _size15); + this->ips.resize(_size15); + uint32_t _i19; + for (_i19 = 0; _i19 < _size15; ++_i19) + { + xfer += iprot->readString(this->ips[_i19]); + } + iprot->readListEnd(); + } + this->__isset.ips = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->appkeys.clear(); + uint32_t _size20; + ::apache::thrift::protocol::TType _etype23; + iprot->readListBegin(_etype23, _size20); + this->appkeys.resize(_size20); + uint32_t _i24; + for (_i24 = 0; _i24 < _size20; ++_i24) + { + xfer += iprot->readString(this->appkeys[_i24]); + } + iprot->readListEnd(); + } + this->__isset.appkeys = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t Consumer::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("Consumer"); + xfer += oprot->writeFieldBegin("ips", ::apache::thrift::protocol::T_LIST, 1); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast(this->ips.size())); + std::vector ::const_iterator _iter25; + for (_iter25 = this->ips.begin(); _iter25 != this->ips.end(); ++_iter25) + { + xfer += oprot->writeString((*_iter25)); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("appkeys", ::apache::thrift::protocol::T_LIST, 2); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast(this->appkeys.size())); + std::vector ::const_iterator _iter26; + for (_iter26 = this->appkeys.begin(); _iter26 != this->appkeys.end(); ++_iter26) + { + xfer += oprot->writeString((*_iter26)); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* CRouteData::ascii_fingerprint = "BA097AEDC13A13D0EF25D33F4578FC59"; +const uint8_t CRouteData::binary_fingerprint[16] = {0xBA,0x09,0x7A,0xED,0xC1,0x3A,0x13,0xD0,0xEF,0x25,0xD3,0x3F,0x45,0x78,0xFC,0x59}; + +uint32_t CRouteData::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->id); + this->__isset.id = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->name); + this->__isset.name = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->appkey); + this->__isset.appkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->env); + this->__isset.env = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 5: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->category); + this->__isset.category = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 6: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->priority); + this->__isset.priority = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 7: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->status); + this->__isset.status = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 8: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->consumer.read(iprot); + this->__isset.consumer = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 9: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->provider.clear(); + uint32_t _size27; + ::apache::thrift::protocol::TType _etype30; + iprot->readListBegin(_etype30, _size27); + this->provider.resize(_size27); + uint32_t _i31; + for (_i31 = 0; _i31 < _size27; ++_i31) + { + xfer += iprot->readString(this->provider[_i31]); + } + iprot->readListEnd(); + } + this->__isset.provider = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 10: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->updateTime); + this->__isset.updateTime = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 11: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->createTime); + this->__isset.createTime = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 12: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->reserved); + this->__isset.reserved = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t CRouteData::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("CRouteData"); + xfer += oprot->writeFieldBegin("id", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->id); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("name", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString(this->name); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("appkey", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString(this->appkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("env", ::apache::thrift::protocol::T_I32, 4); + xfer += oprot->writeI32(this->env); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("category", ::apache::thrift::protocol::T_I32, 5); + xfer += oprot->writeI32(this->category); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("priority", ::apache::thrift::protocol::T_I32, 6); + xfer += oprot->writeI32(this->priority); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("status", ::apache::thrift::protocol::T_I32, 7); + xfer += oprot->writeI32(this->status); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("consumer", ::apache::thrift::protocol::T_STRUCT, 8); + xfer += this->consumer.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("provider", ::apache::thrift::protocol::T_LIST, 9); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast(this->provider.size())); + std::vector ::const_iterator _iter32; + for (_iter32 = this->provider.begin(); _iter32 != this->provider.end(); ++_iter32) + { + xfer += oprot->writeString((*_iter32)); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("updateTime", ::apache::thrift::protocol::T_I32, 10); + xfer += oprot->writeI32(this->updateTime); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("createTime", ::apache::thrift::protocol::T_I32, 11); + xfer += oprot->writeI32(this->createTime); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("reserved", ::apache::thrift::protocol::T_STRING, 12); + xfer += oprot->writeString(this->reserved); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* CProviderNode::ascii_fingerprint = "9118FDD77343DD231D97C424A53D2DCF"; +const uint8_t CProviderNode::binary_fingerprint[16] = {0x91,0x18,0xFD,0xD7,0x73,0x43,0xDD,0x23,0x1D,0x97,0xC4,0x24,0xA5,0x3D,0x2D,0xCF}; + +uint32_t CProviderNode::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->appkey); + this->__isset.appkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->lastModifiedTime); + this->__isset.lastModifiedTime = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->mtime); + this->__isset.mtime = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->cversion); + this->__isset.cversion = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 5: + if (ftype == ::apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->version); + this->__isset.version = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t CProviderNode::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("CProviderNode"); + xfer += oprot->writeFieldBegin("appkey", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->appkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("lastModifiedTime", ::apache::thrift::protocol::T_I64, 2); + xfer += oprot->writeI64(this->lastModifiedTime); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("mtime", ::apache::thrift::protocol::T_I64, 3); + xfer += oprot->writeI64(this->mtime); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("cversion", ::apache::thrift::protocol::T_I64, 4); + xfer += oprot->writeI64(this->cversion); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("version", ::apache::thrift::protocol::T_I64, 5); + xfer += oprot->writeI64(this->version); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* CRouteNode::ascii_fingerprint = "9118FDD77343DD231D97C424A53D2DCF"; +const uint8_t CRouteNode::binary_fingerprint[16] = {0x91,0x18,0xFD,0xD7,0x73,0x43,0xDD,0x23,0x1D,0x97,0xC4,0x24,0xA5,0x3D,0x2D,0xCF}; + +uint32_t CRouteNode::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->appkey); + this->__isset.appkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->lastModifiedTime); + this->__isset.lastModifiedTime = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->mtime); + this->__isset.mtime = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->cversion); + this->__isset.cversion = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 5: + if (ftype == ::apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->version); + this->__isset.version = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t CRouteNode::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("CRouteNode"); + xfer += oprot->writeFieldBegin("appkey", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->appkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("lastModifiedTime", ::apache::thrift::protocol::T_I64, 2); + xfer += oprot->writeI64(this->lastModifiedTime); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("mtime", ::apache::thrift::protocol::T_I64, 3); + xfer += oprot->writeI64(this->mtime); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("cversion", ::apache::thrift::protocol::T_I64, 4); + xfer += oprot->writeI64(this->cversion); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("version", ::apache::thrift::protocol::T_I64, 5); + xfer += oprot->writeI64(this->version); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* ProtocolRequest::ascii_fingerprint = "C93D890311F28844166CF6E571EB3AC2"; +const uint8_t ProtocolRequest::binary_fingerprint[16] = {0xC9,0x3D,0x89,0x03,0x11,0xF2,0x88,0x44,0x16,0x6C,0xF6,0xE5,0x71,0xEB,0x3A,0xC2}; + +uint32_t ProtocolRequest::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->localAppkey); + this->__isset.localAppkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->remoteAppkey); + this->__isset.remoteAppkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->protocol); + this->__isset.protocol = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->serviceName); + this->__isset.serviceName = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ProtocolRequest::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ProtocolRequest"); + xfer += oprot->writeFieldBegin("localAppkey", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->localAppkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("remoteAppkey", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString(this->remoteAppkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("protocol", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString(this->protocol); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("serviceName", ::apache::thrift::protocol::T_STRING, 4); + xfer += oprot->writeString(this->serviceName); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* ProtocolResponse::ascii_fingerprint = "F56E7FEC73C75A28B4691E35627DB92D"; +const uint8_t ProtocolResponse::binary_fingerprint[16] = {0xF5,0x6E,0x7F,0xEC,0x73,0xC7,0x5A,0x28,0xB4,0x69,0x1E,0x35,0x62,0x7D,0xB9,0x2D}; + +uint32_t ProtocolResponse::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->errcode); + this->__isset.errcode = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->servicelist.clear(); + uint32_t _size33; + ::apache::thrift::protocol::TType _etype36; + iprot->readListBegin(_etype36, _size33); + this->servicelist.resize(_size33); + uint32_t _i37; + for (_i37 = 0; _i37 < _size33; ++_i37) + { + xfer += this->servicelist[_i37].read(iprot); + } + iprot->readListEnd(); + } + this->__isset.servicelist = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t ProtocolResponse::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ProtocolResponse"); + xfer += oprot->writeFieldBegin("errcode", ::apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32(this->errcode); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("servicelist", ::apache::thrift::protocol::T_LIST, 2); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->servicelist.size())); + std::vector ::const_iterator _iter38; + for (_iter38 = this->servicelist.begin(); _iter38 != this->servicelist.end(); ++_iter38) + { + xfer += (*_iter38).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +} // namespace diff --git a/common/gen-cpp/naming_common_types.h b/common/gen-cpp/naming_common_types.h new file mode 100644 index 0000000..b15324b --- /dev/null +++ b/common/gen-cpp/naming_common_types.h @@ -0,0 +1,744 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef naming_common_TYPES_H +#define naming_common_TYPES_H + +#include +#include +#include +#include + + + +namespace meituan_mns { + +struct UptCmd { + enum type { + RESET = 0, + ADD = 1, + DELETE = 2 + }; +}; + +extern const std::map _UptCmd_VALUES_TO_NAMES; + +struct fb_status { + enum type { + DEAD = 0, + STARTING = 1, + ALIVE = 2, + STOPPING = 3, + STOPPED = 4, + WARNING = 5 + }; +}; + +extern const std::map _fb_status_VALUES_TO_NAMES; + +struct HeartbeatSupportType { + enum type { + NoSupport = 0, + P2POnly = 1, + ScannerOnly = 2, + BothSupport = 3 + }; +}; + +extern const std::map _HeartbeatSupportType_VALUES_TO_NAMES; + +typedef struct _ServiceDetail__isset { + _ServiceDetail__isset() : unifiedProto(false) {} + bool unifiedProto; +} _ServiceDetail__isset; + +class ServiceDetail { + public: + + static const char* ascii_fingerprint; // = "5892306F7B861249AE8E27C8ED619593"; + static const uint8_t binary_fingerprint[16]; // = {0x58,0x92,0x30,0x6F,0x7B,0x86,0x12,0x49,0xAE,0x8E,0x27,0xC8,0xED,0x61,0x95,0x93}; + + ServiceDetail() : unifiedProto(0) { + } + + virtual ~ServiceDetail() throw() {} + + bool unifiedProto; + + _ServiceDetail__isset __isset; + + void __set_unifiedProto(const bool val) { + unifiedProto = val; + } + + bool operator == (const ServiceDetail & rhs) const + { + if (!(unifiedProto == rhs.unifiedProto)) + return false; + return true; + } + bool operator != (const ServiceDetail &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceDetail & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _SGService__isset { + _SGService__isset() : appkey(false), version(false), ip(false), port(false), weight(false), status(false), role(false), envir(false), lastUpdateTime(false), fweight(false), serverType(false), protocol(false), serviceInfo(false), heartbeatSupport(false), warmup(false) {} + bool appkey; + bool version; + bool ip; + bool port; + bool weight; + bool status; + bool role; + bool envir; + bool lastUpdateTime; + bool fweight; + bool serverType; + bool protocol; + bool serviceInfo; + bool heartbeatSupport; + bool warmup; +} _SGService__isset; + +class SGService { + public: + + static const char* ascii_fingerprint; // = "BE473A6FD5DE924200DDD8D539C779C1"; + static const uint8_t binary_fingerprint[16]; // = {0xBE,0x47,0x3A,0x6F,0xD5,0xDE,0x92,0x42,0x00,0xDD,0xD8,0xD5,0x39,0xC7,0x79,0xC1}; + + SGService() : appkey(""), version(""), ip(""), port(0), weight(0), status(0), role(0), envir(0), lastUpdateTime(0), fweight(0), serverType(0), protocol(""), heartbeatSupport(0), warmup(0) { + } + + virtual ~SGService() throw() {} + + std::string appkey; + std::string version; + std::string ip; + int32_t port; + int32_t weight; + int32_t status; + int32_t role; + int32_t envir; + int32_t lastUpdateTime; + double fweight; + int32_t serverType; + std::string protocol; + std::map serviceInfo; + int8_t heartbeatSupport; + int32_t warmup; + + _SGService__isset __isset; + + void __set_appkey(const std::string& val) { + appkey = val; + } + + void __set_version(const std::string& val) { + version = val; + } + + void __set_ip(const std::string& val) { + ip = val; + } + + void __set_port(const int32_t val) { + port = val; + } + + void __set_weight(const int32_t val) { + weight = val; + } + + void __set_status(const int32_t val) { + status = val; + } + + void __set_role(const int32_t val) { + role = val; + } + + void __set_envir(const int32_t val) { + envir = val; + } + + void __set_lastUpdateTime(const int32_t val) { + lastUpdateTime = val; + } + + void __set_fweight(const double val) { + fweight = val; + } + + void __set_serverType(const int32_t val) { + serverType = val; + } + + void __set_protocol(const std::string& val) { + protocol = val; + } + + void __set_serviceInfo(const std::map & val) { + serviceInfo = val; + } + + void __set_heartbeatSupport(const int8_t val) { + heartbeatSupport = val; + } + + void __set_warmup(const int32_t val) { + warmup = val; + } + + bool operator == (const SGService & rhs) const + { + if (!(appkey == rhs.appkey)) + return false; + if (!(version == rhs.version)) + return false; + if (!(ip == rhs.ip)) + return false; + if (!(port == rhs.port)) + return false; + if (!(weight == rhs.weight)) + return false; + if (!(status == rhs.status)) + return false; + if (!(role == rhs.role)) + return false; + if (!(envir == rhs.envir)) + return false; + if (!(lastUpdateTime == rhs.lastUpdateTime)) + return false; + if (!(fweight == rhs.fweight)) + return false; + if (!(serverType == rhs.serverType)) + return false; + if (!(protocol == rhs.protocol)) + return false; + if (!(serviceInfo == rhs.serviceInfo)) + return false; + if (!(heartbeatSupport == rhs.heartbeatSupport)) + return false; + if (!(warmup == rhs.warmup)) + return false; + return true; + } + bool operator != (const SGService &rhs) const { + return !(*this == rhs); + } + + bool operator < (const SGService & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceNode__isset { + _ServiceNode__isset() : serviceName(false), appkeys(false), lastUpdateTime(false) {} + bool serviceName; + bool appkeys; + bool lastUpdateTime; +} _ServiceNode__isset; + +class ServiceNode { + public: + + static const char* ascii_fingerprint; // = "E6EB76A1BCBAF7124A43817D5BC322F7"; + static const uint8_t binary_fingerprint[16]; // = {0xE6,0xEB,0x76,0xA1,0xBC,0xBA,0xF7,0x12,0x4A,0x43,0x81,0x7D,0x5B,0xC3,0x22,0xF7}; + + ServiceNode() : serviceName(""), lastUpdateTime(0) { + } + + virtual ~ServiceNode() throw() {} + + std::string serviceName; + std::set appkeys; + int32_t lastUpdateTime; + + _ServiceNode__isset __isset; + + void __set_serviceName(const std::string& val) { + serviceName = val; + } + + void __set_appkeys(const std::set & val) { + appkeys = val; + } + + void __set_lastUpdateTime(const int32_t val) { + lastUpdateTime = val; + } + + bool operator == (const ServiceNode & rhs) const + { + if (!(serviceName == rhs.serviceName)) + return false; + if (!(appkeys == rhs.appkeys)) + return false; + if (!(lastUpdateTime == rhs.lastUpdateTime)) + return false; + return true; + } + bool operator != (const ServiceNode &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceNode & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _Consumer__isset { + _Consumer__isset() : ips(false), appkeys(false) {} + bool ips; + bool appkeys; +} _Consumer__isset; + +class Consumer { + public: + + static const char* ascii_fingerprint; // = "AA819045335EAFAB5C2FE456B4B9CC1C"; + static const uint8_t binary_fingerprint[16]; // = {0xAA,0x81,0x90,0x45,0x33,0x5E,0xAF,0xAB,0x5C,0x2F,0xE4,0x56,0xB4,0xB9,0xCC,0x1C}; + + Consumer() { + } + + virtual ~Consumer() throw() {} + + std::vector ips; + std::vector appkeys; + + _Consumer__isset __isset; + + void __set_ips(const std::vector & val) { + ips = val; + } + + void __set_appkeys(const std::vector & val) { + appkeys = val; + } + + bool operator == (const Consumer & rhs) const + { + if (!(ips == rhs.ips)) + return false; + if (!(appkeys == rhs.appkeys)) + return false; + return true; + } + bool operator != (const Consumer &rhs) const { + return !(*this == rhs); + } + + bool operator < (const Consumer & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _CRouteData__isset { + _CRouteData__isset() : id(false), name(false), appkey(false), env(false), category(false), priority(false), status(false), consumer(false), provider(false), updateTime(false), createTime(false), reserved(false) {} + bool id; + bool name; + bool appkey; + bool env; + bool category; + bool priority; + bool status; + bool consumer; + bool provider; + bool updateTime; + bool createTime; + bool reserved; +} _CRouteData__isset; + +class CRouteData { + public: + + static const char* ascii_fingerprint; // = "BA097AEDC13A13D0EF25D33F4578FC59"; + static const uint8_t binary_fingerprint[16]; // = {0xBA,0x09,0x7A,0xED,0xC1,0x3A,0x13,0xD0,0xEF,0x25,0xD3,0x3F,0x45,0x78,0xFC,0x59}; + + CRouteData() : id(""), name(""), appkey(""), env(0), category(0), priority(0), status(0), updateTime(0), createTime(0), reserved("") { + } + + virtual ~CRouteData() throw() {} + + std::string id; + std::string name; + std::string appkey; + int32_t env; + int32_t category; + int32_t priority; + int32_t status; + Consumer consumer; + std::vector provider; + int32_t updateTime; + int32_t createTime; + std::string reserved; + + _CRouteData__isset __isset; + + void __set_id(const std::string& val) { + id = val; + } + + void __set_name(const std::string& val) { + name = val; + } + + void __set_appkey(const std::string& val) { + appkey = val; + } + + void __set_env(const int32_t val) { + env = val; + } + + void __set_category(const int32_t val) { + category = val; + } + + void __set_priority(const int32_t val) { + priority = val; + } + + void __set_status(const int32_t val) { + status = val; + } + + void __set_consumer(const Consumer& val) { + consumer = val; + } + + void __set_provider(const std::vector & val) { + provider = val; + } + + void __set_updateTime(const int32_t val) { + updateTime = val; + } + + void __set_createTime(const int32_t val) { + createTime = val; + } + + void __set_reserved(const std::string& val) { + reserved = val; + } + + bool operator == (const CRouteData & rhs) const + { + if (!(id == rhs.id)) + return false; + if (!(name == rhs.name)) + return false; + if (!(appkey == rhs.appkey)) + return false; + if (!(env == rhs.env)) + return false; + if (!(category == rhs.category)) + return false; + if (!(priority == rhs.priority)) + return false; + if (!(status == rhs.status)) + return false; + if (!(consumer == rhs.consumer)) + return false; + if (!(provider == rhs.provider)) + return false; + if (!(updateTime == rhs.updateTime)) + return false; + if (!(createTime == rhs.createTime)) + return false; + if (!(reserved == rhs.reserved)) + return false; + return true; + } + bool operator != (const CRouteData &rhs) const { + return !(*this == rhs); + } + + bool operator < (const CRouteData & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _CProviderNode__isset { + _CProviderNode__isset() : appkey(false), lastModifiedTime(false), mtime(false), cversion(false), version(false) {} + bool appkey; + bool lastModifiedTime; + bool mtime; + bool cversion; + bool version; +} _CProviderNode__isset; + +class CProviderNode { + public: + + static const char* ascii_fingerprint; // = "9118FDD77343DD231D97C424A53D2DCF"; + static const uint8_t binary_fingerprint[16]; // = {0x91,0x18,0xFD,0xD7,0x73,0x43,0xDD,0x23,0x1D,0x97,0xC4,0x24,0xA5,0x3D,0x2D,0xCF}; + + CProviderNode() : appkey(""), lastModifiedTime(0), mtime(0), cversion(0), version(0) { + } + + virtual ~CProviderNode() throw() {} + + std::string appkey; + int64_t lastModifiedTime; + int64_t mtime; + int64_t cversion; + int64_t version; + + _CProviderNode__isset __isset; + + void __set_appkey(const std::string& val) { + appkey = val; + } + + void __set_lastModifiedTime(const int64_t val) { + lastModifiedTime = val; + } + + void __set_mtime(const int64_t val) { + mtime = val; + } + + void __set_cversion(const int64_t val) { + cversion = val; + } + + void __set_version(const int64_t val) { + version = val; + } + + bool operator == (const CProviderNode & rhs) const + { + if (!(appkey == rhs.appkey)) + return false; + if (!(lastModifiedTime == rhs.lastModifiedTime)) + return false; + if (!(mtime == rhs.mtime)) + return false; + if (!(cversion == rhs.cversion)) + return false; + if (!(version == rhs.version)) + return false; + return true; + } + bool operator != (const CProviderNode &rhs) const { + return !(*this == rhs); + } + + bool operator < (const CProviderNode & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _CRouteNode__isset { + _CRouteNode__isset() : appkey(false), lastModifiedTime(false), mtime(false), cversion(false), version(false) {} + bool appkey; + bool lastModifiedTime; + bool mtime; + bool cversion; + bool version; +} _CRouteNode__isset; + +class CRouteNode { + public: + + static const char* ascii_fingerprint; // = "9118FDD77343DD231D97C424A53D2DCF"; + static const uint8_t binary_fingerprint[16]; // = {0x91,0x18,0xFD,0xD7,0x73,0x43,0xDD,0x23,0x1D,0x97,0xC4,0x24,0xA5,0x3D,0x2D,0xCF}; + + CRouteNode() : appkey(""), lastModifiedTime(0), mtime(0), cversion(0), version(0) { + } + + virtual ~CRouteNode() throw() {} + + std::string appkey; + int64_t lastModifiedTime; + int64_t mtime; + int64_t cversion; + int64_t version; + + _CRouteNode__isset __isset; + + void __set_appkey(const std::string& val) { + appkey = val; + } + + void __set_lastModifiedTime(const int64_t val) { + lastModifiedTime = val; + } + + void __set_mtime(const int64_t val) { + mtime = val; + } + + void __set_cversion(const int64_t val) { + cversion = val; + } + + void __set_version(const int64_t val) { + version = val; + } + + bool operator == (const CRouteNode & rhs) const + { + if (!(appkey == rhs.appkey)) + return false; + if (!(lastModifiedTime == rhs.lastModifiedTime)) + return false; + if (!(mtime == rhs.mtime)) + return false; + if (!(cversion == rhs.cversion)) + return false; + if (!(version == rhs.version)) + return false; + return true; + } + bool operator != (const CRouteNode &rhs) const { + return !(*this == rhs); + } + + bool operator < (const CRouteNode & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ProtocolRequest__isset { + _ProtocolRequest__isset() : localAppkey(false), remoteAppkey(false), protocol(false), serviceName(false) {} + bool localAppkey; + bool remoteAppkey; + bool protocol; + bool serviceName; +} _ProtocolRequest__isset; + +class ProtocolRequest { + public: + + static const char* ascii_fingerprint; // = "C93D890311F28844166CF6E571EB3AC2"; + static const uint8_t binary_fingerprint[16]; // = {0xC9,0x3D,0x89,0x03,0x11,0xF2,0x88,0x44,0x16,0x6C,0xF6,0xE5,0x71,0xEB,0x3A,0xC2}; + + ProtocolRequest() : localAppkey(""), remoteAppkey(""), protocol(""), serviceName("") { + } + + virtual ~ProtocolRequest() throw() {} + + std::string localAppkey; + std::string remoteAppkey; + std::string protocol; + std::string serviceName; + + _ProtocolRequest__isset __isset; + + void __set_localAppkey(const std::string& val) { + localAppkey = val; + } + + void __set_remoteAppkey(const std::string& val) { + remoteAppkey = val; + } + + void __set_protocol(const std::string& val) { + protocol = val; + } + + void __set_serviceName(const std::string& val) { + serviceName = val; + } + + bool operator == (const ProtocolRequest & rhs) const + { + if (!(localAppkey == rhs.localAppkey)) + return false; + if (!(remoteAppkey == rhs.remoteAppkey)) + return false; + if (!(protocol == rhs.protocol)) + return false; + if (!(serviceName == rhs.serviceName)) + return false; + return true; + } + bool operator != (const ProtocolRequest &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ProtocolRequest & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ProtocolResponse__isset { + _ProtocolResponse__isset() : errcode(false), servicelist(false) {} + bool errcode; + bool servicelist; +} _ProtocolResponse__isset; + +class ProtocolResponse { + public: + + static const char* ascii_fingerprint; // = "F56E7FEC73C75A28B4691E35627DB92D"; + static const uint8_t binary_fingerprint[16]; // = {0xF5,0x6E,0x7F,0xEC,0x73,0xC7,0x5A,0x28,0xB4,0x69,0x1E,0x35,0x62,0x7D,0xB9,0x2D}; + + ProtocolResponse() : errcode(0) { + } + + virtual ~ProtocolResponse() throw() {} + + int32_t errcode; + std::vector servicelist; + + _ProtocolResponse__isset __isset; + + void __set_errcode(const int32_t val) { + errcode = val; + } + + void __set_servicelist(const std::vector & val) { + servicelist = val; + } + + bool operator == (const ProtocolResponse & rhs) const + { + if (!(errcode == rhs.errcode)) + return false; + if (!(servicelist == rhs.servicelist)) + return false; + return true; + } + bool operator != (const ProtocolResponse &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ProtocolResponse & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +} // namespace + +#endif diff --git a/common/gen-cpp/naming_data_constants.cpp b/common/gen-cpp/naming_data_constants.cpp new file mode 100644 index 0000000..a9a573b --- /dev/null +++ b/common/gen-cpp/naming_data_constants.cpp @@ -0,0 +1,17 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "naming_data_constants.h" + +namespace meituan_mns { + +const naming_dataConstants g_naming_data_constants; + +naming_dataConstants::naming_dataConstants() { +} + +} // namespace + diff --git a/common/gen-cpp/naming_data_constants.h b/common/gen-cpp/naming_data_constants.h new file mode 100644 index 0000000..7ef8442 --- /dev/null +++ b/common/gen-cpp/naming_data_constants.h @@ -0,0 +1,24 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef naming_data_CONSTANTS_H +#define naming_data_CONSTANTS_H + +#include "naming_data_types.h" + +namespace meituan_mns { + +class naming_dataConstants { + public: + naming_dataConstants(); + +}; + +extern const naming_dataConstants g_naming_data_constants; + +} // namespace + +#endif diff --git a/common/gen-cpp/naming_data_types.cpp b/common/gen-cpp/naming_data_types.cpp new file mode 100644 index 0000000..de69dea --- /dev/null +++ b/common/gen-cpp/naming_data_types.cpp @@ -0,0 +1,726 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "naming_data_types.h" + +namespace meituan_mns { + +int _kRegistCmdValues[] = { + RegistCmd::REGIST, + RegistCmd::UNREGIST +}; +const char* _kRegistCmdNames[] = { + "REGIST", + "UNREGIST" +}; +const std::map _RegistCmd_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(2, _kRegistCmdValues, _kRegistCmdNames), ::apache::thrift::TEnumIterator(-1, NULL, NULL)); + +const char* getservice_req_param_t::ascii_fingerprint = "C93D890311F28844166CF6E571EB3AC2"; +const uint8_t getservice_req_param_t::binary_fingerprint[16] = {0xC9,0x3D,0x89,0x03,0x11,0xF2,0x88,0x44,0x16,0x6C,0xF6,0xE5,0x71,0xEB,0x3A,0xC2}; + +uint32_t getservice_req_param_t::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->localAppkey); + this->__isset.localAppkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->remoteAppkey); + this->__isset.remoteAppkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->version); + this->__isset.version = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->protocol); + this->__isset.protocol = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t getservice_req_param_t::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("getservice_req_param_t"); + xfer += oprot->writeFieldBegin("localAppkey", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->localAppkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("remoteAppkey", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString(this->remoteAppkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("version", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString(this->version); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("protocol", ::apache::thrift::protocol::T_STRING, 4); + xfer += oprot->writeString(this->protocol); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* getservice_res_param_t::ascii_fingerprint = "BEE4DB4CE7FE0806BC8C2B45BA6E4742"; +const uint8_t getservice_res_param_t::binary_fingerprint[16] = {0xBE,0xE4,0xDB,0x4C,0xE7,0xFE,0x08,0x06,0xBC,0x8C,0x2B,0x45,0xBA,0x6E,0x47,0x42}; + +uint32_t getservice_res_param_t::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->localAppkey); + this->__isset.localAppkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->remoteAppkey); + this->__isset.remoteAppkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->version); + this->__isset.version = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->serviceList.clear(); + uint32_t _size0; + ::apache::thrift::protocol::TType _etype3; + iprot->readListBegin(_etype3, _size0); + this->serviceList.resize(_size0); + uint32_t _i4; + for (_i4 = 0; _i4 < _size0; ++_i4) + { + xfer += this->serviceList[_i4].read(iprot); + } + iprot->readListEnd(); + } + this->__isset.serviceList = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 5: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->protocol); + this->__isset.protocol = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t getservice_res_param_t::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("getservice_res_param_t"); + xfer += oprot->writeFieldBegin("localAppkey", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->localAppkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("remoteAppkey", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString(this->remoteAppkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("version", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString(this->version); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("serviceList", ::apache::thrift::protocol::T_LIST, 4); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->serviceList.size())); + std::vector ::const_iterator _iter5; + for (_iter5 = this->serviceList.begin(); _iter5 != this->serviceList.end(); ++_iter5) + { + xfer += (*_iter5).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("protocol", ::apache::thrift::protocol::T_STRING, 5); + xfer += oprot->writeString(this->protocol); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* getservicename_req_param_t::ascii_fingerprint = "C93D890311F28844166CF6E571EB3AC2"; +const uint8_t getservicename_req_param_t::binary_fingerprint[16] = {0xC9,0x3D,0x89,0x03,0x11,0xF2,0x88,0x44,0x16,0x6C,0xF6,0xE5,0x71,0xEB,0x3A,0xC2}; + +uint32_t getservicename_req_param_t::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->localAppkey); + this->__isset.localAppkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->servicename); + this->__isset.servicename = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->version); + this->__isset.version = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->protocol); + this->__isset.protocol = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t getservicename_req_param_t::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("getservicename_req_param_t"); + xfer += oprot->writeFieldBegin("localAppkey", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->localAppkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("servicename", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString(this->servicename); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("version", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString(this->version); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("protocol", ::apache::thrift::protocol::T_STRING, 4); + xfer += oprot->writeString(this->protocol); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* getservicename_res_param_t::ascii_fingerprint = "029F9D059094419E5A20EF21917997A5"; +const uint8_t getservicename_res_param_t::binary_fingerprint[16] = {0x02,0x9F,0x9D,0x05,0x90,0x94,0x41,0x9E,0x5A,0x20,0xEF,0x21,0x91,0x79,0x97,0xA5}; + +uint32_t getservicename_res_param_t::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->localAppkey); + this->__isset.localAppkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->servicename); + this->__isset.servicename = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->version); + this->__isset.version = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_SET) { + { + this->appkeys.clear(); + uint32_t _size6; + ::apache::thrift::protocol::TType _etype9; + iprot->readSetBegin(_etype9, _size6); + uint32_t _i10; + for (_i10 = 0; _i10 < _size6; ++_i10) + { + std::string _elem11; + xfer += iprot->readString(_elem11); + this->appkeys.insert(_elem11); + } + iprot->readSetEnd(); + } + this->__isset.appkeys = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 5: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->protocol); + this->__isset.protocol = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t getservicename_res_param_t::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("getservicename_res_param_t"); + xfer += oprot->writeFieldBegin("localAppkey", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->localAppkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("servicename", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString(this->servicename); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("version", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString(this->version); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("appkeys", ::apache::thrift::protocol::T_SET, 4); + { + xfer += oprot->writeSetBegin(::apache::thrift::protocol::T_STRING, static_cast(this->appkeys.size())); + std::set ::const_iterator _iter12; + for (_iter12 = this->appkeys.begin(); _iter12 != this->appkeys.end(); ++_iter12) + { + xfer += oprot->writeString((*_iter12)); + } + xfer += oprot->writeSetEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("protocol", ::apache::thrift::protocol::T_STRING, 5); + xfer += oprot->writeString(this->protocol); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* getroute_req_param_t::ascii_fingerprint = "C93D890311F28844166CF6E571EB3AC2"; +const uint8_t getroute_req_param_t::binary_fingerprint[16] = {0xC9,0x3D,0x89,0x03,0x11,0xF2,0x88,0x44,0x16,0x6C,0xF6,0xE5,0x71,0xEB,0x3A,0xC2}; + +uint32_t getroute_req_param_t::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->localAppkey); + this->__isset.localAppkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->remoteAppkey); + this->__isset.remoteAppkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->version); + this->__isset.version = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->protocol); + this->__isset.protocol = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t getroute_req_param_t::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("getroute_req_param_t"); + xfer += oprot->writeFieldBegin("localAppkey", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->localAppkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("remoteAppkey", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString(this->remoteAppkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("version", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString(this->version); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("protocol", ::apache::thrift::protocol::T_STRING, 4); + xfer += oprot->writeString(this->protocol); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* getroute_res_param_t::ascii_fingerprint = "61123EDDD00927E85F89381EEBDBC37F"; +const uint8_t getroute_res_param_t::binary_fingerprint[16] = {0x61,0x12,0x3E,0xDD,0xD0,0x09,0x27,0xE8,0x5F,0x89,0x38,0x1E,0xEB,0xDB,0xC3,0x7F}; + +uint32_t getroute_res_param_t::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->localAppkey); + this->__isset.localAppkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->remoteAppkey); + this->__isset.remoteAppkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->version); + this->__isset.version = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_LIST) { + { + this->routeList.clear(); + uint32_t _size13; + ::apache::thrift::protocol::TType _etype16; + iprot->readListBegin(_etype16, _size13); + this->routeList.resize(_size13); + uint32_t _i17; + for (_i17 = 0; _i17 < _size13; ++_i17) + { + xfer += this->routeList[_i17].read(iprot); + } + iprot->readListEnd(); + } + this->__isset.routeList = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 5: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->protocol); + this->__isset.protocol = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t getroute_res_param_t::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("getroute_res_param_t"); + xfer += oprot->writeFieldBegin("localAppkey", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->localAppkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("remoteAppkey", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString(this->remoteAppkey); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("version", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString(this->version); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("routeList", ::apache::thrift::protocol::T_LIST, 4); + { + xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->routeList.size())); + std::vector ::const_iterator _iter18; + for (_iter18 = this->routeList.begin(); _iter18 != this->routeList.end(); ++_iter18) + { + xfer += (*_iter18).write(oprot); + } + xfer += oprot->writeListEnd(); + } + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("protocol", ::apache::thrift::protocol::T_STRING, 5); + xfer += oprot->writeString(this->protocol); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* regist_req_param_t::ascii_fingerprint = "0E9168D7B65EE33C82EF267B678FCB69"; +const uint8_t regist_req_param_t::binary_fingerprint[16] = {0x0E,0x91,0x68,0xD7,0xB6,0x5E,0xE3,0x3C,0x82,0xEF,0x26,0x7B,0x67,0x8F,0xCB,0x69}; + +uint32_t regist_req_param_t::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->retry_times); + this->__isset.retry_times = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->sgservice.read(iprot); + this->__isset.sgservice = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->uptCmd); + this->__isset.uptCmd = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_I32) { + int32_t ecast19; + xfer += iprot->readI32(ecast19); + this->regCmd = (RegistCmd::type)ecast19; + this->__isset.regCmd = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t regist_req_param_t::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("regist_req_param_t"); + xfer += oprot->writeFieldBegin("retry_times", ::apache::thrift::protocol::T_I32, 1); + xfer += oprot->writeI32(this->retry_times); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("sgservice", ::apache::thrift::protocol::T_STRUCT, 2); + xfer += this->sgservice.write(oprot); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("uptCmd", ::apache::thrift::protocol::T_I32, 3); + xfer += oprot->writeI32(this->uptCmd); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("regCmd", ::apache::thrift::protocol::T_I32, 4); + xfer += oprot->writeI32((int32_t)this->regCmd); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +} // namespace diff --git a/common/gen-cpp/naming_data_types.h b/common/gen-cpp/naming_data_types.h new file mode 100644 index 0000000..9272deb --- /dev/null +++ b/common/gen-cpp/naming_data_types.h @@ -0,0 +1,514 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef naming_data_TYPES_H +#define naming_data_TYPES_H + +#include +#include +#include +#include + +#include "naming_common_types.h" + + +namespace meituan_mns { + +struct RegistCmd { + enum type { + REGIST = 0, + UNREGIST = 1 + }; +}; + +extern const std::map _RegistCmd_VALUES_TO_NAMES; + +typedef class ::meituan_mns::SGService SGService; + +typedef class ::meituan_mns::CRouteData CRouteData; + +typedef struct _getservice_req_param_t__isset { + _getservice_req_param_t__isset() : localAppkey(false), remoteAppkey(false), version(false), protocol(false) {} + bool localAppkey; + bool remoteAppkey; + bool version; + bool protocol; +} _getservice_req_param_t__isset; + +class getservice_req_param_t { + public: + + static const char* ascii_fingerprint; // = "C93D890311F28844166CF6E571EB3AC2"; + static const uint8_t binary_fingerprint[16]; // = {0xC9,0x3D,0x89,0x03,0x11,0xF2,0x88,0x44,0x16,0x6C,0xF6,0xE5,0x71,0xEB,0x3A,0xC2}; + + getservice_req_param_t() : localAppkey(""), remoteAppkey(""), version(""), protocol("") { + } + + virtual ~getservice_req_param_t() throw() {} + + std::string localAppkey; + std::string remoteAppkey; + std::string version; + std::string protocol; + + _getservice_req_param_t__isset __isset; + + void __set_localAppkey(const std::string& val) { + localAppkey = val; + } + + void __set_remoteAppkey(const std::string& val) { + remoteAppkey = val; + } + + void __set_version(const std::string& val) { + version = val; + } + + void __set_protocol(const std::string& val) { + protocol = val; + } + + bool operator == (const getservice_req_param_t & rhs) const + { + if (!(localAppkey == rhs.localAppkey)) + return false; + if (!(remoteAppkey == rhs.remoteAppkey)) + return false; + if (!(version == rhs.version)) + return false; + if (!(protocol == rhs.protocol)) + return false; + return true; + } + bool operator != (const getservice_req_param_t &rhs) const { + return !(*this == rhs); + } + + bool operator < (const getservice_req_param_t & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _getservice_res_param_t__isset { + _getservice_res_param_t__isset() : localAppkey(false), remoteAppkey(false), version(false), serviceList(false), protocol(false) {} + bool localAppkey; + bool remoteAppkey; + bool version; + bool serviceList; + bool protocol; +} _getservice_res_param_t__isset; + +class getservice_res_param_t { + public: + + static const char* ascii_fingerprint; // = "BEE4DB4CE7FE0806BC8C2B45BA6E4742"; + static const uint8_t binary_fingerprint[16]; // = {0xBE,0xE4,0xDB,0x4C,0xE7,0xFE,0x08,0x06,0xBC,0x8C,0x2B,0x45,0xBA,0x6E,0x47,0x42}; + + getservice_res_param_t() : localAppkey(""), remoteAppkey(""), version(""), protocol("") { + } + + virtual ~getservice_res_param_t() throw() {} + + std::string localAppkey; + std::string remoteAppkey; + std::string version; + std::vector serviceList; + std::string protocol; + + _getservice_res_param_t__isset __isset; + + void __set_localAppkey(const std::string& val) { + localAppkey = val; + } + + void __set_remoteAppkey(const std::string& val) { + remoteAppkey = val; + } + + void __set_version(const std::string& val) { + version = val; + } + + void __set_serviceList(const std::vector & val) { + serviceList = val; + } + + void __set_protocol(const std::string& val) { + protocol = val; + } + + bool operator == (const getservice_res_param_t & rhs) const + { + if (!(localAppkey == rhs.localAppkey)) + return false; + if (!(remoteAppkey == rhs.remoteAppkey)) + return false; + if (!(version == rhs.version)) + return false; + if (!(serviceList == rhs.serviceList)) + return false; + if (!(protocol == rhs.protocol)) + return false; + return true; + } + bool operator != (const getservice_res_param_t &rhs) const { + return !(*this == rhs); + } + + bool operator < (const getservice_res_param_t & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _getservicename_req_param_t__isset { + _getservicename_req_param_t__isset() : localAppkey(false), servicename(false), version(false), protocol(false) {} + bool localAppkey; + bool servicename; + bool version; + bool protocol; +} _getservicename_req_param_t__isset; + +class getservicename_req_param_t { + public: + + static const char* ascii_fingerprint; // = "C93D890311F28844166CF6E571EB3AC2"; + static const uint8_t binary_fingerprint[16]; // = {0xC9,0x3D,0x89,0x03,0x11,0xF2,0x88,0x44,0x16,0x6C,0xF6,0xE5,0x71,0xEB,0x3A,0xC2}; + + getservicename_req_param_t() : localAppkey(""), servicename(""), version(""), protocol("") { + } + + virtual ~getservicename_req_param_t() throw() {} + + std::string localAppkey; + std::string servicename; + std::string version; + std::string protocol; + + _getservicename_req_param_t__isset __isset; + + void __set_localAppkey(const std::string& val) { + localAppkey = val; + } + + void __set_servicename(const std::string& val) { + servicename = val; + } + + void __set_version(const std::string& val) { + version = val; + } + + void __set_protocol(const std::string& val) { + protocol = val; + } + + bool operator == (const getservicename_req_param_t & rhs) const + { + if (!(localAppkey == rhs.localAppkey)) + return false; + if (!(servicename == rhs.servicename)) + return false; + if (!(version == rhs.version)) + return false; + if (!(protocol == rhs.protocol)) + return false; + return true; + } + bool operator != (const getservicename_req_param_t &rhs) const { + return !(*this == rhs); + } + + bool operator < (const getservicename_req_param_t & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _getservicename_res_param_t__isset { + _getservicename_res_param_t__isset() : localAppkey(false), servicename(false), version(false), appkeys(false), protocol(false) {} + bool localAppkey; + bool servicename; + bool version; + bool appkeys; + bool protocol; +} _getservicename_res_param_t__isset; + +class getservicename_res_param_t { + public: + + static const char* ascii_fingerprint; // = "029F9D059094419E5A20EF21917997A5"; + static const uint8_t binary_fingerprint[16]; // = {0x02,0x9F,0x9D,0x05,0x90,0x94,0x41,0x9E,0x5A,0x20,0xEF,0x21,0x91,0x79,0x97,0xA5}; + + getservicename_res_param_t() : localAppkey(""), servicename(""), version(""), protocol("") { + } + + virtual ~getservicename_res_param_t() throw() {} + + std::string localAppkey; + std::string servicename; + std::string version; + std::set appkeys; + std::string protocol; + + _getservicename_res_param_t__isset __isset; + + void __set_localAppkey(const std::string& val) { + localAppkey = val; + } + + void __set_servicename(const std::string& val) { + servicename = val; + } + + void __set_version(const std::string& val) { + version = val; + } + + void __set_appkeys(const std::set & val) { + appkeys = val; + } + + void __set_protocol(const std::string& val) { + protocol = val; + } + + bool operator == (const getservicename_res_param_t & rhs) const + { + if (!(localAppkey == rhs.localAppkey)) + return false; + if (!(servicename == rhs.servicename)) + return false; + if (!(version == rhs.version)) + return false; + if (!(appkeys == rhs.appkeys)) + return false; + if (!(protocol == rhs.protocol)) + return false; + return true; + } + bool operator != (const getservicename_res_param_t &rhs) const { + return !(*this == rhs); + } + + bool operator < (const getservicename_res_param_t & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _getroute_req_param_t__isset { + _getroute_req_param_t__isset() : localAppkey(false), remoteAppkey(false), version(false), protocol(false) {} + bool localAppkey; + bool remoteAppkey; + bool version; + bool protocol; +} _getroute_req_param_t__isset; + +class getroute_req_param_t { + public: + + static const char* ascii_fingerprint; // = "C93D890311F28844166CF6E571EB3AC2"; + static const uint8_t binary_fingerprint[16]; // = {0xC9,0x3D,0x89,0x03,0x11,0xF2,0x88,0x44,0x16,0x6C,0xF6,0xE5,0x71,0xEB,0x3A,0xC2}; + + getroute_req_param_t() : localAppkey(""), remoteAppkey(""), version(""), protocol("") { + } + + virtual ~getroute_req_param_t() throw() {} + + std::string localAppkey; + std::string remoteAppkey; + std::string version; + std::string protocol; + + _getroute_req_param_t__isset __isset; + + void __set_localAppkey(const std::string& val) { + localAppkey = val; + } + + void __set_remoteAppkey(const std::string& val) { + remoteAppkey = val; + } + + void __set_version(const std::string& val) { + version = val; + } + + void __set_protocol(const std::string& val) { + protocol = val; + } + + bool operator == (const getroute_req_param_t & rhs) const + { + if (!(localAppkey == rhs.localAppkey)) + return false; + if (!(remoteAppkey == rhs.remoteAppkey)) + return false; + if (!(version == rhs.version)) + return false; + if (!(protocol == rhs.protocol)) + return false; + return true; + } + bool operator != (const getroute_req_param_t &rhs) const { + return !(*this == rhs); + } + + bool operator < (const getroute_req_param_t & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _getroute_res_param_t__isset { + _getroute_res_param_t__isset() : localAppkey(false), remoteAppkey(false), version(false), routeList(false), protocol(false) {} + bool localAppkey; + bool remoteAppkey; + bool version; + bool routeList; + bool protocol; +} _getroute_res_param_t__isset; + +class getroute_res_param_t { + public: + + static const char* ascii_fingerprint; // = "61123EDDD00927E85F89381EEBDBC37F"; + static const uint8_t binary_fingerprint[16]; // = {0x61,0x12,0x3E,0xDD,0xD0,0x09,0x27,0xE8,0x5F,0x89,0x38,0x1E,0xEB,0xDB,0xC3,0x7F}; + + getroute_res_param_t() : localAppkey(""), remoteAppkey(""), version(""), protocol("") { + } + + virtual ~getroute_res_param_t() throw() {} + + std::string localAppkey; + std::string remoteAppkey; + std::string version; + std::vector routeList; + std::string protocol; + + _getroute_res_param_t__isset __isset; + + void __set_localAppkey(const std::string& val) { + localAppkey = val; + } + + void __set_remoteAppkey(const std::string& val) { + remoteAppkey = val; + } + + void __set_version(const std::string& val) { + version = val; + } + + void __set_routeList(const std::vector & val) { + routeList = val; + } + + void __set_protocol(const std::string& val) { + protocol = val; + } + + bool operator == (const getroute_res_param_t & rhs) const + { + if (!(localAppkey == rhs.localAppkey)) + return false; + if (!(remoteAppkey == rhs.remoteAppkey)) + return false; + if (!(version == rhs.version)) + return false; + if (!(routeList == rhs.routeList)) + return false; + if (!(protocol == rhs.protocol)) + return false; + return true; + } + bool operator != (const getroute_res_param_t &rhs) const { + return !(*this == rhs); + } + + bool operator < (const getroute_res_param_t & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _regist_req_param_t__isset { + _regist_req_param_t__isset() : retry_times(false), sgservice(false), uptCmd(false), regCmd(false) {} + bool retry_times; + bool sgservice; + bool uptCmd; + bool regCmd; +} _regist_req_param_t__isset; + +class regist_req_param_t { + public: + + static const char* ascii_fingerprint; // = "0E9168D7B65EE33C82EF267B678FCB69"; + static const uint8_t binary_fingerprint[16]; // = {0x0E,0x91,0x68,0xD7,0xB6,0x5E,0xE3,0x3C,0x82,0xEF,0x26,0x7B,0x67,0x8F,0xCB,0x69}; + + regist_req_param_t() : retry_times(0), uptCmd(0), regCmd((RegistCmd::type)0) { + } + + virtual ~regist_req_param_t() throw() {} + + int32_t retry_times; + SGService sgservice; + int32_t uptCmd; + RegistCmd::type regCmd; + + _regist_req_param_t__isset __isset; + + void __set_retry_times(const int32_t val) { + retry_times = val; + } + + void __set_sgservice(const SGService& val) { + sgservice = val; + } + + void __set_uptCmd(const int32_t val) { + uptCmd = val; + } + + void __set_regCmd(const RegistCmd::type val) { + regCmd = val; + } + + bool operator == (const regist_req_param_t & rhs) const + { + if (!(retry_times == rhs.retry_times)) + return false; + if (!(sgservice == rhs.sgservice)) + return false; + if (!(uptCmd == rhs.uptCmd)) + return false; + if (!(regCmd == rhs.regCmd)) + return false; + return true; + } + bool operator != (const regist_req_param_t &rhs) const { + return !(*this == rhs); + } + + bool operator < (const regist_req_param_t & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +} // namespace + +#endif diff --git a/common/gen-cpp/naming_service_constants.cpp b/common/gen-cpp/naming_service_constants.cpp new file mode 100644 index 0000000..77a730a --- /dev/null +++ b/common/gen-cpp/naming_service_constants.cpp @@ -0,0 +1,17 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "naming_service_constants.h" + +namespace meituan_mns { + +const naming_serviceConstants g_naming_service_constants; + +naming_serviceConstants::naming_serviceConstants() { +} + +} // namespace + diff --git a/common/gen-cpp/naming_service_constants.h b/common/gen-cpp/naming_service_constants.h new file mode 100644 index 0000000..54a6a0c --- /dev/null +++ b/common/gen-cpp/naming_service_constants.h @@ -0,0 +1,24 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef naming_service_CONSTANTS_H +#define naming_service_CONSTANTS_H + +#include "naming_service_types.h" + +namespace meituan_mns { + +class naming_serviceConstants { + public: + naming_serviceConstants(); + +}; + +extern const naming_serviceConstants g_naming_service_constants; + +} // namespace + +#endif diff --git a/common/gen-cpp/naming_service_types.cpp b/common/gen-cpp/naming_service_types.cpp new file mode 100644 index 0000000..5fd5241 --- /dev/null +++ b/common/gen-cpp/naming_service_types.cpp @@ -0,0 +1,11 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "naming_service_types.h" + +namespace meituan_mns { + +} // namespace diff --git a/common/gen-cpp/naming_service_types.h b/common/gen-cpp/naming_service_types.h new file mode 100644 index 0000000..62b923e --- /dev/null +++ b/common/gen-cpp/naming_service_types.h @@ -0,0 +1,28 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef naming_service_TYPES_H +#define naming_service_TYPES_H + +#include +#include +#include +#include + +#include "naming_common_types.h" + + +namespace meituan_mns { + +typedef class ::meituan_mns::SGService SGService; + +typedef class ::meituan_mns::ProtocolRequest ProtocolRequest; + +typedef class ::meituan_mns::ProtocolResponse ProtocolResponse; + +} // namespace + +#endif diff --git a/common/gen-cpp/unified_protocol_constants.cpp b/common/gen-cpp/unified_protocol_constants.cpp new file mode 100644 index 0000000..bc989c3 --- /dev/null +++ b/common/gen-cpp/unified_protocol_constants.cpp @@ -0,0 +1,17 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "unified_protocol_constants.h" + +namespace meituan_mns { + +const unified_protocolConstants g_unified_protocol_constants; + +unified_protocolConstants::unified_protocolConstants() { +} + +} // namespace + diff --git a/common/gen-cpp/unified_protocol_constants.h b/common/gen-cpp/unified_protocol_constants.h new file mode 100644 index 0000000..760de8a --- /dev/null +++ b/common/gen-cpp/unified_protocol_constants.h @@ -0,0 +1,24 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef unified_protocol_CONSTANTS_H +#define unified_protocol_CONSTANTS_H + +#include "unified_protocol_types.h" + +namespace meituan_mns { + +class unified_protocolConstants { + public: + unified_protocolConstants(); + +}; + +extern const unified_protocolConstants g_unified_protocol_constants; + +} // namespace + +#endif diff --git a/common/gen-cpp/unified_protocol_types.cpp b/common/gen-cpp/unified_protocol_types.cpp new file mode 100644 index 0000000..9e5bb3e --- /dev/null +++ b/common/gen-cpp/unified_protocol_types.cpp @@ -0,0 +1,825 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#include "unified_protocol_types.h" + +namespace meituan_mns { + +int _kMessageTypeValues[] = { + MessageType::Normal, + MessageType::NormalHeartbeat, + MessageType::ScannerHeartbeat +}; +const char* _kMessageTypeNames[] = { + "Normal", + "NormalHeartbeat", + "ScannerHeartbeat" +}; +const std::map _MessageType_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(3, _kMessageTypeValues, _kMessageTypeNames), ::apache::thrift::TEnumIterator(-1, NULL, NULL)); + +int _kCompressTypeValues[] = { + CompressType::None, + CompressType::Snappy, + CompressType::Gzip +}; +const char* _kCompressTypeNames[] = { + "None", + "Snappy", + "Gzip" +}; +const std::map _CompressType_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(3, _kCompressTypeValues, _kCompressTypeNames), ::apache::thrift::TEnumIterator(-1, NULL, NULL)); + +int _kCallTypeValues[] = { + CallType::Reply, + CallType::NoReply +}; +const char* _kCallTypeNames[] = { + "Reply", + "NoReply" +}; +const std::map _CallType_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(2, _kCallTypeValues, _kCallTypeNames), ::apache::thrift::TEnumIterator(-1, NULL, NULL)); + +int _kStatusCodesValues[] = { + StatusCodes::Success, + StatusCodes::ApplicationException, + StatusCodes::RuntimeException, + StatusCodes::RpcException, + StatusCodes::TransportException, + StatusCodes::ProtocolException, + StatusCodes::DegradeException, + StatusCodes::SecurityException, + StatusCodes::ServiceException, + StatusCodes::RemoteException +}; +const char* _kStatusCodesNames[] = { + "Success", + "ApplicationException", + "RuntimeException", + "RpcException", + "TransportException", + "ProtocolException", + "DegradeException", + "SecurityException", + "ServiceException", + "RemoteException" +}; +const std::map _StatusCodes_VALUES_TO_NAMES(::apache::thrift::TEnumIterator(10, _kStatusCodesValues, _kStatusCodesNames), ::apache::thrift::TEnumIterator(-1, NULL, NULL)); + +const char* RequestInfo::ascii_fingerprint = "59AD75927B39FBAC91B35C663FDB29CD"; +const uint8_t RequestInfo::binary_fingerprint[16] = {0x59,0xAD,0x75,0x92,0x7B,0x39,0xFB,0xAC,0x91,0xB3,0x5C,0x66,0x3F,0xDB,0x29,0xCD}; + +uint32_t RequestInfo::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + bool isset_serviceName = false; + bool isset_sequenceId = false; + bool isset_callType = false; + bool isset_timeout = false; + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->serviceName); + isset_serviceName = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->sequenceId); + isset_sequenceId = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_BYTE) { + xfer += iprot->readByte(this->callType); + isset_callType = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->timeout); + isset_timeout = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + if (!isset_serviceName) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_sequenceId) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_callType) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_timeout) + throw TProtocolException(TProtocolException::INVALID_DATA); + return xfer; +} + +uint32_t RequestInfo::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("RequestInfo"); + xfer += oprot->writeFieldBegin("serviceName", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->serviceName); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("sequenceId", ::apache::thrift::protocol::T_I64, 2); + xfer += oprot->writeI64(this->sequenceId); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("callType", ::apache::thrift::protocol::T_BYTE, 3); + xfer += oprot->writeByte(this->callType); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("timeout", ::apache::thrift::protocol::T_I32, 4); + xfer += oprot->writeI32(this->timeout); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* ResponseInfo::ascii_fingerprint = "C6D3CA4A6A1EB8E865A6A00B60176AA8"; +const uint8_t ResponseInfo::binary_fingerprint[16] = {0xC6,0xD3,0xCA,0x4A,0x6A,0x1E,0xB8,0xE8,0x65,0xA6,0xA0,0x0B,0x60,0x17,0x6A,0xA8}; + +uint32_t ResponseInfo::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + bool isset_sequenceId = false; + bool isset_status = false; + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->sequenceId); + isset_sequenceId = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_BYTE) { + xfer += iprot->readByte(this->status); + isset_status = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->message); + this->__isset.message = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + if (!isset_sequenceId) + throw TProtocolException(TProtocolException::INVALID_DATA); + if (!isset_status) + throw TProtocolException(TProtocolException::INVALID_DATA); + return xfer; +} + +uint32_t ResponseInfo::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("ResponseInfo"); + xfer += oprot->writeFieldBegin("sequenceId", ::apache::thrift::protocol::T_I64, 1); + xfer += oprot->writeI64(this->sequenceId); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("status", ::apache::thrift::protocol::T_BYTE, 2); + xfer += oprot->writeByte(this->status); + xfer += oprot->writeFieldEnd(); + if (this->__isset.message) { + xfer += oprot->writeFieldBegin("message", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString(this->message); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* TraceInfo::ascii_fingerprint = "ABB2B5AA298E9052ED1A5DE871EF9527"; +const uint8_t TraceInfo::binary_fingerprint[16] = {0xAB,0xB2,0xB5,0xAA,0x29,0x8E,0x90,0x52,0xED,0x1A,0x5D,0xE8,0x71,0xEF,0x95,0x27}; + +uint32_t TraceInfo::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + bool isset_clientAppkey = false; + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->clientAppkey); + isset_clientAppkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->traceId); + this->__isset.traceId = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->spanId); + this->__isset.spanId = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->rootMessageId); + this->__isset.rootMessageId = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 5: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->currentMessageId); + this->__isset.currentMessageId = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 6: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->serverMessageId); + this->__isset.serverMessageId = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 7: + if (ftype == ::apache::thrift::protocol::T_BOOL) { + xfer += iprot->readBool(this->debug); + this->__isset.debug = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 8: + if (ftype == ::apache::thrift::protocol::T_BOOL) { + xfer += iprot->readBool(this->sample); + this->__isset.sample = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 9: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->clientIp); + this->__isset.clientIp = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + if (!isset_clientAppkey) + throw TProtocolException(TProtocolException::INVALID_DATA); + return xfer; +} + +uint32_t TraceInfo::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("TraceInfo"); + xfer += oprot->writeFieldBegin("clientAppkey", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->clientAppkey); + xfer += oprot->writeFieldEnd(); + if (this->__isset.traceId) { + xfer += oprot->writeFieldBegin("traceId", ::apache::thrift::protocol::T_STRING, 2); + xfer += oprot->writeString(this->traceId); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.spanId) { + xfer += oprot->writeFieldBegin("spanId", ::apache::thrift::protocol::T_STRING, 3); + xfer += oprot->writeString(this->spanId); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.rootMessageId) { + xfer += oprot->writeFieldBegin("rootMessageId", ::apache::thrift::protocol::T_STRING, 4); + xfer += oprot->writeString(this->rootMessageId); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.currentMessageId) { + xfer += oprot->writeFieldBegin("currentMessageId", ::apache::thrift::protocol::T_STRING, 5); + xfer += oprot->writeString(this->currentMessageId); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.serverMessageId) { + xfer += oprot->writeFieldBegin("serverMessageId", ::apache::thrift::protocol::T_STRING, 6); + xfer += oprot->writeString(this->serverMessageId); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.debug) { + xfer += oprot->writeFieldBegin("debug", ::apache::thrift::protocol::T_BOOL, 7); + xfer += oprot->writeBool(this->debug); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.sample) { + xfer += oprot->writeFieldBegin("sample", ::apache::thrift::protocol::T_BOOL, 8); + xfer += oprot->writeBool(this->sample); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.clientIp) { + xfer += oprot->writeFieldBegin("clientIp", ::apache::thrift::protocol::T_STRING, 9); + xfer += oprot->writeString(this->clientIp); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* LoadInfo::ascii_fingerprint = "F424555CA1CEF935A4729C49DC664047"; +const uint8_t LoadInfo::binary_fingerprint[16] = {0xF4,0x24,0x55,0x5C,0xA1,0xCE,0xF9,0x35,0xA4,0x72,0x9C,0x49,0xDC,0x66,0x40,0x47}; + +uint32_t LoadInfo::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_DOUBLE) { + xfer += iprot->readDouble(this->averageLoad); + this->__isset.averageLoad = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->oldGC); + this->__isset.oldGC = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->threadNum); + this->__isset.threadNum = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->queueSize); + this->__isset.queueSize = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 5: + if (ftype == ::apache::thrift::protocol::T_MAP) { + { + this->methodQpsMap.clear(); + uint32_t _size0; + ::apache::thrift::protocol::TType _ktype1; + ::apache::thrift::protocol::TType _vtype2; + iprot->readMapBegin(_ktype1, _vtype2, _size0); + uint32_t _i4; + for (_i4 = 0; _i4 < _size0; ++_i4) + { + std::string _key5; + xfer += iprot->readString(_key5); + double& _val6 = this->methodQpsMap[_key5]; + xfer += iprot->readDouble(_val6); + } + iprot->readMapEnd(); + } + this->__isset.methodQpsMap = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t LoadInfo::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("LoadInfo"); + if (this->__isset.averageLoad) { + xfer += oprot->writeFieldBegin("averageLoad", ::apache::thrift::protocol::T_DOUBLE, 1); + xfer += oprot->writeDouble(this->averageLoad); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.oldGC) { + xfer += oprot->writeFieldBegin("oldGC", ::apache::thrift::protocol::T_I32, 2); + xfer += oprot->writeI32(this->oldGC); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.threadNum) { + xfer += oprot->writeFieldBegin("threadNum", ::apache::thrift::protocol::T_I32, 3); + xfer += oprot->writeI32(this->threadNum); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.queueSize) { + xfer += oprot->writeFieldBegin("queueSize", ::apache::thrift::protocol::T_I32, 4); + xfer += oprot->writeI32(this->queueSize); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.methodQpsMap) { + xfer += oprot->writeFieldBegin("methodQpsMap", ::apache::thrift::protocol::T_MAP, 5); + { + xfer += oprot->writeMapBegin(::apache::thrift::protocol::T_STRING, ::apache::thrift::protocol::T_DOUBLE, static_cast(this->methodQpsMap.size())); + std::map ::const_iterator _iter7; + for (_iter7 = this->methodQpsMap.begin(); _iter7 != this->methodQpsMap.end(); ++_iter7) + { + xfer += oprot->writeString(_iter7->first); + xfer += oprot->writeDouble(_iter7->second); + } + xfer += oprot->writeMapEnd(); + } + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* HeartbeatInfo::ascii_fingerprint = "EF43E82D9230E1225E24787F74163831"; +const uint8_t HeartbeatInfo::binary_fingerprint[16] = {0xEF,0x43,0xE8,0x2D,0x92,0x30,0xE1,0x22,0x5E,0x24,0x78,0x7F,0x74,0x16,0x38,0x31}; + +uint32_t HeartbeatInfo::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + bool isset_status = false; + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(this->appkey); + this->__isset.appkey = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_I64) { + xfer += iprot->readI64(this->sendTime); + this->__isset.sendTime = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->loadInfo.read(iprot); + this->__isset.loadInfo = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_I32) { + xfer += iprot->readI32(this->status); + isset_status = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + if (!isset_status) + throw TProtocolException(TProtocolException::INVALID_DATA); + return xfer; +} + +uint32_t HeartbeatInfo::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("HeartbeatInfo"); + if (this->__isset.appkey) { + xfer += oprot->writeFieldBegin("appkey", ::apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(this->appkey); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.sendTime) { + xfer += oprot->writeFieldBegin("sendTime", ::apache::thrift::protocol::T_I64, 2); + xfer += oprot->writeI64(this->sendTime); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.loadInfo) { + xfer += oprot->writeFieldBegin("loadInfo", ::apache::thrift::protocol::T_STRUCT, 3); + xfer += this->loadInfo.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldBegin("status", ::apache::thrift::protocol::T_I32, 4); + xfer += oprot->writeI32(this->status); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +const char* Header::ascii_fingerprint = "449EC0AD8F982561B4D899B14FB0084B"; +const uint8_t Header::binary_fingerprint[16] = {0x44,0x9E,0xC0,0xAD,0x8F,0x98,0x25,0x61,0xB4,0xD8,0x99,0xB1,0x4F,0xB0,0x08,0x4B}; + +uint32_t Header::read(::apache::thrift::protocol::TProtocol* iprot) { + + uint32_t xfer = 0; + std::string fname; + ::apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + using ::apache::thrift::protocol::TProtocolException; + + + while (true) + { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == ::apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) + { + case 1: + if (ftype == ::apache::thrift::protocol::T_BYTE) { + xfer += iprot->readByte(this->messageType); + this->__isset.messageType = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->requestInfo.read(iprot); + this->__isset.requestInfo = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 3: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->responseInfo.read(iprot); + this->__isset.responseInfo = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 4: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->traceInfo.read(iprot); + this->__isset.traceInfo = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 5: + if (ftype == ::apache::thrift::protocol::T_MAP) { + { + this->globalContext.clear(); + uint32_t _size8; + ::apache::thrift::protocol::TType _ktype9; + ::apache::thrift::protocol::TType _vtype10; + iprot->readMapBegin(_ktype9, _vtype10, _size8); + uint32_t _i12; + for (_i12 = 0; _i12 < _size8; ++_i12) + { + std::string _key13; + xfer += iprot->readString(_key13); + std::string& _val14 = this->globalContext[_key13]; + xfer += iprot->readString(_val14); + } + iprot->readMapEnd(); + } + this->__isset.globalContext = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 6: + if (ftype == ::apache::thrift::protocol::T_MAP) { + { + this->localContext.clear(); + uint32_t _size15; + ::apache::thrift::protocol::TType _ktype16; + ::apache::thrift::protocol::TType _vtype17; + iprot->readMapBegin(_ktype16, _vtype17, _size15); + uint32_t _i19; + for (_i19 = 0; _i19 < _size15; ++_i19) + { + std::string _key20; + xfer += iprot->readString(_key20); + std::string& _val21 = this->localContext[_key20]; + xfer += iprot->readString(_val21); + } + iprot->readMapEnd(); + } + this->__isset.localContext = true; + } else { + xfer += iprot->skip(ftype); + } + break; + case 7: + if (ftype == ::apache::thrift::protocol::T_STRUCT) { + xfer += this->heartbeatInfo.read(iprot); + this->__isset.heartbeatInfo = true; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + + return xfer; +} + +uint32_t Header::write(::apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("Header"); + if (this->__isset.messageType) { + xfer += oprot->writeFieldBegin("messageType", ::apache::thrift::protocol::T_BYTE, 1); + xfer += oprot->writeByte(this->messageType); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.requestInfo) { + xfer += oprot->writeFieldBegin("requestInfo", ::apache::thrift::protocol::T_STRUCT, 2); + xfer += this->requestInfo.write(oprot); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.responseInfo) { + xfer += oprot->writeFieldBegin("responseInfo", ::apache::thrift::protocol::T_STRUCT, 3); + xfer += this->responseInfo.write(oprot); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.traceInfo) { + xfer += oprot->writeFieldBegin("traceInfo", ::apache::thrift::protocol::T_STRUCT, 4); + xfer += this->traceInfo.write(oprot); + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.globalContext) { + xfer += oprot->writeFieldBegin("globalContext", ::apache::thrift::protocol::T_MAP, 5); + { + xfer += oprot->writeMapBegin(::apache::thrift::protocol::T_STRING, ::apache::thrift::protocol::T_STRING, static_cast(this->globalContext.size())); + std::map ::const_iterator _iter22; + for (_iter22 = this->globalContext.begin(); _iter22 != this->globalContext.end(); ++_iter22) + { + xfer += oprot->writeString(_iter22->first); + xfer += oprot->writeString(_iter22->second); + } + xfer += oprot->writeMapEnd(); + } + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.localContext) { + xfer += oprot->writeFieldBegin("localContext", ::apache::thrift::protocol::T_MAP, 6); + { + xfer += oprot->writeMapBegin(::apache::thrift::protocol::T_STRING, ::apache::thrift::protocol::T_STRING, static_cast(this->localContext.size())); + std::map ::const_iterator _iter23; + for (_iter23 = this->localContext.begin(); _iter23 != this->localContext.end(); ++_iter23) + { + xfer += oprot->writeString(_iter23->first); + xfer += oprot->writeString(_iter23->second); + } + xfer += oprot->writeMapEnd(); + } + xfer += oprot->writeFieldEnd(); + } + if (this->__isset.heartbeatInfo) { + xfer += oprot->writeFieldBegin("heartbeatInfo", ::apache::thrift::protocol::T_STRUCT, 7); + xfer += this->heartbeatInfo.write(oprot); + xfer += oprot->writeFieldEnd(); + } + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +} // namespace diff --git a/common/gen-cpp/unified_protocol_types.h b/common/gen-cpp/unified_protocol_types.h new file mode 100644 index 0000000..df6a0cf --- /dev/null +++ b/common/gen-cpp/unified_protocol_types.h @@ -0,0 +1,582 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef unified_protocol_TYPES_H +#define unified_protocol_TYPES_H + +#include +#include +#include +#include + + + +namespace meituan_mns { + +struct MessageType { + enum type { + Normal = 0, + NormalHeartbeat = 1, + ScannerHeartbeat = 2 + }; +}; + +extern const std::map _MessageType_VALUES_TO_NAMES; + +struct CompressType { + enum type { + None = 0, + Snappy = 1, + Gzip = 2 + }; +}; + +extern const std::map _CompressType_VALUES_TO_NAMES; + +struct CallType { + enum type { + Reply = 0, + NoReply = 1 + }; +}; + +extern const std::map _CallType_VALUES_TO_NAMES; + +struct StatusCodes { + enum type { + Success = 0, + ApplicationException = 1, + RuntimeException = 2, + RpcException = 3, + TransportException = 4, + ProtocolException = 5, + DegradeException = 6, + SecurityException = 7, + ServiceException = 8, + RemoteException = 9 + }; +}; + +extern const std::map _StatusCodes_VALUES_TO_NAMES; + +typedef std::map Context; + + +class RequestInfo { + public: + + static const char* ascii_fingerprint; // = "59AD75927B39FBAC91B35C663FDB29CD"; + static const uint8_t binary_fingerprint[16]; // = {0x59,0xAD,0x75,0x92,0x7B,0x39,0xFB,0xAC,0x91,0xB3,0x5C,0x66,0x3F,0xDB,0x29,0xCD}; + + RequestInfo() : serviceName(""), sequenceId(0), callType(0), timeout(0) { + } + + virtual ~RequestInfo() throw() {} + + std::string serviceName; + int64_t sequenceId; + int8_t callType; + int32_t timeout; + + void __set_serviceName(const std::string& val) { + serviceName = val; + } + + void __set_sequenceId(const int64_t val) { + sequenceId = val; + } + + void __set_callType(const int8_t val) { + callType = val; + } + + void __set_timeout(const int32_t val) { + timeout = val; + } + + bool operator == (const RequestInfo & rhs) const + { + if (!(serviceName == rhs.serviceName)) + return false; + if (!(sequenceId == rhs.sequenceId)) + return false; + if (!(callType == rhs.callType)) + return false; + if (!(timeout == rhs.timeout)) + return false; + return true; + } + bool operator != (const RequestInfo &rhs) const { + return !(*this == rhs); + } + + bool operator < (const RequestInfo & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ResponseInfo__isset { + _ResponseInfo__isset() : message(false) {} + bool message; +} _ResponseInfo__isset; + +class ResponseInfo { + public: + + static const char* ascii_fingerprint; // = "C6D3CA4A6A1EB8E865A6A00B60176AA8"; + static const uint8_t binary_fingerprint[16]; // = {0xC6,0xD3,0xCA,0x4A,0x6A,0x1E,0xB8,0xE8,0x65,0xA6,0xA0,0x0B,0x60,0x17,0x6A,0xA8}; + + ResponseInfo() : sequenceId(0), status(0), message("") { + } + + virtual ~ResponseInfo() throw() {} + + int64_t sequenceId; + int8_t status; + std::string message; + + _ResponseInfo__isset __isset; + + void __set_sequenceId(const int64_t val) { + sequenceId = val; + } + + void __set_status(const int8_t val) { + status = val; + } + + void __set_message(const std::string& val) { + message = val; + __isset.message = true; + } + + bool operator == (const ResponseInfo & rhs) const + { + if (!(sequenceId == rhs.sequenceId)) + return false; + if (!(status == rhs.status)) + return false; + if (__isset.message != rhs.__isset.message) + return false; + else if (__isset.message && !(message == rhs.message)) + return false; + return true; + } + bool operator != (const ResponseInfo &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ResponseInfo & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _TraceInfo__isset { + _TraceInfo__isset() : traceId(false), spanId(false), rootMessageId(false), currentMessageId(false), serverMessageId(false), debug(false), sample(false), clientIp(false) {} + bool traceId; + bool spanId; + bool rootMessageId; + bool currentMessageId; + bool serverMessageId; + bool debug; + bool sample; + bool clientIp; +} _TraceInfo__isset; + +class TraceInfo { + public: + + static const char* ascii_fingerprint; // = "ABB2B5AA298E9052ED1A5DE871EF9527"; + static const uint8_t binary_fingerprint[16]; // = {0xAB,0xB2,0xB5,0xAA,0x29,0x8E,0x90,0x52,0xED,0x1A,0x5D,0xE8,0x71,0xEF,0x95,0x27}; + + TraceInfo() : clientAppkey(""), traceId(""), spanId(""), rootMessageId(""), currentMessageId(""), serverMessageId(""), debug(0), sample(0), clientIp("") { + } + + virtual ~TraceInfo() throw() {} + + std::string clientAppkey; + std::string traceId; + std::string spanId; + std::string rootMessageId; + std::string currentMessageId; + std::string serverMessageId; + bool debug; + bool sample; + std::string clientIp; + + _TraceInfo__isset __isset; + + void __set_clientAppkey(const std::string& val) { + clientAppkey = val; + } + + void __set_traceId(const std::string& val) { + traceId = val; + __isset.traceId = true; + } + + void __set_spanId(const std::string& val) { + spanId = val; + __isset.spanId = true; + } + + void __set_rootMessageId(const std::string& val) { + rootMessageId = val; + __isset.rootMessageId = true; + } + + void __set_currentMessageId(const std::string& val) { + currentMessageId = val; + __isset.currentMessageId = true; + } + + void __set_serverMessageId(const std::string& val) { + serverMessageId = val; + __isset.serverMessageId = true; + } + + void __set_debug(const bool val) { + debug = val; + __isset.debug = true; + } + + void __set_sample(const bool val) { + sample = val; + __isset.sample = true; + } + + void __set_clientIp(const std::string& val) { + clientIp = val; + __isset.clientIp = true; + } + + bool operator == (const TraceInfo & rhs) const + { + if (!(clientAppkey == rhs.clientAppkey)) + return false; + if (__isset.traceId != rhs.__isset.traceId) + return false; + else if (__isset.traceId && !(traceId == rhs.traceId)) + return false; + if (__isset.spanId != rhs.__isset.spanId) + return false; + else if (__isset.spanId && !(spanId == rhs.spanId)) + return false; + if (__isset.rootMessageId != rhs.__isset.rootMessageId) + return false; + else if (__isset.rootMessageId && !(rootMessageId == rhs.rootMessageId)) + return false; + if (__isset.currentMessageId != rhs.__isset.currentMessageId) + return false; + else if (__isset.currentMessageId && !(currentMessageId == rhs.currentMessageId)) + return false; + if (__isset.serverMessageId != rhs.__isset.serverMessageId) + return false; + else if (__isset.serverMessageId && !(serverMessageId == rhs.serverMessageId)) + return false; + if (__isset.debug != rhs.__isset.debug) + return false; + else if (__isset.debug && !(debug == rhs.debug)) + return false; + if (__isset.sample != rhs.__isset.sample) + return false; + else if (__isset.sample && !(sample == rhs.sample)) + return false; + if (__isset.clientIp != rhs.__isset.clientIp) + return false; + else if (__isset.clientIp && !(clientIp == rhs.clientIp)) + return false; + return true; + } + bool operator != (const TraceInfo &rhs) const { + return !(*this == rhs); + } + + bool operator < (const TraceInfo & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _LoadInfo__isset { + _LoadInfo__isset() : averageLoad(false), oldGC(false), threadNum(false), queueSize(false), methodQpsMap(false) {} + bool averageLoad; + bool oldGC; + bool threadNum; + bool queueSize; + bool methodQpsMap; +} _LoadInfo__isset; + +class LoadInfo { + public: + + static const char* ascii_fingerprint; // = "F424555CA1CEF935A4729C49DC664047"; + static const uint8_t binary_fingerprint[16]; // = {0xF4,0x24,0x55,0x5C,0xA1,0xCE,0xF9,0x35,0xA4,0x72,0x9C,0x49,0xDC,0x66,0x40,0x47}; + + LoadInfo() : averageLoad(0), oldGC(0), threadNum(0), queueSize(0) { + } + + virtual ~LoadInfo() throw() {} + + double averageLoad; + int32_t oldGC; + int32_t threadNum; + int32_t queueSize; + std::map methodQpsMap; + + _LoadInfo__isset __isset; + + void __set_averageLoad(const double val) { + averageLoad = val; + __isset.averageLoad = true; + } + + void __set_oldGC(const int32_t val) { + oldGC = val; + __isset.oldGC = true; + } + + void __set_threadNum(const int32_t val) { + threadNum = val; + __isset.threadNum = true; + } + + void __set_queueSize(const int32_t val) { + queueSize = val; + __isset.queueSize = true; + } + + void __set_methodQpsMap(const std::map & val) { + methodQpsMap = val; + __isset.methodQpsMap = true; + } + + bool operator == (const LoadInfo & rhs) const + { + if (__isset.averageLoad != rhs.__isset.averageLoad) + return false; + else if (__isset.averageLoad && !(averageLoad == rhs.averageLoad)) + return false; + if (__isset.oldGC != rhs.__isset.oldGC) + return false; + else if (__isset.oldGC && !(oldGC == rhs.oldGC)) + return false; + if (__isset.threadNum != rhs.__isset.threadNum) + return false; + else if (__isset.threadNum && !(threadNum == rhs.threadNum)) + return false; + if (__isset.queueSize != rhs.__isset.queueSize) + return false; + else if (__isset.queueSize && !(queueSize == rhs.queueSize)) + return false; + if (__isset.methodQpsMap != rhs.__isset.methodQpsMap) + return false; + else if (__isset.methodQpsMap && !(methodQpsMap == rhs.methodQpsMap)) + return false; + return true; + } + bool operator != (const LoadInfo &rhs) const { + return !(*this == rhs); + } + + bool operator < (const LoadInfo & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _HeartbeatInfo__isset { + _HeartbeatInfo__isset() : appkey(false), sendTime(false), loadInfo(false) {} + bool appkey; + bool sendTime; + bool loadInfo; +} _HeartbeatInfo__isset; + +class HeartbeatInfo { + public: + + static const char* ascii_fingerprint; // = "EF43E82D9230E1225E24787F74163831"; + static const uint8_t binary_fingerprint[16]; // = {0xEF,0x43,0xE8,0x2D,0x92,0x30,0xE1,0x22,0x5E,0x24,0x78,0x7F,0x74,0x16,0x38,0x31}; + + HeartbeatInfo() : appkey(""), sendTime(0), status(0) { + } + + virtual ~HeartbeatInfo() throw() {} + + std::string appkey; + int64_t sendTime; + LoadInfo loadInfo; + int32_t status; + + _HeartbeatInfo__isset __isset; + + void __set_appkey(const std::string& val) { + appkey = val; + __isset.appkey = true; + } + + void __set_sendTime(const int64_t val) { + sendTime = val; + __isset.sendTime = true; + } + + void __set_loadInfo(const LoadInfo& val) { + loadInfo = val; + __isset.loadInfo = true; + } + + void __set_status(const int32_t val) { + status = val; + } + + bool operator == (const HeartbeatInfo & rhs) const + { + if (__isset.appkey != rhs.__isset.appkey) + return false; + else if (__isset.appkey && !(appkey == rhs.appkey)) + return false; + if (__isset.sendTime != rhs.__isset.sendTime) + return false; + else if (__isset.sendTime && !(sendTime == rhs.sendTime)) + return false; + if (__isset.loadInfo != rhs.__isset.loadInfo) + return false; + else if (__isset.loadInfo && !(loadInfo == rhs.loadInfo)) + return false; + if (!(status == rhs.status)) + return false; + return true; + } + bool operator != (const HeartbeatInfo &rhs) const { + return !(*this == rhs); + } + + bool operator < (const HeartbeatInfo & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _Header__isset { + _Header__isset() : messageType(false), requestInfo(false), responseInfo(false), traceInfo(false), globalContext(false), localContext(false), heartbeatInfo(false) {} + bool messageType; + bool requestInfo; + bool responseInfo; + bool traceInfo; + bool globalContext; + bool localContext; + bool heartbeatInfo; +} _Header__isset; + +class Header { + public: + + static const char* ascii_fingerprint; // = "449EC0AD8F982561B4D899B14FB0084B"; + static const uint8_t binary_fingerprint[16]; // = {0x44,0x9E,0xC0,0xAD,0x8F,0x98,0x25,0x61,0xB4,0xD8,0x99,0xB1,0x4F,0xB0,0x08,0x4B}; + + Header() : messageType(0) { + } + + virtual ~Header() throw() {} + + int8_t messageType; + RequestInfo requestInfo; + ResponseInfo responseInfo; + TraceInfo traceInfo; + Context globalContext; + Context localContext; + HeartbeatInfo heartbeatInfo; + + _Header__isset __isset; + + void __set_messageType(const int8_t val) { + messageType = val; + __isset.messageType = true; + } + + void __set_requestInfo(const RequestInfo& val) { + requestInfo = val; + __isset.requestInfo = true; + } + + void __set_responseInfo(const ResponseInfo& val) { + responseInfo = val; + __isset.responseInfo = true; + } + + void __set_traceInfo(const TraceInfo& val) { + traceInfo = val; + __isset.traceInfo = true; + } + + void __set_globalContext(const Context& val) { + globalContext = val; + __isset.globalContext = true; + } + + void __set_localContext(const Context& val) { + localContext = val; + __isset.localContext = true; + } + + void __set_heartbeatInfo(const HeartbeatInfo& val) { + heartbeatInfo = val; + __isset.heartbeatInfo = true; + } + + bool operator == (const Header & rhs) const + { + if (__isset.messageType != rhs.__isset.messageType) + return false; + else if (__isset.messageType && !(messageType == rhs.messageType)) + return false; + if (__isset.requestInfo != rhs.__isset.requestInfo) + return false; + else if (__isset.requestInfo && !(requestInfo == rhs.requestInfo)) + return false; + if (__isset.responseInfo != rhs.__isset.responseInfo) + return false; + else if (__isset.responseInfo && !(responseInfo == rhs.responseInfo)) + return false; + if (__isset.traceInfo != rhs.__isset.traceInfo) + return false; + else if (__isset.traceInfo && !(traceInfo == rhs.traceInfo)) + return false; + if (__isset.globalContext != rhs.__isset.globalContext) + return false; + else if (__isset.globalContext && !(globalContext == rhs.globalContext)) + return false; + if (__isset.localContext != rhs.__isset.localContext) + return false; + else if (__isset.localContext && !(localContext == rhs.localContext)) + return false; + if (__isset.heartbeatInfo != rhs.__isset.heartbeatInfo) + return false; + else if (__isset.heartbeatInfo && !(heartbeatInfo == rhs.heartbeatInfo)) + return false; + return true; + } + bool operator != (const Header &rhs) const { + return !(*this == rhs); + } + + bool operator < (const Header & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +} // namespace + +#endif diff --git a/common/idl-mns/idl-common/Compile.md b/common/idl-mns/idl-common/Compile.md new file mode 100644 index 0000000..35f5ffa --- /dev/null +++ b/common/idl-mns/idl-common/Compile.md @@ -0,0 +1,26 @@ + +# idl-common 源码编译说明 + +## 1.下载工程 +``` + git clone https://github.com/Meituan-Dianping/octo-ns.git +``` + +## 2.构建Jar包 +环境要求: + +- Java version >= 1.8 +- Maven version >= 3.2 + +切换到idl-common目录 + +``` +cd common/idl-mns/idl-common +``` + +本地install,执行后在本地仓库~/.m2/repository/com/meituan/octo/idl-common/(假如你的仓库位置是~/.m2/repository)下可以找到idl-common的jar + +``` +# common/idl-mns/idl-common 目录下 +mvn clean install -Dmaven.test.skip=true +``` diff --git a/common/idl-mns/idl-common/pom.xml b/common/idl-mns/idl-common/pom.xml new file mode 100644 index 0000000..b391482 --- /dev/null +++ b/common/idl-mns/idl-common/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + com.meituan.octo + idl-common + 1.0.0 + jar + + + org.apache.thrift + libthrift + + 0.9.3 + + + + + + org.apache.thrift.tools + maven-thrift-plugin + 0.1.11 + + + /usr/local/bin/thrift + + + + thrift-sources + generate-sources + + compile + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + attach-sources + package + + jar-no-fork + test-jar-no-fork + + + + + + + diff --git a/common/idl-mns/idl-common/src/main/thrift/idc.thrift b/common/idl-mns/idl-common/src/main/thrift/idc.thrift new file mode 100644 index 0000000..841eb77 --- /dev/null +++ b/common/idl-mns/idl-common/src/main/thrift/idc.thrift @@ -0,0 +1,23 @@ +/* + * Copyright 2018 Meituan Dianping. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace java com.octo.idc.model + +struct Idc { + 1:string region; + 2:string idc; + 3:optional string center; +} diff --git a/common/idl-mns/idl-common/src/main/thrift/naming_common.thrift b/common/idl-mns/idl-common/src/main/thrift/naming_common.thrift new file mode 100644 index 0000000..ef67a02 --- /dev/null +++ b/common/idl-mns/idl-common/src/main/thrift/naming_common.thrift @@ -0,0 +1,130 @@ +/* + * Copyright 2018 Meituan Dianping. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace java com.octo.naming.common.thrift.model +namespace cpp meituan_mns +enum UptCmd { + RESET = 0, + ADD = 1, + DELETE = 2, +} +/** + * Common status reporting mechanism across all services + */ +enum fb_status { + DEAD = 0,//宕机,故障 + STARTING = 1,//启动中 + ALIVE = 2,//正常 + STOPPING = 3,//正在下线 + STOPPED = 4,//禁用 + WARNING = 5,//警告 +} +enum HeartbeatSupportType { + NoSupport = 0, + P2POnly = 1, + ScannerOnly = 2, + BothSupport = 3, +} +struct ServiceDetail { + 1:bool unifiedProto; //默认为false,true代表支持统一协议 +} + +struct SGService +{ + 1:string appkey; + 2:string version; + 3:string ip; + 4:i32 port; + 5:i32 weight; + 6:i32 status; //正常状态,重启状态,下线状态,故障状态,具体值参考fb_status + 7:i32 role; //backup角色,当其他服务无法服务的时候,启用backup状态;0(主)1(备) + 8:i32 envir; //运行环境,prod(线上环境3),stag(线上测试环境2),test(测试环境1) + 9:i32 lastUpdateTime; //最后修改时间 + 10:double fweight; //浮点型权重 + 11:i32 serverType; //用于区分http(1)和thrift(0) + 12:string protocol; //支持扩展协议 + 13:map serviceInfo; //serviceName 到 servcieDetail的映射 + 14:byte heartbeatSupport; //0:不支持心跳, 1:仅支持端对端心跳 2:仅支持scanner心跳 3:两种心跳都支持 + 15:i32 warmup; //节点预热时间,单位秒 +} +/* + * 服务节点, 主要储存服务->appkey映射 + */ +struct ServiceNode +{ + 1:string serviceName; + 2:set appkeys; //serviceName对应的appkey + 3:i32 lastUpdateTime; //最后修改时间 +} +/* + * 服务分组,consumer定义 + */ +struct Consumer +{ + 1:list ips; + 2:list appkeys; +} + +/* + * 服务分组定义 + */ +struct CRouteData +{ + 1:string id; + 2:string name; + 3:string appkey; + 4:i32 env; + 5:i32 category; + 6:i32 priority; + 7:i32 status; //服务分组,0:禁用,1:启用 + 8:Consumer consumer; + 9:list provider; + 10:i32 updateTime; //最后修改时间 + 11:i32 createTime; //最后修改时间 + 12:string reserved; //扩展 k1:v1|k2:v2... +} +/* + * 路由分组中provider节点信息 + */ +struct CProviderNode +{ + 1:string appkey; + 2:i64 lastModifiedTime; + 3:i64 mtime; + 4:i64 cversion; + 5:i64 version; +} +/* + * 路由分组中route根节点结构 + */ +struct CRouteNode +{ + 1:string appkey; + 2:i64 lastModifiedTime; + 3:i64 mtime; + 4:i64 cversion; + 5:i64 version; +} +struct ProtocolRequest { + 1:string localAppkey; + 2:string remoteAppkey; + 3:string protocol; + 4:string serviceName; +} +struct ProtocolResponse { + 1:i32 errcode; + 2:list servicelist; +} diff --git a/common/idl-mns/idl-common/src/main/thrift/naming_data.thrift b/common/idl-mns/idl-common/src/main/thrift/naming_data.thrift new file mode 100644 index 0000000..05ed505 --- /dev/null +++ b/common/idl-mns/idl-common/src/main/thrift/naming_data.thrift @@ -0,0 +1,78 @@ +/* + * Copyright 2018 Meituan Dianping. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace java com.octo.data.thrift.model +namespace cpp meituan_mns + +include "naming_common.thrift" +typedef naming_common.SGService SGService +typedef naming_common.CRouteData CRouteData +enum RegistCmd { + REGIST = 0, + UNREGIST = 1 +} +struct getservice_req_param_t +{ + 1:string localAppkey; + 2:string remoteAppkey; + 3:string version; + 4:string protocol; +} +struct getservice_res_param_t +{ + 1:string localAppkey; + 2:string remoteAppkey; + 3:string version; + 4:list serviceList; + 5:string protocol; +} +struct getservicename_req_param_t +{ + 1:string localAppkey; + 2:string servicename; + 3:string version; + 4:string protocol; +} +struct getservicename_res_param_t +{ + 1:string localAppkey; + 2:string servicename; + 3:string version; + 4:set appkeys; + 5:string protocol; +} +struct getroute_req_param_t +{ + 1:string localAppkey; + 2:string remoteAppkey; + 3:string version; + 4:string protocol; +} +struct getroute_res_param_t +{ + 1:string localAppkey; + 2:string remoteAppkey; + 3:string version; + 4:list routeList; + 5:string protocol; +} +struct regist_req_param_t +{ + 1:i32 retry_times = 0; + 2:SGService sgservice; + 3:i32 uptCmd; + 4:RegistCmd regCmd; +} diff --git a/common/idl-mns/idl-common/src/main/thrift/naming_service.thrift b/common/idl-mns/idl-common/src/main/thrift/naming_service.thrift new file mode 100644 index 0000000..ccd4689 --- /dev/null +++ b/common/idl-mns/idl-common/src/main/thrift/naming_service.thrift @@ -0,0 +1,51 @@ +/* + * Copyright 2018 Meituan Dianping. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace java com.octo.naming.service.thrift.model +namespace cpp meituan_mns + +include "naming_common.thrift" +typedef naming_common.SGService SGService +typedef naming_common.ProtocolRequest ProtocolRequest +typedef naming_common.ProtocolResponse ProtocolResponse +/** + * Common status reporting mechanism across all services + */ +service ServiceAgent +{ + /* + * 新增协议获取服务列表的接口 + */ + ProtocolResponse getServiceListByProtocol(1:ProtocolRequest req); + // 获取zk全部节点的接口 + ProtocolResponse getOriginServiceList(1:ProtocolRequest req); + /* + *服务注册 + */ + i32 registService(1:SGService oService); + + /* + * 注册服务 + * uptCmd:0,重置(代表后面的serviceName list就是该应用支持的全量接口); + * 1,增加(代表后面的serviceName list是该应用新增的接口); + * 2,减少(代表后面的serviceName list是该应用删除的接口)。 + */ + i32 registServicewithCmd(1:i32 uptCmd, 2:SGService oService); + /* + *服务注销 + */ + i32 unRegistService(1:SGService oService); +} diff --git a/common/idl-mns/idl-common/src/main/thrift/unified_protocol.thrift b/common/idl-mns/idl-common/src/main/thrift/unified_protocol.thrift new file mode 100644 index 0000000..b75db8f --- /dev/null +++ b/common/idl-mns/idl-common/src/main/thrift/unified_protocol.thrift @@ -0,0 +1,103 @@ +/* + * Copyright 2018 Meituan Dianping. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace java com.octo.unified.protocol +namespace cpp meituan_mns + +enum MessageType { // 消息类型 + Normal = 0, // 正常消息 + NormalHeartbeat = 1, // 端对端心跳消息 + ScannerHeartbeat = 2 //scanner心跳消息 +} + +enum CompressType { // 压缩类型 + None = 0, // 不压缩 + Snappy = 1, // Snappy + Gzip = 2 // Gzip +} + +struct RequestInfo { // 请求信息 + 1: required string serviceName; // 服务名 + 2: required i64 sequenceId; // 消息序列号 + 3: required byte callType; // 调用类型 + 4: required i32 timeout; // 请求超时时间 +} + +enum CallType { // 调用类型 + Reply = 0, // 需要响应 + NoReply = 1, // 不需要响应 +} + +struct ResponseInfo { // 响应信息 + 1: required i64 sequenceId; // 消息序列号 + 2: required byte status; // 消息返回状态 + 3: optional string message; //异常消息 +} + +enum StatusCodes{ + Success = 0, // 成功 + ApplicationException = 1, // 业务异常,业务接口方法定义抛出的异常 + RuntimeException = 2, // 运行时异常,一般由业务抛出 + RpcException = 3, // 框架异常,包含没有被下列异常覆盖到的框架异常 + TransportException = 4, // 传输异常 + ProtocolException = 5, // 协议异常 + DegradeException = 6, // 降级异常 + SecurityException = 7, // 安全异常 + ServiceException = 8, // 服务异常,如服务端找不到对应的服务或方法 + RemoteException = 9, // 远程异常 +} + + + +struct TraceInfo { // Mtrace 跟踪信息,原 MTthrift 中的 RequestHeader + 1: required string clientAppkey; // 客户端应用名 + 2: optional string traceId; // Mtrace 的 traceId + 3: optional string spanId; // Mtrace 的 spanId + 4: optional string rootMessageId; // Cat 的 rootMessageId + 5: optional string currentMessageId; // Cat 的 currentMessageId + 6: optional string serverMessageId; // Cat 的 serverMessageId + 7: optional bool debug; // 是否强制采样 + 8: optional bool sample; // 是否采样 + 9: optional string clientIp; // 客户端IP +} + + +struct LoadInfo{ + 1: optional double averageLoad; + 2: optional i32 oldGC; + 3: optional i32 threadNum; //默认线程池 + 4: optional i32 queueSize; //主IO线程队列长度 + 5: optional map methodQpsMap; //key为ServiceName.methodName,value为1分钟内的对应的qps值(key为all,value则为所有方法的qps) +} + +struct HeartbeatInfo { + 1: optional string appkey; // 解决重复注册,修改错误appkey状态的问题 + 2: optional i64 sendTime; // 发送心跳时间,微秒,方便业务剔除历史心跳 + 3: optional LoadInfo loadInfo; // 负载信息 + 4: required i32 status; // 0:DEAD(未启动), 2:ALIVE(正常),4:STOPPED(禁用) +} + +typedef map Context // 消息上下文,用于传递自定义数据 + +struct Header { // 消息头 + 1: optional byte messageType = MessageType.Normal; // 消息类型 + 2: optional RequestInfo requestInfo; // 请求信息 + 3: optional ResponseInfo responseInfo; // 响应信息 + 4: optional TraceInfo traceInfo; // 跟踪信息 + 5: optional Context globalContext; // 全链路消息上下文,总大小不超过 512 Bytes + 6: optional Context localContext; // 单次消息上下文,总大小不超过 2K Bytes + 7: optional HeartbeatInfo heartbeatInfo; // 心跳信息 +} diff --git a/common/idl-mns/idl-mnsc/Compile.md b/common/idl-mns/idl-mnsc/Compile.md new file mode 100644 index 0000000..7de0605 --- /dev/null +++ b/common/idl-mns/idl-mnsc/Compile.md @@ -0,0 +1,28 @@ + +# idl-mnsc 源码编译说明 + +## 1.下载工程 +``` + git clone https://github.com/Meituan-Dianping/octo-ns.git +``` + +## 2.构建Jar包 +环境要求: + +- Java version >= 1.8 +- Maven version >= 3.2 + +切换到idl-mnsc目录 + +``` +cd common/idl-mns/idl-mnsc +``` + +本地install,执行后在本地仓库~/.m2/repository/com/meituan/octo/idl-mnsc/(假如你的仓库位置是~/.m2/repository)下可以找到idl-mnsc的jar + +``` +# common/idl-mns/idl-mnsc 目录下 +mvn clean install -Dmaven.test.skip=true +``` + +``` diff --git a/common/idl-mns/idl-mnsc/pom.xml b/common/idl-mns/idl-mnsc/pom.xml new file mode 100644 index 0000000..43c9514 --- /dev/null +++ b/common/idl-mns/idl-mnsc/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + com.meituan.octo + idl-mnsc + 1.0.0 + jar + + + com.meituan.octo + idl-common + 1.0.0 + + + org.apache.thrift + + libthrift + 0.9.3 + + + + + + org.apache.thrift.tools + maven-thrift-plugin + 0.1.11 + + + /usr/local/bin/thrift + + + + thrift-sources + generate-sources + + compile + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + attach-sources + package + + jar-no-fork + test-jar-no-fork + + + + + + + diff --git a/common/idl-mns/idl-mnsc/src/main/thrift/mnsc_data.thrift b/common/idl-mns/idl-mnsc/src/main/thrift/mnsc_data.thrift new file mode 100644 index 0000000..3cd463b --- /dev/null +++ b/common/idl-mns/idl-mnsc/src/main/thrift/mnsc_data.thrift @@ -0,0 +1,89 @@ +/* + * Copyright 2018 Meituan Dianping. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace java com.octo.mnsc.idl.thrift.model +namespace cpp meituan_mns +include "../../../../idl-common/src/main/thrift/naming_common.thrift" +typedef naming_common.SGService SGService +struct MNSResponse { + /* + * 状态码,200: 正常返回200;如果version不同,MNSCache正在更新时,先直接返回500; 400: 访问MNS请求超时 + */ + 1 : required i32 code = 200; + /* + * 节点列表,code = 200时,必须返回的字段 + */ + 2 : optional list defaultMNSCache; + /* + * 版本信息 + */ + 3 : optional string version; //正常返回时,附带上version信息 +} +// for scanner +struct MNSBatchResponse { + /* + * 状态码,200: 正常返回200;如果version不同,MNSCache正在更新时,先直接返回500; 400: 访问MNS请求超时 + */ + 1 : required i32 code = 200; + /* + * appkey->(env->detail) + */ + 2 : optional map>> cache; +} +struct AppKeyListResponse { + /* + * 状态码,200: 正常返回;400: 访问MNS请求超时; + */ + 1 : required i32 code = 200; + /* + * 服务appkey列表 + */ + 2 : optional list appKeyList; +} +enum Protocols{ + THRIFT, + HTTP +} +struct MnsRequest{ + 1: Protocols protoctol; + 2: string appkey; + 3: string env; +} +//环境的名字 +const string PROD = "prod"; +const string STAGE = "stage"; +const string TEST = "test"; +/** +* 异常错误定义 +**/ +/** +* 正常服务 +**/ +const i32 SUCCESS = 200; +/** +* 如果version不同,MNSCache正在更新时,先直接返回500 +**/ +const i32 MNSCache_UPDATE = 500; +/** +* 超时异常 +**/ +const i32 TIMEOUT_ERROR = 400; +//参数错误 +const i32 ILLEGAL_ARGUMENT = 400; +//请求的缓存不存在 +const i32 NOT_FOUND = 404 +//缓存没有变化 +const i32 NOT_MODIFIED = 304 diff --git a/common/idl-mns/idl-mnsc/src/main/thrift/mnsc_service.thrift b/common/idl-mns/idl-mnsc/src/main/thrift/mnsc_service.thrift new file mode 100644 index 0000000..c5bff72 --- /dev/null +++ b/common/idl-mns/idl-mnsc/src/main/thrift/mnsc_service.thrift @@ -0,0 +1,63 @@ +/* + * Copyright 2018 Meituan Dianping. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace java com.octo.mnsc.idl.thrift.service +namespace cpp meituan_mns +include "mnsc_data.thrift" +typedef mnsc_data.MNSResponse MNSResponse +typedef mnsc_data.MNSBatchResponse MNSBatchResponse +typedef mnsc_data.AppKeyListResponse AppKeyListResponse +typedef mnsc_data.MnsRequest MnsRequest +typedef mnsc_data.SGService SGService +service MNSCacheService { + /** + * @param appkey 服务标识 + * @param version 版本 + * @param env 环境 + * @return 服务的节点列表 + * @name 获取服务的节点列表 + */ + MNSResponse getMNSCache(1:string appkey, 2:string version, 3:string env); + /** + * @param appkey 服务标识 + * @param version 版本 + * @param env 环境 + * @return 服务的HLB节点列表 + * @name 获取服务的HLB节点列表 + */ + MNSResponse getMNSCacheHttp(1:string appkey, 2:string version, 3:string env); + /** + * @param req 请求结构体 + * @name 获取服务的节点列表; 获取时, 会将缓存中的version与zk上的version进行比较,如果不相等,则重新更新缓存后,再返回数据。 + */ + MNSResponse getMNSCacheWithVersionCheck(1:MnsRequest req); + /** + * @param appkeys 请求的appkey列表 + * @param protocol + */ + MNSBatchResponse getMNSCacheByAppkeys(1:list appkeys, 2:string protocol); + /** + * 根据IP返回与该IP相关的服务节点 + * @param ip IP 地址 + */ + MNSResponse getProvidersByIP(1:string ip); + /** + * + * @param ip + * @return appkey列表 + */ + AppKeyListResponse getAppkeyListByIP(1:string ip); +} diff --git a/conf/build_common_cfg.sh b/conf/build_common_cfg.sh new file mode 100755 index 0000000..0e0c084 --- /dev/null +++ b/conf/build_common_cfg.sh @@ -0,0 +1,6 @@ +#!/bin/sh + mkdir -p /data/webapps + mkdir -p /octo/ns/ + cp -rf octo.cfg /data/webapps + cp -rf idc.xml /octo/ns/ + echo "you have create the octo.cfg dir(/data/webapps) and idc.xml dir(/octo/ns/sg_agent)" diff --git a/conf/idc.xml b/conf/idc.xml new file mode 100644 index 0000000..ca99fcd --- /dev/null +++ b/conf/idc.xml @@ -0,0 +1,97 @@ + + + + beijing + + DX + BJ1 + + 10.32.0.0 + 255.255.0.0 + + + 10.33.0.0 + 255.255.0.0 + + + + YF + BJ2 + + 10.4.0.0 + 255.255.0.0 + + + 10.5.0.0 + 255.255.0.0 + + + + RZ + NOCENTER + + 10.16.0.0 + 255.255.0.0 + + + 10.17.0.0 + 255.255.0.0 + + + + GH + BJ1 + + 10.20.0.0 + 255.255.0.0 + + + 10.21.0.0 + 255.255.0.0 + + + + TXBJ + BJ1 + + 10.61.0.0 + 255.255.0.0 + + + + + shanghai + + DP + SH + + 10.100.0.0 + 255.255.0.0 + + + + GQ + SH + + 10.3.0.0 + 255.255.0.0 + + + 10.67.0.0 + 255.255.0.0 + + + + NH + SH + + 10.1.0.0 + 255.255.0.0 + + + 10.101.0.0 + 255.255.0.0 + + + + diff --git a/conf/octo.cfg b/conf/octo.cfg new file mode 100644 index 0000000..66987f4 --- /dev/null +++ b/conf/octo.cfg @@ -0,0 +1,7 @@ +env=test +mns_url=http://10.24.33.222:8911 +idc_path=/octo/ns/idc.xml +port=5266 +sg_sentinel_appkey=com.octo.example.sg_sentinel +sgagent_appkey=com.octo.example.sgagent +mnszk_url=127.0.0.1:2181 diff --git a/docs/image/ns.svg b/docs/image/ns.svg new file mode 100644 index 0000000..ab93faa --- /dev/null +++ b/docs/image/ns.svg @@ -0,0 +1 @@ +
health check(scanner)
   local/sentinel(sgagent)
naming service cache(nsc)
zookeeper
openapi(rpc/http)
\ No newline at end of file diff --git a/docs/image/ns_components.svg b/docs/image/ns_components.svg new file mode 100644 index 0000000..ea9fd29 --- /dev/null +++ b/docs/image/ns_components.svg @@ -0,0 +1 @@ +
service provider instance
transport
sdk
service
service consumer instance
transport
sdk
service
sgagent
sgagent
nsc
scanner
管理端
sentienl
local
Zookeeper
zookeeper
rpc call
\ No newline at end of file diff --git a/docs/image/ns_trait.svg b/docs/image/ns_trait.svg new file mode 100644 index 0000000..6c086b8 --- /dev/null +++ b/docs/image/ns_trait.svg @@ -0,0 +1,2 @@ + +
  octo/thrift
[Not supported by viewer]
octo/http
[Not supported by viewer]
     ......
[Not supported by viewer]
服务治理代理sgagent
<font style="font-size: 20px">服务治理代理sgagent</font>
服务发现
[Not supported by viewer]
服务注册
[Not supported by viewer]
节点标签
[Not supported by viewer]
服务分组
[Not supported by viewer]
哨兵模式
[Not supported by viewer]
......
[Not supported by viewer]
服务
注册
[Not supported by viewer]
service provider
service provider
service provider
service provider
service provider
service provider
octo/thrift
[Not supported by viewer]
octo/http
[Not supported by viewer]
     ......
[Not supported by viewer]
service consumer
service&nbsp;consumer
service consumer
service&nbsp;consumer
service consumer
service&nbsp;consumer
服务
发现
[Not supported by viewer]
\ No newline at end of file diff --git a/docs/image/registry_sucess.png b/docs/image/registry_sucess.png new file mode 100644 index 0000000..4eddac5 Binary files /dev/null and b/docs/image/registry_sucess.png differ diff --git a/docs/image/scanner_traits.png b/docs/image/scanner_traits.png new file mode 100644 index 0000000..ef81f50 Binary files /dev/null and b/docs/image/scanner_traits.png differ diff --git a/docs/ns-quick-start.md b/docs/ns-quick-start.md new file mode 100644 index 0000000..aaba191 --- /dev/null +++ b/docs/ns-quick-start.md @@ -0,0 +1,195 @@ +## Naming Service(NS) + + 快速进行Java环境配置、依赖管理以及ZooKeeper、项目下载和配置、NSC、NSInvoker、SGAgent四部分部署即可进行服务注册、服务发现功能,下面给出安装部署说明. + + +| 步骤| 描述 | 备注 | +| ------ | ------ | ------ | +| 1.Java环境配置 | 服务依赖的Java环境 | | +| 2.依赖管理 | 第三方库| | +| 3.ZooKeeper部署 | 存储注册数据| | +| 4.项目下载 | 从git下载项目工程| | +| 5.配置更新 | 更新配置依赖项| | +| 6.NSC部署 | NS缓存服务部署| | +| 7.SGAgent部署 | 服务治理代理安装部署 | | + +### Java环境配置 + +64bit OS: Linux/Unix/Mac, Linux/Unix/Mac recommended. + +64bit JDK 1.8+: [downloads](https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html), [JAVA_HOME settings](https://docs.oracle.com/cd/E19182-01/820-7851/inst_cli_jdk_javahome_t/) + +Maven 3.2.x+: [downloads](https://maven.apache.org/download.cgi), [settings](https://maven.apache.org/settings.html). + +### 依赖管理 + +| 库依赖 | 版本 | 备注 | +| ------ | ------ | ------ | +| muduo | v1.1.0 | 有http服务补丁,见 patch/0001-add-patch-for-http.patch | +| zookeeper | v3.4.6 | | +| thrift | v0.9.3 |依赖的java组件请配置对应程序执行路径,缺省路径/usr/local/bin| + + + +### ZooKeeper部署 +--- + +> [见ZooKeeper安装及部署](https://zookeeper.apache.org/doc/r3.1.2/zookeeperStarted.html) +> [ZooKeeper数据初始化](https://github.com/Meituan-Dianping/octo-ns/tree/master/docs/zookeeper_data_build.md) +> 记录部署的ZooKeeper单机IP或集群IP列表及端口 + +### 项目下载 +--- +~~~ +git clone https://github.com/Meituan-Dianping/octo-ns.git +~~~ + +### 配置更新 +--- +~~~ +cd octo-ns/conf +更新octo.cfg中mnszk_url=IP:PORT //已部署的ZooKeeper机器地址 +更新octo.cfg中mns_url=http://IP:PORT //已部署的NSC服务机器地址,若有多台可配置成为域名) +sh build_common_cfg.sh //见conf目录下的README.md介绍 +~~~ + + +### NSC部署 +--- +依赖构建 +[idl-common依赖构建](../common/idl-mns/idl-common/Compile.md) +[idl-mnsc依赖构建](../common/idl-mns/idl-mnsc/Compile.md) +[mns-invoker依赖构建](../sdk/mns-invoker/docs/Compile.md) +[Dorado依赖构建](https://github.com/Meituan-Dianping/octo-rpc/blob/master/dorado/dorado-doc/manual-developer/Compile.md) + + +部署运行 + +~~~ +cd nsc +sh run.sh +lsof -i:[port] //查看服务端口是否已启用 +~~~ + + +### SGAgent部署 +--- +#### 支持环境 + * CentOS(支持CentOS 6系统) + +#### 依赖初始化 +~~~ +cd octo-ns/sg_agent +sh build.sh init +已自带常用第三方依赖库 //见thrid_party README.md详细介绍 +~~~ +#### 配置初始化 + +>日志级别配置见[Log4cplus使用指南](https://github.com/log4cplus/log4cplus) +cd sg_agent +修改sg\_agent\_mutable.xml的MnsHost对应地域ZooKeeper地址信息(区分测试和生产环境) + +#### 编译 +~~~ +cd octo-ns/sg_agent +sh build.sh with_bin //可执行文件生成 +~~~ +#### 运行 +~~~ +cd octo-ns/sg_agent/tool +sh build_resource.sh //见配置资源文件介绍 +sh run_server.sh +lsof -i:[port] //查看服务端口是否已启用 +~~~ +查看log日志是否有sg_agent自注册日志,如下: + +~~~ +[2018-12-18 22:43:13:671.423] +[../util/json_data_tools.cc:177] +INFO - out: { + "appkey": "com.octo.mns.sg_agent", + "version": "sg_agent-open", + "ip": "10.4.231.87", + "port": 7776, + "weight": 10, + "status": 2, + "role": 0, + "env": 1, + "lastUpdateTime": 1545144193, + "fweight": 10, + "serverType": 0, + "warmup": 0, + "heartbeatSupport": 0, + "protocol": "thrift", + "serviceInfo": { +} +} +[2018-12-18 22:43:13:671.443] [registry_service.cc:482] INFO - to regist when node exists, uptCmd : 1, appkey : com.octo.mns.sg_agent, env : 1, local env : 1, status : 2; fweight : 10; serverType : 0; protocol: thrift, ip : 10.4.231.87 +[2018-12-18 22:43:13:674.349] [zk_client.cc:310] INFO - zoo_set ret = 0, path = /octo/nameservice/test/com.sankuai.inf.newct/provider/10.4.231.87:7776 +[2018-12-18 22:43:13:677.031] [zk_client.cc:310] INFO - zoo_set ret = 0, path = /octo/nameservice/test/com.sankuai.inf.newct/provider +[2018-12-18 22:43:13:677.106] [registry_service.cc:105] INFO - success registry, appkey:com.octo.mns.sg_agent; ip = 10.4.231.87 +~~~ + + + +##### 使用C++ NSSdk发起服务注册/服务发现示例 +--- +见C++ [NSSdk示例说明](../sdk/mns-sdk/ReadMe.md) + +##### 使用Java NSInvoker发起服务注册/服务发现示例 +添加依赖 + +~~~ +pom.xml添加mns-invoker的maven坐标,如下: + + com.meituan.octo + mns-invoker + 1.0.0 + +pom.xml添加依赖,如下: + + com.meituan.octo + mns-invoker + 1.0.0 + +~~~ + +> 构建thrift协议示例,观察SGAgent日志. + + +~~~ +String appkey ="com.meituan.octo.dorado.server"; +String protocol = "thrift"; +int port = 5198; +String version = "original"; +String ip = "127.0.0.1"; +int serverType = 0;//thrift是0,http是1 + +SGService service = new SGService(); + service.setAppkey(appkey); + service.setPort(port); + service.setVersion(version); + service.setIp(ip); + service.setLastUpdateTime((int) (System.currentTimeMillis() / 1000)); + service.setServerType(serverType); + service.setWeight(10); + service.setFweight(10.0); + service.setProtocol(protocol); + +MnsInvoker.registServiceWithCmd(1,service);//增量模式注册 +~~~ + +##### 使用NSInvoker发起服务发现流程 +下面是发现上述服务的例子 + +~~~ +String consumerAppkey = "com.meituan.octo.dorado.client"; +String remoteAppkey = "com.meituan.octo.dorado.server"; + +ProtocolRequest thriftReq = new ProtocolRequest() + .setLocalAppkey(consumerAppkey) + .setRemoteAppkey(remoteAppkey) + .setProtocol("thrift"); +​ +List thriftList = MnsInvoker.getServiceList(thriftReq); +~~~ diff --git a/docs/zookeeper_data_build.md b/docs/zookeeper_data_build.md new file mode 100644 index 0000000..d6998b0 --- /dev/null +++ b/docs/zookeeper_data_build.md @@ -0,0 +1,46 @@ +## zookeeper数据初始化 + + 由于NSC服务启用依赖zookeeper数据的path路径,快速构建可使用zookeeper自带的zkCli.sh脚本进入zookeeper操作控制台操作,也可使用第三方脚本自行创建如python,其自带了zkclient包,便于操作. + 以下给出第一种简单操作方式. + +### 使用zkClie.sh创建数据 +--- +切换至zookeeper安装的bin文件目录 + +~~~ +cd [dirName] //dirName为zookeeper的bin目录 +~~~ + +创建节点信息test、stage、prod环境path + +~~~ +cd [dirName] //dirName为zookeeper的bin目录 +./zkCli.sh -timeout 1000 -r -server 127.0.0.1:2181 +create /octo "top octo path" //永久节点方式 +create /octo/nameservice "nameservice dir" +create /octo/nameservice/test "test dir" +create /octo/nameservice/stage "stage dir" +create /octo/nameservice/prod "prod dir" +~~~ + +创建servicename环境test、stage、prod路径 + +~~~ +cd [dirName] //dirName为zookeeper的bin目录 +./zkCli.sh -timeout 1000 -r -server 127.0.0.1:2181 +create /octo "top octo path" //永久节点方式 +create /octo/service "nameservice dir" +create /octo/service/test "test dir" +create /octo/service/stage "stage dir" +create /octo/service/prod "prod dir" +~~~ + +### 数据导入 +将项目中自带的快照数据导入到安装的zookeeper数据路径 + +~~~ +scp octo-ns/conf/snapshot [dirName] +cd [zkBinDir] +./zkServer.sh restart + +~~~ diff --git a/nsc/README.md b/nsc/README.md new file mode 100644 index 0000000..f7570e9 --- /dev/null +++ b/nsc/README.md @@ -0,0 +1,56 @@ +# nsc 介绍 + +## 背景描述 +nsc 是 octo 服务治理体系内的缓存服务数据子系统. + +开发语言: Java + +运行环境要求: JDK 1.8及以上、maven3、zookeeper + +组件依赖: [Dorado](https://github.com/Meituan-Dianping/octo-rpc/tree/master/dorado) + +主要功能点: + +1. 缓存服务注册信息,为octo组件提供批量获取服务列表功能 +2. 提供sgagent哨兵列表,本地sg不可用时,业务服务fallback到哨兵服务,保证octo健壮性 + + +## 实现细节 +### 数据同步机制 +被动notify + push的机制保障数据实效性;周期性的pull同步模式,确保数据完整性。 + +### 异步模式 +采用异步模式处理watcher触发后的逻辑,避免同步模式下大量watcher阻塞执行,排队耗费大量等待时间。 + +### 过滤zk事件 +网络抖动时,产生的网络事件会导致zk-client进行watcher实例重复注册;频繁网络抖动可能导致进程OOM。 + +### 队列分离 +分队列处理不同优先级任务,保证核心任务快速响应 + +## 快速上手 +### 依赖构建 +[idl-common依赖构建](https://github.com/Meituan-Dianping/octo-ns/tree/master/common/idl-mns/idl-common/Compile.md) +[idl-mnsc依赖构建](https://github.com/Meituan-Dianping/octo-ns/tree/master/common/idl-mns/idl-mnsc/Compile.md) +[mns-invoker依赖构建](https://github.com/Meituan-Dianping/octo-ns/tree/master/mns-invoker/docs/Compile.md) +[Dorado依赖构建](https://github.com/Meituan-Dianping/octo-rpc/blob/master/dorado/dorado-doc/manual-developer/Compile.md) + + + + +### 打包运行nsc + + +```bash +git clone git@github.com:Meituan-Dianping/octo-ns.git + +cd octo-ns/mns-cache + +sh ./run.sh + +#需要在启动提前在octo.cfg参数中指定zookeeper地址 +#日志会输出到当前路径下"/opt/logs/com.meituan.octo.mnsc/mnsc-server.log"文件 + +``` + + diff --git a/nsc/pom.xml b/nsc/pom.xml new file mode 100644 index 0000000..171a8b0 --- /dev/null +++ b/nsc/pom.xml @@ -0,0 +1,285 @@ + + + 4.0.0 + com.meituan.octo + mnsc + 1.0.0 + jar + mnsc + + org.springframework.boot + spring-boot-starter-parent + 1.5.18.RELEASE + + + + 2.9.5 + 2.7 + 3.1.0 + 2.10.7 + 2.1.0 + 0.11.2 + 2.4.0-M1 + 0.3.16 + 2.2.4 + 2.6 + + + + org.springframework.boot + spring-boot-starter + + + logback-classic + ch.qos.logback + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-jetty + + + org.eclipse.jetty.websocket + websocket-server + + + org.eclipse.jetty.websocket + javax-websocket-server-impl + + + + + org.springframework.boot + spring-boot-starter-test + test + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.meituan.octo + idl-common + 1.0.0 + + + libthrift + org.apache.thrift + + + + + com.meituan.octo + idl-mnsc + 1.0.0 + + + com.meituan.octo + mns-invoker + 1.0.0 + + + com.fasterxml.jackson.module + jackson-module-scala_2.10 + 2.9.2 + + + + org.apache.curator + curator-framework + 4.0.1 + + + org.apache.curator + curator-recipes + 4.0.1 + + + org.apache.zookeeper + zookeeper + 3.4.8 + + + slf4j-log4j12 + org.slf4j + + + log4j + log4j + + + + + joda-time + joda-time + 2.8.2 + + + com.meituan.octo + dorado + 1.0.0 + + + junit + junit + 4.12 + test + + + org.codehaus.jackson + jackson-mapper-asl + 1.8.0 + + + net.liftweb + lift-json_2.10 + 2.5 + + + org.scala-lang + scala-compiler + ${scala.version} + + + org.scala-lang + scala-library + ${scala.version} + + + org.scalaj + scalaj-http_2.10 + ${scalaj-http.version} + + + com.typesafe.slick + slick_2.10 + ${slick.version} + + + com.typesafe.slick + slick-codegen_2.10 + ${slick.version} + + + com.typesafe.play + play-json_2.10 + ${play-json.version} + + + net.databinder.dispatch + dispatch-core_2.10 + ${dispatch.version} + + + org.scalatest + scalatest_2.10 + ${scalatest.version} + + + org.apache.logging.log4j + log4j-slf4j-impl + ${log4j.version} + true + + + org.apache.logging.log4j + log4j-core + ${log4j.version} + true + + + commons-lang + commons-lang + ${commons-lang.version} + + + + + + net.alchim31.maven + scala-maven-plugin + ${scala.maven.version} + + + scala-compile-first + process-resources + + add-source + compile + + + + scala-test-compile + process-test-resources + + testCompile + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + false + + **/*Test.java + + + + + + + + test + + true + + + + + src/main/profiles/test + + + src/main/resources + + + + + + online + + + + src/main/profiles/online + + + src/main/resources + + + + + + diff --git a/nsc/run.sh b/nsc/run.sh new file mode 100644 index 0000000..8b663ed --- /dev/null +++ b/nsc/run.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +JVM_ARGS="-server -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Djava.io.tmpdir=/tmp -Djava.net.preferIPv6Addresses=false" +JVM_GC="-XX:+DisableExplicitGC -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:+UseConcMarkSweepGC -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps" +JVM_GC=$JVM_GC" -XX:CMSFullGCsBeforeCompaction=0 -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=80" +JVM_HEAP="-XX:SurvivorRatio=8 -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:ReservedCodeCacheSize=128m -XX:InitialCodeCacheSize=128m" +JVM_SIZE="-Xmx4g -Xms4g -Xmn2g" + +EXEC_JAVA="java $JVM_ARGS $JVM_SIZE $JVM_HEAP $JVM_GC" +EXEC_JAVA=$EXEC_JAVA" $JAVA_ARGS" + +mvn clean -U package -Dmaven.test.skip=true +cd target +$EXEC_JAVA -jar mnsc-1.0.0.jar \ No newline at end of file diff --git a/nsc/src/main/java/com/meituan/octo/mnsc/MnscServerApplication.java b/nsc/src/main/java/com/meituan/octo/mnsc/MnscServerApplication.java new file mode 100644 index 0000000..0594f89 --- /dev/null +++ b/nsc/src/main/java/com/meituan/octo/mnsc/MnscServerApplication.java @@ -0,0 +1,13 @@ +package com.meituan.octo.mnsc; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ImportResource; + +@SpringBootApplication +@ImportResource(locations = {"classpath:applicationContext.xml", "classpath:webmvc-config.xml"}) +public class MnscServerApplication { + public static void main(String[] args) { + SpringApplication.run(MnscServerApplication.class, args); + } +} diff --git a/nsc/src/main/java/com/meituan/octo/mnsc/thrift/service/impl/MNSCacheServiceImpl.java b/nsc/src/main/java/com/meituan/octo/mnsc/thrift/service/impl/MNSCacheServiceImpl.java new file mode 100644 index 0000000..a013788 --- /dev/null +++ b/nsc/src/main/java/com/meituan/octo/mnsc/thrift/service/impl/MNSCacheServiceImpl.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.thrift.service.impl; + +import com.octo.mnsc.idl.thrift.model.*; +import com.octo.mnsc.idl.thrift.service.MNSCacheService; +import com.meituan.octo.mnsc.model.Env; +import com.meituan.octo.mnsc.service.mnscService; +import org.apache.commons.lang.StringUtils; +import org.apache.thrift.TException; +import org.springframework.util.Assert; + +import java.util.List; + +public class MNSCacheServiceImpl implements MNSCacheService.Iface { + @Override + public MNSResponse getMNSCache(String appkey, String version, String env) throws TException { + if (!Env.isValid(env) || org.apache.commons.lang3.StringUtils.isEmpty(appkey)) { + MNSResponse ret = new MNSResponse(); + ret.setCode(mnsc_dataConstants.ILLEGAL_ARGUMENT); + return ret; + } + return mnscService.getMnsc(appkey, version, env); + } + + @Override + public MNSResponse getMNSCacheHttp(String appkey, String version, String env) throws TException { + if (!Env.isValid(env) || org.apache.commons.lang3.StringUtils.isEmpty(appkey)) { + MNSResponse ret = new MNSResponse(); + ret.setCode(mnsc_dataConstants.ILLEGAL_ARGUMENT); + return ret; + } + return mnscService.getMNSCache4HLB(appkey, version, env); + } + + @Override + public MNSBatchResponse getMNSCacheByAppkeys(List appkeys, String protocol) throws TException { + if (null == appkeys || StringUtils.isEmpty(protocol)) { + return new MNSBatchResponse().setCode(mnsc_dataConstants.ILLEGAL_ARGUMENT); + } + return mnscService.getMNSCacheByAppkeys(appkeys, protocol); + } + + @Override + public MNSResponse getProvidersByIP(String ip) throws TException { + Assert.hasText(ip, "ip不能为空"); + return mnscService.getProvidersByIP(ip); + } + + @Override + public MNSResponse getMNSCacheWithVersionCheck(MnsRequest mnsRequest) throws TException { + if (null == mnsRequest || StringUtils.isEmpty(mnsRequest.getAppkey()) || !Env.isValid(mnsRequest.getEnv())) { + MNSResponse invalidResponse = new MNSResponse(); + invalidResponse.setCode(mnsc_dataConstants.ILLEGAL_ARGUMENT); + return invalidResponse; + } + return mnscService.getMnsc(mnsRequest); + } + + @Override + public AppKeyListResponse getAppkeyListByIP(String ip) throws TException { + AppKeyListResponse ret = new AppKeyListResponse(); + if (StringUtils.isEmpty(ip)) { + ret.setCode(400); + } else { + List appkeys = mnscService.getAppkeyListByIP(ip.trim()); + ret.setCode(200).setAppKeyList(appkeys); + } + return ret; + } +} diff --git a/nsc/src/main/java/com/meituan/octo/mnsc/web/api/ApiController.java b/nsc/src/main/java/com/meituan/octo/mnsc/web/api/ApiController.java new file mode 100644 index 0000000..884b98e --- /dev/null +++ b/nsc/src/main/java/com/meituan/octo/mnsc/web/api/ApiController.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.web.api; + +import com.meituan.octo.mns.util.ProcessInfoUtil; +import com.meituan.octo.mnsc.model.Env; +import com.meituan.octo.mnsc.service.apiService; +import com.meituan.octo.mnsc.service.mnscService; +import com.meituan.octo.mnsc.utils.api; +import com.meituan.octo.mnsc.utils.ipCommon; +import com.meituan.octo.mnsc.utils.mnscCommon; +import com.octo.mnsc.idl.thrift.model.AppKeyListResponse; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.springframework.web.bind.annotation.*; + +@Controller +@RequestMapping("/api") +public class ApiController { + private static final Logger LOG = LoggerFactory.getLogger(ApiController.class); + private static final String SENTINEL = ProcessInfoUtil.getSgsentinelAppkey(); + + @RequestMapping(value = "/monitor/alive") + @ResponseBody + public Map monitorAlive() { + Map result = new HashMap(1); + result.put("status", "ok"); + return result; + } + + @RequestMapping(value = "/servicelist", method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String getServiceList(@RequestParam("appkey") String appkey, + @RequestParam("env") String env, + @RequestParam("ip") String ip) { + //all parameters are required. + try { + if (!SENTINEL.equals(appkey)) { + return api.errorJson(400, "appkey currently only supports com.sankuai.inf.sgsentinel"); + + } + + if (StringUtils.isEmpty(ip) || !(ipCommon.checkIP(ip.trim()))) { + return api.errorJson(400, "ip invalid"); + } + if (!Env.isValid(env.trim())) { + return api.errorJson(400, "env invalid"); + } + + return apiService.getServiceList(appkey, env.trim(), ip.trim()); + } catch (Exception e) { + LOG.error("/api/servicelist error ", e); + return api.errorJson(500, "server error"); + } + } + + @RequestMapping(value = "/{ip}/appkeylist", method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String getAppkeyList(@PathVariable("ip") String ip) { + AppKeyListResponse ret = new AppKeyListResponse(); + if (StringUtils.isEmpty(ip)) { + ret.setCode(400); + } else { + List appkeys = mnscService.getAppkeyListByIP(ip.trim()); + ret.setCode(200).setAppKeyList(appkeys); + } + return api.dataJson(ret.getCode(), ret.getAppKeyList()); + } + + + @RequestMapping(value = "/allappkeys", method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String getAppkeys() { + return api.dataJson200(mnscCommon.allAppkeysList()); + } +} \ No newline at end of file diff --git a/nsc/src/main/java/com/meituan/octo/mnsc/web/api/ProvidersController.java b/nsc/src/main/java/com/meituan/octo/mnsc/web/api/ProvidersController.java new file mode 100644 index 0000000..f065361 --- /dev/null +++ b/nsc/src/main/java/com/meituan/octo/mnsc/web/api/ProvidersController.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.web.api; + +import com.meituan.octo.mnsc.dataCache.appProviderDataCache; +import com.meituan.octo.mnsc.dataCache.appProviderHttpDataCache; +import com.meituan.octo.mnsc.model.Env; +import com.meituan.octo.mnsc.service.apiProviders; +import com.meituan.octo.mnsc.utils.api; +import com.octo.naming.common.thrift.model.SGService; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + + +@Controller +@RequestMapping("/api/providers") +public class ProvidersController { + private static final Logger LOG = LoggerFactory.getLogger(ProvidersController.class); + private static final String HTTP = "http"; + private static final String THRIFT = "thrift"; + + @RequestMapping(value = "", method = RequestMethod.GET, produces = "application/json") + @ResponseBody + public String getProviders(@RequestParam("appkey") String appkey, + @RequestParam("env") int env, + @RequestParam("protocol") String protocol) { + try { + if (StringUtils.isEmpty(appkey)) { + return api.errorJson(400, "appkey is not allowed to empty"); + } + + if (!Env.isValid(env)) { + return api.errorJson(400, "env invalid"); + } + + if (StringUtils.isEmpty(protocol)) { + return api.errorJson(400, "protocol is not allowed to empty"); + } + + if (THRIFT.equalsIgnoreCase(protocol)) { + return api.dataJson(appProviderDataCache.getProviderCache(appkey, Env.apply(env).toString(),false)); + } else if (HTTP.equalsIgnoreCase(protocol)) { + return api.dataJson(appProviderHttpDataCache.getProviderHttpCache(appkey, Env.apply(env).toString(),false)); + } else { + return apiProviders.getProviders(appkey.trim(), env, protocol); + } + } catch (Exception e) { + LOG.error("/api/providers error ", e); + return api.errorJson(500, "server error"); + } + } + + @RequestMapping(value = "", method = RequestMethod.POST, produces = "application/json") + @ResponseBody + public String postProviders(@RequestBody List providers) { + return api.jsonStr(apiProviders.postProviders(providers)); + } + + @RequestMapping(value = "", method = RequestMethod.DELETE, produces = "application/json") + @ResponseBody + public String deleteProviders(@RequestBody List providers) { + return api.jsonStr(apiProviders.deleteProviders(providers)); + } + + @RequestMapping(value = "/delete", method = RequestMethod.POST, produces = "application/json") + @ResponseBody + public String deletePostProviders(@RequestBody List providers) { + // client may be able to delete the nodes because the jdk bug, so add a new API. more detail see: http://bugs.java.com/view_bug.do?bug_id=8148558 + return api.jsonStr(apiProviders.deleteProviders(providers)); + } +} diff --git a/nsc/src/main/profiles/online/log4j2.xml b/nsc/src/main/profiles/online/log4j2.xml new file mode 100644 index 0000000..893540c --- /dev/null +++ b/nsc/src/main/profiles/online/log4j2.xml @@ -0,0 +1,24 @@ + + + + com.meituan.octo.mnsc + mnsc-server + + + + + %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + \ No newline at end of file diff --git a/nsc/src/main/profiles/test/log4j2.xml b/nsc/src/main/profiles/test/log4j2.xml new file mode 100644 index 0000000..4e4c30a --- /dev/null +++ b/nsc/src/main/profiles/test/log4j2.xml @@ -0,0 +1,28 @@ + + + + com.meituan.octo.mnsc + mnsc-server + + + + + + + + %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nsc/src/main/resources/application.yaml b/nsc/src/main/resources/application.yaml new file mode 100644 index 0000000..16e6559 --- /dev/null +++ b/nsc/src/main/resources/application.yaml @@ -0,0 +1,2 @@ +server: + port: 8911 \ No newline at end of file diff --git a/nsc/src/main/resources/applicationContext.xml b/nsc/src/main/resources/applicationContext.xml new file mode 100644 index 0000000..22d5410 --- /dev/null +++ b/nsc/src/main/resources/applicationContext.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nsc/src/main/resources/webmvc-config.xml b/nsc/src/main/resources/webmvc-config.xml new file mode 100644 index 0000000..cc918f8 --- /dev/null +++ b/nsc/src/main/resources/webmvc-config.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/bootstrap/bootstrap.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/bootstrap/bootstrap.scala new file mode 100644 index 0000000..227e8d1 --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/bootstrap/bootstrap.scala @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.bootstrap + +import com.meituan.octo.mnsc.dataCache.{appProviderDataCache, appProviderHttpDataCache} +import com.meituan.octo.mnsc.model.Path +import com.meituan.octo.mnsc.zkWatcher.appProviderWatcher +import org.joda.time.DateTime + +class bootstrap { + def init() = { + val start = new DateTime().getMillis + println(s"start to init.") + appProviderDataCache.renewAllProviderForce(Path.provider.toString, true) + appProviderHttpDataCache.renewAllProviderForce(Path.providerHttp.toString, true) + + appProviderWatcher.initWatcher() + + appProviderHttpDataCache.doRenew() + appProviderDataCache.doRenew() + val end = new DateTime().getMillis + println(s"finish to init --> cost ${end - start}") + } +} diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/dataCache/appProviderDataCache.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/dataCache/appProviderDataCache.scala new file mode 100644 index 0000000..6ef73b4 --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/dataCache/appProviderDataCache.scala @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.dataCache + +import java.util.concurrent.{ConcurrentHashMap, Executors, TimeUnit} + +import com.meituan.octo.mnsc.model.{Env, Path, ServerType} +import com.meituan.octo.mnsc.remote.zk +import com.meituan.octo.mnsc.utils.mnscCommon +import com.meituan.octo.mnsc.model.service.CacheValue +import org.slf4j.LoggerFactory + +import scala.collection.JavaConverters._ +import scala.collection.concurrent.Map + +/** + * ZK provider节点下数据缓存 + */ +object appProviderDataCache extends providerBaseCache { + private val LOG = LoggerFactory.getLogger(appProviderDataCache.getClass) + + //服务的provider缓存,key为"appkey|env" + private val providerCache = new ConcurrentHashMap[String, CacheValue]() asScala + + private val ipInfoCache = new ConcurrentHashMap[String, scala.collection.Set[String]]() asScala + + private var pullCount4Provider = 0 + + private val scheduler = Executors.newScheduledThreadPool(2) + + //获取provider cache + def getProviderCache(appkey: String, env: String, isSearchZK: Boolean) = { + val cache = getCache(appkey) + val providers = cache.get(getCacheKey(appkey, env)) + if (providers.isEmpty && isSearchZK) { + LOG.debug(s"providerCache don't exist $appkey|$env") + val (version, _) = zk.getNodeVersion(s"${mnscCommon.rootPre}/$env/$appkey/${Path.provider.toString}") + updateProviderCache(version, appkey, env, Path.provider.toString) + cache.get(getCacheKey(appkey, env)) + + } else { + providers + } + } + + override protected def getCache(appkey: String) = { + providerCache + } + + override protected def getCache(): Map[String, CacheValue] = providerCache + + override protected def getIpInfoCache(): Map[String, scala.collection.Set[String]] = ipInfoCache + + //周期进行强同步和弱同步 + def doRenew() = { + val now = System.currentTimeMillis() / mnscCommon.initDelay4Provider + val init = 60 - (now % 60) + LOG.info(s"init doRenew on $now with delay $init") + //provider定时同步任务 + scheduler.scheduleAtFixedRate(new Runnable { + def run(): Unit = { + try { + if (0 == pullCount4Provider) { + LOG.info("renewAllProviderForce start. count = {}", pullCount4Provider + 1) + val startProvider = System.currentTimeMillis() + renewAllProviderForce(Path.provider.toString, true) + val endProvider = System.currentTimeMillis() + LOG.info("renewAllProviderForce cost {}", endProvider - startProvider) + //逐出被删除的appKey + deleteNonexistentAppKey() + } else { + LOG.info(s"renewAllProvider start. count = {}", pullCount4Provider + 1) + val startProvider = System.currentTimeMillis() + renewAllProvider(providerCache, Path.provider.toString) + val endProvider = System.currentTimeMillis() + LOG.info(s"renewAllProvider cost {}", endProvider - startProvider) + } + pullCount4Provider = (pullCount4Provider + 1) % mnscCommon.forceBorder4Provider + } catch { + case e: Exception => LOG.error(s"renew localCache fail.", e) + } + } + }, init, mnscCommon.renewInterval4Provider * 6, TimeUnit.SECONDS) + + scheduler.scheduleWithFixedDelay(new Runnable { + def run(): Unit = { + try { + LOG.info(s"renew ip to appkeys map start.") + val startProvider = System.currentTimeMillis() + + ipInfoCache.foreach { + item => + val removeAppkey = scala.collection.mutable.ArrayBuffer[String]() + item._2.foreach { + app => + val isExists = Env.values.exists{ + env => + val key = s"$app|$env" + providerCache.keySet.contains(key) && providerCache(key).SGServices.exists(_.ip == item._1) + } + if (!isExists) { + removeAppkey += app + } + } + val newCache = item._2 -- removeAppkey + ipInfoCache.update(item._1, newCache) + } + val endProvider = System.currentTimeMillis() + LOG.info(s"renew ip to appkeys map start cost ${endProvider - startProvider}") + } catch { + case e: Exception => LOG.error(s"renew ip to appkeys map start fail.", e) + } + } + }, init, 10, TimeUnit.MINUTES) + } + + + def getProvidersByIP(ip: String) = { + val list = providerCache.flatMap(_._2.SGServices.filter(_.ip.equals(ip))) + list.foreach(_.setServerType(ServerType.thrift.id)) + list.toList + } +} \ No newline at end of file diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/dataCache/appProviderHttpDataCache.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/dataCache/appProviderHttpDataCache.scala new file mode 100644 index 0000000..4347cf8 --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/dataCache/appProviderHttpDataCache.scala @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.dataCache + +import java.util.concurrent.{ConcurrentHashMap, Executors, TimeUnit} + +import com.meituan.octo.mnsc.model.{Env, Path, ServerType} +import com.meituan.octo.mnsc.model.service.CacheValue +import com.meituan.octo.mnsc.remote.zk +import com.meituan.octo.mnsc.utils.mnscCommon +import org.joda.time.DateTime +import org.slf4j.{Logger, LoggerFactory} + +import scala.collection.JavaConverters._ +import scala.collection.concurrent.Map + +object appProviderHttpDataCache extends providerBaseCache { + private val LOG: Logger = LoggerFactory.getLogger(appProviderHttpDataCache.getClass) + private val pre = mnscCommon.rootPre + + //服务的provider-http缓存,key为"appkey|env" + private val providerHttpCache = new ConcurrentHashMap[String, CacheValue]() asScala + + private val ipInfoCache = new ConcurrentHashMap[String, scala.collection.Set[String]]() asScala + + private var pullCount4ProviderHttp = 0 + + private val scheduler = Executors.newScheduledThreadPool(1) + + //周期进行强同步和弱同步 + def doRenew() = { + val now = System.currentTimeMillis() / mnscCommon.initDelay4HttpProperties + val init = 60 - (now % 60) + LOG.info(s"init doRenew on $now with delay $init") + + //provider-http定时同步任务 + scheduler.scheduleAtFixedRate(new Runnable { + def run(): Unit = { + try { + if (0 == pullCount4ProviderHttp) { + //For provider-http + LOG.info("renewAllProviderHTTPForce start") + val startProviderHTTP = new DateTime().getMillis + renewAllProviderForce(Path.providerHttp.toString, true) + val endProviderHTTP = new DateTime().getMillis + LOG.info(s"renewAllProviderHTTPForce cost ${endProviderHTTP - startProviderHTTP}") + //逐出被删除的appKey + deleteNonexistentAppKey() + } else { + LOG.info("renewAllProviderHTTP start") + val startProviderHTTP = new DateTime().getMillis + renewAllProvider(providerHttpCache, Path.providerHttp.toString) + val endProviderHTTP = new DateTime().getMillis + LOG.info(s"renewAllProviderHTTP cost ${endProviderHTTP - startProviderHTTP}") + } + pullCount4ProviderHttp = (pullCount4ProviderHttp + 1) % mnscCommon.forceBorder4ProviderHttp + } catch { + case e: Exception => LOG.error(s"renew localCache fail.", e) + } + } + }, init, mnscCommon.renewInterval4ProviderHttp * 6, TimeUnit.SECONDS) + + scheduler.scheduleWithFixedDelay(new Runnable { + def run(): Unit = { + try { + LOG.info(s"renewHTTP ip to appkeys map start.") + val startProvider = System.currentTimeMillis() + + ipInfoCache.foreach { + item => + val removeAppkey = scala.collection.mutable.ArrayBuffer[String]() + item._2.foreach { + app => + val isExists = Env.values.exists{ + env => + val key = s"$app|$env" + providerHttpCache.keySet.contains(key) && providerHttpCache(key).SGServices.exists(_.ip == item._1) + } + if (!isExists) { + removeAppkey += app + } + } + val newCache = item._2 -- removeAppkey + ipInfoCache.update(item._1, newCache) + } + val endProvider = System.currentTimeMillis() + LOG.info(s"renewHTTP ip to appkeys map start cost ${endProvider - startProvider}") + } catch { + case e: Exception => LOG.error(s"renewHTTP ip to appkeys map start fail.", e) + } + } + }, init+1, 10, TimeUnit.MINUTES) + } + + //获取provider-http cache + def getProviderHttpCache(appkey: String, env: String, isSearchZK: Boolean) = { + val providers = providerHttpCache.get(getCacheKey(appkey, env)) + if (providers.isEmpty && isSearchZK) { + LOG.debug(s"providerHttpCache don't exist $appkey|$env") + val (version, _) = zk.getNodeVersion(s"${mnscCommon.rootPre}/$env/$appkey/${Path.providerHttp.toString}") + updateProviderCache(version, appkey, env, Path.providerHttp.toString) + providerHttpCache.get(s"$appkey|$env") + } else { + providers + } + } + + def getProvidersByIP(ip: String) = { + val list = providerHttpCache.flatMap(_._2.SGServices.filter(_.ip.equals(ip))) + list.foreach(_.setServerType(ServerType.http.id)) + list.toList + } + + override protected def getCache(appkey: String): Map[String, CacheValue] = providerHttpCache + + override protected def getCache() = providerHttpCache + + override protected def getIpInfoCache(): Map[String, scala.collection.Set[String]] = ipInfoCache +} + + diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/dataCache/appProvidersCommCache.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/dataCache/appProvidersCommCache.scala new file mode 100644 index 0000000..c4632ae --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/dataCache/appProvidersCommCache.scala @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.dataCache + +import java.util.concurrent.ConcurrentHashMap + +import com.meituan.octo.mnsc.model.Env +import com.meituan.octo.mnsc.remote.zk +import com.meituan.octo.mnsc.utils.zkCommon +import com.meituan.octo.mnsc.model.service.{CacheData, ProviderNode} +import org.slf4j.{Logger, LoggerFactory} +import play.api.libs.json.Json + +import scala.collection.JavaConverters._ + +/** + * ZK provider节点下数据缓存 + */ +object appProvidersCommCache { + private val LOG: Logger = LoggerFactory.getLogger(appProvidersCommCache.getClass) + + //服务的provider缓存,key为"appkey|env" + private val providerCache = new ConcurrentHashMap[String, CacheData]() asScala + + //获取provider cache + def getProviderCache(appkey: String, env: Int, protocol: String): CacheData = { + val strEnv = Env(env).toString + val providers = providerCache.get(s"$appkey|$strEnv|$protocol") + providers match { + case Some(value) => { + val curTime = System.currentTimeMillis() / 1000 + if (10 > curTime - providers.get.lastGetTime) { + providers.get + } else { + LOG.info(s"providerCache $appkey|$strEnv|$protocol is expired") + getProviderPar(appkey, strEnv, protocol) + } + } + case None => + LOG.info(s"providerCache don't exist $appkey|$strEnv|$protocol") + getProviderPar(appkey, strEnv, protocol) + } + } + + def getProviderPar(appkey: String, env: String, protocol: String) = { + val path = zkCommon.getProtocolPath(appkey, env, protocol) + val (version, _) = zk.getNodeVersion(path) + val nodeList = zk.children(path) + val versionNew = zk.getNodeVersion(path) + if (version != versionNew) { + LOG.warn(s"version changed during zk.children($path) from $version to $versionNew") + } + val result = scala.collection.mutable.ArrayBuffer[ProviderNode]() + nodeList.foreach( + node => { + val nodePath = s"$path/$node" + try { + val data = zk.getData(nodePath) + Json.parse(data).validate[ProviderNode].asOpt match { + case Some(x) => + result.synchronized { + result += x + } + case _ => //do nothing + } + } catch { + case e: Exception => LOG.error(s"get path $nodePath or Json.validate error ${e.getMessage}", e) + } + } + ) + val cacheData = CacheData(version, result.toList) + providerCache.update(s"$appkey|$env|$protocol", cacheData) + cacheData + } + +} \ No newline at end of file diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/dataCache/providerBaseCache.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/dataCache/providerBaseCache.scala new file mode 100644 index 0000000..0a53f7a --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/dataCache/providerBaseCache.scala @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.dataCache + +import com.meituan.octo.mnsc.model +import com.meituan.octo.mnsc.model.Env +import com.meituan.octo.mnsc.remote.zk +import com.meituan.octo.mnsc.utils.mnscCommon +import com.meituan.octo.mnsc.model.service.{CacheValue, ProviderNode} +import com.octo.naming.common.thrift.model.SGService +import org.apache.commons.lang.StringUtils +import org.joda.time.DateTime +import org.slf4j.LoggerFactory +import play.api.libs.json.Json + +import scala.collection.JavaConverters._ + + +abstract class providerBaseCache { + private val LOG = LoggerFactory.getLogger(this.getClass) + + def updateProviderCache(providerVersion: String, appkey: String, env: String, providerPath: String, isPar: Boolean = false) = { + val path = s"${mnscCommon.rootPre}/$env/$appkey/$providerPath" + if (StringUtils.isNotEmpty(providerVersion)) { + try { + val nodeList = zk.client().getChildren.forPath(path).asScala + val result = scala.collection.mutable.ArrayBuffer[SGService]() + val parList = if (isPar) { + nodeList.par + } else { + nodeList + } + + val ipToAppkey = getIpInfoCache() + parList.foreach( + node => { + val nodePath = s"$path/$node" + val data = zk.client.getData.forPath(nodePath) + val dataUTF8 = if (null == data) "" else new String(data, "utf-8") + if (dataUTF8.nonEmpty) { + Json.parse(dataUTF8).validate[ProviderNode].asOpt match { + case Some(x) => + val service = model.service.ProviderNode2SGService(x) + result.synchronized { + result += service + } + + if (service.ip.nonEmpty) { + val v = if (ipToAppkey.keySet.contains(service.ip)) { + ipToAppkey(service.ip) + service.appkey + } else { + scala.collection.Set[String](service.appkey) + } + + ipToAppkey.update(service.ip, v) + } + case _ => //do nothing + } + } + } + ) + val currentCache = getCache(appkey) + val cacheValue = CacheValue(providerVersion, result.toList) + currentCache.update(getCacheKey(appkey, env), cacheValue) + cacheValue + } catch { + case e: Exception => + LOG.error(s"fail to update cache, appkey=$appkey env=$env", e) + null + } + } else { + null + } + } + + protected def getCache(appkey: String): scala.collection.concurrent.Map[String, CacheValue] + + protected def getCache(): scala.collection.concurrent.Map[String, CacheValue] + + protected def getIpInfoCache(): scala.collection.concurrent.Map[String, scala.collection.Set[String]] + + protected def getCacheKey(appkey: String, env: String) = s"$appkey|$env" + + //若在providerCache中发现不存在的appkey,删除之 + def deleteNonexistentAppKey() = { + val cache = getCache() + val newAppkeys = mnscCommon.allApp() + val cacheAppkeys = getAppkeysByCacheKeySet(cache.keySet) + LOG.info(s"[deleteNonexistentAppKey] providerCache=${cache.keySet.size} cacheAppkeys=${cacheAppkeys.size} newAppkeys=${newAppkeys.size}") + + cacheAppkeys.toList.filter(!newAppkeys.contains(_)).foreach { + appkey => + Env.values.foreach { + env => + cache.remove(s"$appkey|$env") + LOG.info(s"[deleteNonexistentAppKey] providerCache delete $appkey|$env") + } + } + } + + //定时任务强同步pull provider + def renewAllProviderForce(providerPathStr: String, isPar: Boolean) = { + val apps = mnscCommon.allAppkeys(isPar) + val start = new DateTime().getMillis + Env.values.foreach { + env => + apps.foreach { + appkey => + val path = s"${mnscCommon.rootPre}/$env/$appkey/$providerPathStr" + val (version, _) = zk.getNodeVersion(path) + if (null == version) { + LOG.error(s"renewAllProviderForce failed, $path don't exist") + } else { + updateProviderCache(version, appkey, env.toString, providerPathStr) + } + } + } + val end = new DateTime().getMillis + LOG.info(s"renewProviderForce--> path=${providerPathStr} apps.length=${apps.length} cost ${end - start}") + + } + + private def getAppkeysByCacheKeySet(appkeySets: scala.collection.Set[String]) = appkeySets.map(x => x.stripSuffix("|prod").stripSuffix("|stage").stripSuffix("|test")) + + //定时任务弱同步pull provider + protected def renewAllProvider(cache: scala.collection.concurrent.Map[String, CacheValue], providerPathStr: String) = { + val apps = mnscCommon.allApp().par + apps.foreach { + appkey => + Env.values.foreach { + env => + val providers = cache.get(getCacheKey(appkey, env.toString)) + providers match { + case Some(value) => + val path = s"${mnscCommon.rootPre}/$env/$appkey/$providerPathStr" + val (version, _) = zk.getNodeVersion(path) + if (null == version) { + LOG.warn(s"renewAllProvider failed, $path don't exist") + } else { + if (version != value.version) { + updateProviderCache(version, appkey, env.toString, providerPathStr) + } + } + case None => + LOG.debug(s"reload providerCache is empty: $appkey|$env") + } + } + } + } + + + //watcher触发执行动作 + def mnscWatcherAction(appkey: String, env: String, providerPathStr: String) = { + val providers = getCache(appkey).get(getCacheKey(appkey, env)) + val path = s"${mnscCommon.rootPre}/$env/$appkey/$providerPathStr" + val (version, _) = zk.getNodeVersion(path) + providers match { + case Some(value) => + if (version != value.version) { + updateProviderCache(version, appkey, env, providerPathStr) + } + case None => + updateProviderCache(version, appkey, env, providerPathStr) + } + } + + def getAppkeyListByIP(ip: String) = { + val cache = getCache() + val keySet = cache.filter(_._2.SGServices.foldLeft(false) { (result, item) => + result || StringUtils.equals(ip, item.ip) + }).keySet + getAppkeysByCacheKeySet(keySet) + } + + def getAppkeysByIP(ip: String) = { + getIpInfoCache().getOrElse(ip, Nil) + } +} diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/model/Env.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/model/Env.scala new file mode 100644 index 0000000..e0de759 --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/model/Env.scala @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.model + +import com.meituan.octo.mns.util.ProcessInfoUtil +import org.apache.commons.lang.StringUtils + +object Env extends Enumeration { + type Env = Value + val test = Value(1) + val stage = Value(2) + val prod = Value(3) + + def isValid(env: String) = { + if (StringUtils.isEmpty(env)) { + false + } else { + if (ProcessInfoUtil.isLocalHostOnline) { + onlineEnv.contains(env) + } else { + offlineEnv.contains(env) + } + } + } + + def strConvertEnum(env:String)={ + val envEnum= if (ProcessInfoUtil.isLocalHostOnline){ + onlineEnv.get(env) + }else{ + offlineEnv.get(env) + } + envEnum.get + } + + private val offlineEnv = Map( + "ppe" -> stage, + "dev" -> prod, + "test" -> test, + "prod" -> prod, + "stage" -> stage, + "beta" -> stage, + "1" -> test, + "2" -> stage, + "3" -> prod + ) + private val onlineEnv = Map( + "prod" -> prod, + "staging" -> stage, + "stage" -> stage, + "test" -> test, + "1" -> test, + "2" -> stage, + "3" -> prod + ) + + def isValid(env: Int) = values.map(_.id).contains(env) +} diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/model/Path.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/model/Path.scala new file mode 100644 index 0000000..53fa4c4 --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/model/Path.scala @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.model + +object Path extends Enumeration { + type Path = Value + val provider = Value("provider") + val providerHttp = Value("provider-http") +} diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/model/ServerType.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/model/ServerType.scala new file mode 100644 index 0000000..b8c2c71 --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/model/ServerType.scala @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.model + +object ServerType extends Enumeration { + type ServerType= Value + val thrift = Value(0,"provider") + val http = Value(1,"provider-http") +} diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/model/service.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/model/service.scala new file mode 100644 index 0000000..4f2e8ea --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/model/service.scala @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.model + +import com.octo.naming.common.thrift.model.SGService +import org.apache.commons.lang3.StringUtils +import play.api.libs.json.Json.JsValueWrapper +import play.api.libs.json._ +import scala.collection.JavaConverters._ + + +object service { + + case class ServiceDetail(unifiedProto: Int) + + // enabled 0 启用 1 停用 trace 0 关闭 1 开启 + case class ProviderNode(appkey: String, version: String, ip: String, port: Int, + weight: Int, fweight: Option[Double], status: Int, role: Int, env: Int, + lastUpdateTime: Long, serverType: Option[Int] = Some(0), protocol: Option[String] = Some(""), + serviceInfo: Option[Map[String, ServiceDetail]], heartbeatSupport: Option[Int] = Some(0)) { + override def toString = try { + val envir = Env(env) + s"""{"appkey":"${appkey}","version":"${version}","ip":"${ip},"port":${port},"weight":${weight},"fweight":$fweight,"status:":${status},"role":$role,"envir":"${envir}","lastUpdateTime":${lastUpdateTime},"serverType":$serverType,"protocol":"${protocol},"serviceInfo":"${serviceInfo}","heartbeatSupport":"${heartbeatSupport}"}""" + } catch { + case e: Exception => "" + } + } + + case class AppkeyTs(appkey: String, lastUpdateTime: Long) + + implicit val ApppkeyTsReads = Json.reads[AppkeyTs] + implicit val ApppkeyTsWrites = Json.writes[AppkeyTs] + + implicit val serviceDetailRepads = Json.reads[ServiceDetail] + implicit val serviceDetailWrites = Json.writes[ServiceDetail] + + + implicit val mapRepads: Reads[Map[String, ServiceDetail]] = new Reads[Map[String, ServiceDetail]] { + override def reads(json: JsValue): JsResult[Map[String, ServiceDetail]] = JsSuccess { + json.as[JsObject].value.map { + case (k, v) => (k, ServiceDetail( + (v \ "unifiedProto").as[Int] + )) + }.toMap + } + } + implicit val mapWrites: Writes[Map[String, ServiceDetail]] = new Writes[Map[String, ServiceDetail]] { + def writes(map: Map[String, ServiceDetail]): JsValue = + Json.obj(map.map { case (s, o) => + val ret: (String, JsValueWrapper) = s -> Json.toJson(o) + ret + }.toSeq: _*) + } + + + case class ProviderDel(appkey: String, protocol: String, ip: String, prot: Int, env: Int) + + case class Provider(appkey: String, lastUpdateTime: Long) + + implicit val providerNodeReads = Json.reads[ProviderNode] + implicit val providerNodeWrites = Json.writes[ProviderNode] + + implicit val providerReads = Json.reads[Provider] + implicit val providerWrites = Json.writes[Provider] + + implicit val providerDelReads = Json.reads[ProviderDel] + implicit val providerDelWrites = Json.writes[ProviderDel] + + + case class NodeState(mtime: Long, cversion: Long, version: Long) + + implicit val nodeStateR = Json.reads[NodeState] + implicit val nodeStateW = Json.writes[NodeState] + + case class CacheValue(version: String, SGServices: List[SGService]) + + case class CacheData(version: String, Providers: List[ProviderNode], lastGetTime: Long = System.currentTimeMillis() / 1000) + + // version mtime|cversion|version + + def ProviderNode2SGService(node: ProviderNode) = { + + val service = new SGService() + service.setAppkey(node.appkey) + .setVersion(node.version) + .setIp(node.ip) + .setPort(node.port) + .setWeight(node.weight) + .setStatus(node.status) + .setRole(node.role) + .setEnvir(node.env) + .setLastUpdateTime(node.lastUpdateTime.toInt) + .setFweight(node.fweight.getOrElse(0)) + .setServerType(node.serverType.getOrElse(0)) + .setProtocol(node.protocol.getOrElse("")) + .setHeartbeatSupport(node.heartbeatSupport.getOrElse(0).toByte) + .setServiceInfo(ProviderInfo2Info(node).asJava) + } + + + def SGService2ProviderNode(service: SGService) = { + val serviceInfo = if (null == service.serviceInfo) { + Some(Map[String, ServiceDetail]()) + } else { + Some(SGServiceInfo2Info(service)) + } + val protocolTemp = if (StringUtils.isEmpty(service.protocol)) None else Some(service.protocol) + + ProviderNode(service.appkey, + service.version, + service.ip, + service.port, + service.weight, + Some(service.fweight), + service.status, + service.role, + service.envir, + service.lastUpdateTime, + Some(service.serverType), + protocolTemp, + serviceInfo = serviceInfo, + heartbeatSupport = Some(service.heartbeatSupport & 0xff) + ) + } + + private def ProviderInfo2Info(node: ProviderNode) = { + val info = node.serviceInfo.getOrElse(Map[String, ServiceDetail]()) + info.map { + item => + val value = new com.octo.naming.common.thrift.model.ServiceDetail() + value.setUnifiedProto(1 == item._2.unifiedProto) + (item._1 -> value) + } + } + + private def SGServiceInfo2Info(service: SGService) = { + val serviceInfo = service.serviceInfo.asScala + val info = scala.collection.mutable.Map[String, ServiceDetail]() + serviceInfo.foreach { e => + info.put(e._1, ServiceDetail(if (e._2.isUnifiedProto) 1 else 0)) + } + info.toMap + } +} diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/remote/zk.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/remote/zk.scala new file mode 100644 index 0000000..9248862 --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/remote/zk.scala @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.remote + +import java.util + +import com.meituan.octo.mns.util.ProcessInfoUtil +import com.meituan.octo.mnsc.utils.mnscCommon +import org.apache.curator.framework.CuratorFrameworkFactory +import org.apache.curator.framework.api.CuratorWatcher +import org.apache.curator.retry.RetryUntilElapsed +import org.apache.zookeeper.data._ +import org.slf4j.{Logger, LoggerFactory} + +import scala.collection.JavaConverters._ +import scala.util.control.Breaks + + +object zk { + private val LOG: Logger = LoggerFactory.getLogger(zk.getClass) + private val singleHostCount = mnscCommon.singleHostCount4ZK + private var INDEX = 0 + private val zkList = (1 to singleHostCount).flatMap(x => getZk).toList + private val zkWatcher = getWatcherZk + private val zkCount = zkList.length + private val zkClientLock = new Object() + + private def getZk = { + getURLCn2.map { + host => + val superClient = CuratorFrameworkFactory.builder.connectString(host).retryPolicy(new RetryUntilElapsed(3000, 2000)).build() + LOG.info("start zk client with " + host) + superClient.start() + superClient + } + } + + private def getWatcherZk = { + val superClient = CuratorFrameworkFactory.builder.connectString(url).retryPolicy(new RetryUntilElapsed(3000, 2000)).build() + superClient.start() + superClient + } + + private def getURLCn2 = { + val urlsArr = url.split(",") + val ret = new util.ArrayList[String] + var x = 0 + while (x < urlsArr.length) { + var y = x + 1 + while (y < urlsArr.length) { + ret.add(s"${urlsArr(x)},${urlsArr(y)}") + y += 1 + } + x += 1 + } + if (ret.isEmpty) { + ret.add(url) + } + ret.asScala + } + + def client() = { + val loop = new Breaks + var curIndex = getZkIndex() + var ret = zkList(curIndex) + loop.breakable { + for (i <- 1 to zkCount) { + ret = zkList(curIndex) + if (!ret.getZookeeperClient.isConnected) { + curIndex = getNextIndex(curIndex) + } else { + loop.break() + } + } + } + ret + } + + private def getNextIndex(curIndex: Int) = (curIndex + 1) % zkCount + + private def getZkIndex() = zkClientLock.synchronized { + INDEX = getNextIndex(INDEX) + INDEX + } + + private def url: String = { + val uri = ProcessInfoUtil.getMnsZKUrl + if (uri.isEmpty) { + LOG.error("Please set zk url in octo.cfg") + mnscCommon.zookeeperHost + } else uri + } + + def getData(path: String): java.lang.String = { + try { + val data = client.getData.forPath(path) + if (data == null) "" else new String(data, "utf-8") + } catch { + case e: Exception => { + LOG.error(s"function zk.getData exception.", e) + "" + } + } + } + + def children(path: String) = { + try { + client.getChildren.forPath(path).asScala + } catch { + case e: Exception => { + LOG.error("function zk.children exception.", e) + List[String]() + } + } + } + + def exist(path: String): Boolean = { + try { + client.checkExists().forPath(path) != null + } catch { + case e: Exception => { + LOG.error("function zk.exist exception.", e) + false + } + } + } + + private def addWatcher(path: String, watcher: CuratorWatcher, isData: Boolean) = { + try { + if (isData) { + zkWatcher.getData.usingWatcher(watcher).inBackground().forPath(path) + } else { + zkWatcher.getChildren.usingWatcher(watcher).inBackground().forPath(path) + } + true + } catch { + case e: Exception => + LOG.error("fail to add watcher.", e) + false + } + } + + def addDataWatcher(path: String, watcher: CuratorWatcher) = { + addWatcher(path, watcher, true) + } + + def addChildrenWatcher(path: String, watcher: CuratorWatcher) = { + addWatcher(path, watcher, false) + } + + def getNodeState(path: String) = { + try { + client.checkExists().forPath(path) + } catch { + case e: Exception => { + LOG.error(s"function zk.getNodeState exception.", e) + null + } + } + } + + def getNodeVersion(path: String) = { + val nodeState = getNodeState(path) + if (null != nodeState) { + (s"${nodeState.getMtime}|${nodeState.getCversion}|${nodeState.getVersion}", nodeState.getMtime) + } else { + + (null, -101l) + } + } + + def getNodeVersion(nodeState: Stat) = { + if (null != nodeState) { + s"${nodeState.getMtime}|${nodeState.getCversion}|${nodeState.getVersion}" + } else { + null + } + } + + def versionCompare(inputVersion: String, cacheVersion: String, defaultValue: Boolean, f: (Long, Long) => Boolean) = { + if (null == inputVersion || null == cacheVersion) { + defaultValue + } else { + val inputVersionArray = inputVersion.split("\\|") + val cacheVersionArray = cacheVersion.split("\\|") + if (inputVersionArray.length == 3 && cacheVersionArray.length == 3) { + f(inputVersionArray(2).toLong, cacheVersionArray(2).toLong) + } else { + defaultValue + } + } + + } +} diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/service/apiProviders.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/service/apiProviders.scala new file mode 100644 index 0000000..7b19523 --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/service/apiProviders.scala @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.service + +import scala.collection.JavaConverters._ +import com.meituan.octo.mnsc.dataCache.appProvidersCommCache +import com.meituan.octo.mnsc.model.{Env, service} +import com.meituan.octo.mnsc.model.service.{Provider, ProviderNode} +import com.meituan.octo.mnsc.remote.zk +import com.meituan.octo.mnsc.utils.{api, zkCommon} +import com.octo.naming.common.thrift.model.SGService +import org.slf4j.{Logger, LoggerFactory} +import play.api.libs.json.Json + +object apiProviders { + private val LOG: Logger = LoggerFactory.getLogger(apiProviders.getClass) + + + def getProviders(appkey: String, env: Int, protocol: String) = { + val services = appProvidersCommCache.getProviderCache(appkey, env, protocol) + if (services.Providers.isEmpty) api.errorJson(404, s"can't find appkey:$appkey env:$env protocol:$protocol") else api.dataJson(200, Map { + "serviceList" -> services.Providers + }) + } + + def postProviders(providers: java.util.List[SGService]) = { + providers.asScala.map { + svr => + if (null == svr.getVersion) { + // version cannot be null + svr.setVersion("") + } + val item = service.SGService2ProviderNode(svr) + val protocol = getProtocol(item) + val providerPath = zkCommon.getProtocolPath(item.appkey, Env(item.env).toString, protocol) + val nodePath = s"${providerPath}/${item.ip}:${item.port}" + val nodeData = Json.prettyPrint(Json.toJson(item)) + val provider = Provider(item.appkey, item.lastUpdateTime) + val providerData = Json.prettyPrint(Json.toJson(provider)) + if (!zk.exist(providerPath)) { + val msg = Map("appkey" -> item.appkey, "ip" -> item.ip, "port" -> item.port) + Map("ret" -> 404, "msg" -> msg) + } + else if (zk.exist(nodePath)) { + zk.client.inTransaction().setData().forPath(nodePath, nodeData.getBytes("utf-8")).and().setData().forPath(providerPath, providerData.getBytes("utf-8")).and().commit() + Map("ret" -> 200, "msg" -> "success") + } + else { + zk.client.inTransaction().create().forPath(nodePath, nodeData.getBytes("utf-8")).and().setData().forPath(providerPath, providerData.getBytes("utf-8")).and().commit() + Map("ret" -> 200, "msg" -> "success") + } + } + } + + + def deleteProviders(providers: java.util.List[SGService]) = { + providers.asScala.map { + svr => + val item = service.SGService2ProviderNode(svr) + val protocol = getProtocol(item) + val providerPath = zkCommon.getProtocolPath(item.appkey, Env(item.env).toString, protocol) + val nodePath = s"${providerPath}/${item.ip}:${item.port}" + val provider = Provider(item.appkey, item.lastUpdateTime) + val providerData = Json.prettyPrint(Json.toJson(provider)) + if (!zk.exist(providerPath) || !zk.exist(nodePath)) { + val msg = Map("appkey" -> item.appkey, "ip" -> item.ip, "port" -> item.port) + Map("ret" -> 404, "msg" -> msg) + } + else { + zk.client.inTransaction().delete().forPath(nodePath).and().setData().forPath(providerPath, providerData.getBytes("utf-8")).and().commit() + Map("ret" -> 200, "msg" -> "success") + } + } + } + + def getProtocol(item: ProviderNode) = { + item.protocol.getOrElse(if (Some(1) == item.serverType) "http" else "thrift") + } + +} diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/service/apiService.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/service/apiService.scala new file mode 100644 index 0000000..0161b23 --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/service/apiService.scala @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.service + +import java.text.SimpleDateFormat +import java.util.Date + +import com.meituan.octo.mns.util.IpUtil +import com.meituan.octo.mnsc.dataCache.appProviderDataCache +import com.meituan.octo.mnsc.model.service +import com.meituan.octo.mnsc.model.service.CacheValue +import com.meituan.octo.mnsc.utils.api +import com.octo.naming.common.thrift.model.{SGService, fb_status} +import com.octo.idc.model.Idc +import org.slf4j.{Logger, LoggerFactory} + +import scala.collection.JavaConverters._ +object apiService { + private val LOG: Logger = LoggerFactory.getLogger(apiService.getClass) + private def getTimeMillis(time: String) = { + val ret = try { + val dateFormat = new SimpleDateFormat("yy-MM-dd HH:mm:ss"); + val dayFormat = new SimpleDateFormat("yy-MM-dd"); + val curDate = dateFormat.parse(dayFormat.format(new Date()) + " " + time); + curDate.getTime() + } catch { + case e: Exception => + //ignore + 0l + } + ret + } + private def getSamePrefixIP(list: List[SGService], ipIdc: String) = { + val defaultIdc = new Idc() + defaultIdc.setIdc("") + if (ipIdc.nonEmpty) { + list.filter(x => (IpUtil.getIdcInfoFromLocal(List(x.ip).asJava)).asScala.getOrElse(x.ip, defaultIdc).getIdc == ipIdc) + } else { + List() + } + } + private def isListAlive(list: List[SGService]) = { + list.foldLeft(false) { + (ret, item) => + ret || (item.status == fb_status.ALIVE.getValue) + } + } + private def handleServiceList(list: List[SGService], ip: String) = { + val defaultIdc = new Idc() + defaultIdc.setIdc("") + val localIdc = IpUtil.getIdcInfoFromLocal(List(ip).asJava).asScala.getOrElse(ip, defaultIdc) + val regionList = list.filter(x => (IpUtil.getIdcInfoFromLocal(List(x.ip).asJava)).asScala.getOrElse(x.ip, defaultIdc).getRegion == localIdc.getRegion) + val sameIDCList = getSamePrefixIP(regionList, localIdc.getIdc) + if (isListAlive(sameIDCList)) { + sameIDCList + } else if (isListAlive(regionList)) { + regionList + } else { + list + } + } + def getServiceList(appkey: String, env: String, ip: String) = { + val services = appProviderDataCache.getProviderCache(appkey, env, false).getOrElse(CacheValue("", List())) + val list = handleServiceList(services.SGServices, ip) + val retList = if (list.isEmpty) { + List() + } else { + list.map { + item => + service.SGService2ProviderNode(item) + } + } + val retCode = if (retList.isEmpty) 404 else 200 + api.dataJson(retCode, Map("serviceList" -> retList)) + } +} \ No newline at end of file diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/service/mnscService.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/service/mnscService.scala new file mode 100644 index 0000000..83ef55b --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/service/mnscService.scala @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.service + +import java.util.concurrent.ConcurrentHashMap + +import com.meituan.octo.mnsc.dataCache.{appProviderDataCache, appProviderHttpDataCache} +import com.meituan.octo.mnsc.model.{Env, Path, service} +import com.meituan.octo.mnsc.remote.zk +import com.meituan.octo.mnsc.utils.mnscCommon +import com.meituan.octo.mnsc.model.service.CacheValue +import com.octo.mnsc.idl.thrift.model._ +import com.octo.naming.common.thrift.model.SGService +import org.slf4j.{Logger, LoggerFactory} + +import scala.collection.JavaConverters._ + +object mnscService { + private val LOG: Logger = LoggerFactory.getLogger(mnscService.getClass) + + def getMnsc(req: MnsRequest) = { + req.getProtoctol match { + case Protocols.THRIFT => + getCache(req, Path.provider.toString, appProviderDataCache.getProviderCache, appProviderDataCache.updateProviderCache) + case Protocols.HTTP => + getCache(req, Path.providerHttp.toString, appProviderHttpDataCache.getProviderHttpCache, appProviderHttpDataCache.updateProviderCache) + case _ => + val result = new MNSResponse + result.setCode(mnsc_dataConstants.ILLEGAL_ARGUMENT) + result + } + } + + private def getCache(req: MnsRequest, providerPath: String, fCache: (String, String, Boolean) => Option[service.CacheValue], fpar: (String, String, String, String, Boolean) => service.CacheValue) = { + val result = new MNSResponse + val cacheProviders = fCache(req.appkey, req.env, false) + val path = s"${mnscCommon.rootPre}/${req.getEnv}/${req.getAppkey}/$providerPath" + val (zkVersion, _) = zk.getNodeVersion(path) + cacheProviders match { + case Some(item) => + result.setCode(mnsc_dataConstants.SUCCESS) + if (zk.versionCompare(item.version, zkVersion, true, (arg1: Long, arg2: Long) => arg1 == arg2)) { + result.setDefaultMNSCache(item.SGServices.asJava) + .setVersion(item.version) + } else { + val (version,_) = zk.getNodeVersion(path) + val providersUpdate = fpar(version, req.getAppkey, req.getEnv, providerPath, false) + if (null == providersUpdate) { + result.setDefaultMNSCache(item.SGServices.asJava) + .setVersion(item.version) + } else { + result.setDefaultMNSCache(providersUpdate.SGServices.asJava) + .setVersion(providersUpdate.version) + } + } + case None => + result.setCode(mnsc_dataConstants.NOT_FOUND) + } + result + } + + def getMnsc(appkey: String, version: String, env: String) = { + val providers = appProviderDataCache.getProviderCache(appkey, env, false) + getThriftOrHLBCache(providers, appkey, version, env) + } + + + def getMNSCache4HLB(appkey: String, version: String, env: String) = { + val providers = appProviderHttpDataCache.getProviderHttpCache(appkey, env, false) + getThriftOrHLBCache(providers, appkey, version, env) + } + + private def getThriftOrHLBCache(providers: Option[service.CacheValue], appkey: String, version: String, env: String) = { + val res = new MNSResponse + providers match { + case Some(value) => + // if input version is smaller than or equal to cache version, + if (zk.versionCompare(version, value.version, true, (arg1: Long, arg2: Long) => arg1 <= arg2)) { + res.setCode(mnsc_dataConstants.SUCCESS) + .setDefaultMNSCache(value.SGServices.asJava) + .setVersion(value.version) + } else { + res.setCode(mnsc_dataConstants.NOT_MODIFIED) + } + case None => + LOG.debug(s"localCache don't exist $appkey|$env") + res.setCode(mnsc_dataConstants.NOT_FOUND) + + } + res + } + + def getMNSCacheByAppkeys(appkeys: java.util.List[String], protocol: String) = { + val ret = new MNSBatchResponse() + ret.cache = new ConcurrentHashMap[String, java.util.Map[String, java.util.List[SGService]]]() + appkeys.asScala.foreach { + appkey => + Env.values.foreach { + env => + val service = if ("thrift".equalsIgnoreCase(protocol)) { + appProviderDataCache.getProviderCache(appkey, env.toString, false) + } else if ("http".equalsIgnoreCase(protocol)) { + appProviderHttpDataCache.getProviderHttpCache(appkey, env.toString, false) + } else { + None + } + val serviceItem = service.getOrElse(new CacheValue(s"$appkey|$env", List())).SGServices.asJava + // ret.cache.synchronized { + if (null == ret.cache.get(appkey)) { + ret.cache.put(appkey, new ConcurrentHashMap[String, java.util.List[SGService]]()) + } + // } + ret.cache.get(appkey).put(env.toString, serviceItem) + } + } + ret + } + + def getProvidersByIP(ip: String) = { + LOG.debug(s"[getProviderByIP] Input--> ip=$ip") + val ret = new MNSResponse() + try { + val thriftProviders = appProviderDataCache.getProvidersByIP(ip) + val httpProviders = appProviderHttpDataCache.getProvidersByIP(ip) + val list = thriftProviders ::: httpProviders + ret.setCode(200) + ret.setDefaultMNSCache(list.asJava) + } catch { + case e: Exception => + ret.setCode(500) + } + ret + } + + def getAppkeyListByIP(ip: String) = { + val appkeys = appProviderDataCache.getAppkeysByIP(ip) ++ appProviderHttpDataCache.getAppkeysByIP(ip) + appkeys.toList.asJava + } + +} diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/utils/api.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/utils/api.scala new file mode 100644 index 0000000..0d30510 --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/utils/api.scala @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.utils + +import javax.crypto.Mac +import javax.crypto.spec.SecretKeySpec + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.scala.DefaultScalaModule +import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper +import org.apache.commons.codec.binary.Base64 + +object api { + /** ObjectMapper is thread safe */ + private val mapper = new ObjectMapper() with ScalaObjectMapper + mapper.registerModule(DefaultScalaModule) + def errorJsonArgInvalid(msg: AnyRef):String ={ + errorJson(400,msg) + } + + def dataJson200(data: AnyRef):String={ + dataJson(200,data) + } + + def dataJson(errorCode:Int,data: AnyRef):String={ + val map = Map("ret" -> errorCode, "data" -> data) + jsonStr(map) + } + + def dataJson(errorCode:Int, errorMsg:String, data: AnyRef):String={ + val map = Map("ret" -> errorCode, "msg" -> errorMsg, "data" -> data) + jsonStr(map) + } + + def errorJson(errorCode: Int, msg: AnyRef): String = { + val map = Map("ret" -> errorCode, "msg" -> msg) + jsonStr(map) + } + + def dataJson(data: AnyRef): String = { + val map = Map("data" -> data, "isSuccess" -> true) + jsonStr(map) + } + + def jsonStr(data: AnyRef): String = { + new String(jsonBytes(data), "utf-8") + } + + def jsonBytes(data: AnyRef): Array[Byte] = { + mapper.writeValueAsBytes(data) + } + + def toObject[T](bytes: Array[Byte], valueType: Class[T]) = { + mapper.readValue(bytes, valueType) + } + + def toObject[T](str: String, valueType: Class[T]) = { + mapper.readValue(str, valueType) + } + + def authorization(uri: String, method: String, date: String, clientId: String, secret: String): String = { + val signKey = new SecretKeySpec(secret.getBytes("utf-8"), "HmacSHA1") + val mac = Mac.getInstance("HmacSHA1") + mac.init(signKey) + val text = method + " " + uri + "\n" + date + "MWS " + clientId + ":" + Base64.encodeBase64String(mac.doFinal(text.getBytes("utf-8"))) + } +} diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/utils/common.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/utils/common.scala new file mode 100644 index 0000000..65d4f7f --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/utils/common.scala @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.utils + +import org.slf4j.{Logger, LoggerFactory} + +import scala.collection.JavaConverters._ + +object common { + private final val LOG: Logger = LoggerFactory.getLogger(common.getClass) + + def toList(enum: Enumeration) = enum.values.map { + x => Map("name" -> x.toString, "value" -> x.id).asJava + }.toList.sortBy(_.get("value").asInstanceOf[Int]).asJava + + def toPairList(enum: Enumeration) = enum.values.map(x => Pair(x.toString, x.id)).toList.asJava + + def toStringList(enum: Enumeration) = enum.values.map(x => '"' + x.toString + ',' + x.id + '"').toList.asJava + + def toMap(enum: Enumeration) = enum.values.map(x => (x.toString -> x.id)).toMap.asJava + + def toMapById(enum: Enumeration) = enum.values.map(x => (x.id -> x.toString)).toMap.asJava + + def toMap(cc: AnyRef) = { + (Map[String, Any]() /: cc.getClass.getDeclaredFields) { + (a, f) => + f.setAccessible(true) + a + (f.getName -> f.get(cc)) + }.toMap + } + + def toJavaMap(cc: AnyRef) = { + toMap(cc).asJava + } + + def notEmpty(s: String) = s != null && !s.trim.isEmpty + + def notNull(s: String) = s != null + +} diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/utils/ipCommon.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/utils/ipCommon.scala new file mode 100644 index 0000000..5e8074f --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/utils/ipCommon.scala @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.utils + +import org.apache.commons.lang.StringUtils + +object ipCommon { + private final val ipRegex = "^(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|[1-9])\\." + + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." + + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)\\." + + "(1\\d{2}|2[0-4]\\d|25[0-5]|[1-9]\\d|\\d)$" + + + def getPrefixOfIP(ip: String) = { + val ips = ip.split("\\.") + val prefix = List(ips(0), ips(1)).mkString(".") + s"$prefix." + } + + def checkIP(ip: String) = { + if (StringUtils.isBlank(ip)) { + false + } else { + ip.trim.matches(ipRegex) + } + } + +} diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/utils/mnscCommon.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/utils/mnscCommon.scala new file mode 100644 index 0000000..1dde191 --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/utils/mnscCommon.scala @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.utils + +import com.meituan.octo.mnsc.remote.zk +import org.apache.commons.lang3.StringUtils +import com.meituan.octo.mns.util.ProcessInfoUtil +import org.slf4j.{Logger, LoggerFactory} + +import scala.collection.JavaConverters._ + + +object mnscCommon { + private val LOG: Logger = LoggerFactory.getLogger(mnscCommon.getClass) + + val rootPre = "/octo/nameservice" + + val zookeeperHost = "10.24.41.248:2188,10.24.41.248:2188,10.24.41.248:2188" + //10.20.63.232:2181,10.21.128.208:2181,10.20.60.152:2181 + + //provider线程第一执行delay时间模值 + val initDelay4Provider = 100 + //provider弱同步时间间隔 + val renewInterval4Provider = 20 + + //provider强同步时间间隔为renewInterval4Provider * forceBorder4Provider + val forceBorder4Provider = 120 + + //provider-http弱同步时间间隔 + val renewInterval4ProviderHttp = 20 + //20秒 + //provider-http强同步时间间隔renewInterval4ProviderHttp * forceBorder4ProviderHttp + val forceBorder4ProviderHttp = 120 + + + //provider线程第一执行delay时间模值 + val initDelay4HttpProperties = 3000 + + //每个zk节点建立的zkClient数量, mns-zk对单台主机的连接数做了限制 + val singleHostCount4ZK = 2 + + val ENV = ProcessInfoUtil.getAppEnv.toLowerCase + + private var appkeys = List[String]() + + private val appkeysPath = s"$rootPre/$ENV" + + private def getAppFromZK() = { + val testAppkeys = System.getProperty("mnscCacheLoadAppkeys4Test") + val remoteAppkeys =if(StringUtils.isNotEmpty(testAppkeys)){ + testAppkeys.trim.split(",").toList + }else{ + zk.children(appkeysPath).toList + } + + if (remoteAppkeys.nonEmpty) { + appkeys = remoteAppkeys + } + appkeys + } + + def allApp() = { + getAppFromZK() + } + + def allAppkeysList() = { + getAppFromZK().asJava + } + + def allAppkeys(isPar: Boolean) = { + if (isPar) { + mnscCommon.allApp().par + } else { + mnscCommon.allApp() + } + } +} diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/utils/zkCommon.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/utils/zkCommon.scala new file mode 100644 index 0000000..e1890f4 --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/utils/zkCommon.scala @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +package com.meituan.octo.mnsc.utils + +import com.meituan.octo.mnsc.model.Path + +object zkCommon { + private val pre = mnscCommon.rootPre + + def getProtocolPath(appkey: String, env: String, protocol: String) = { + if ("thrift" == protocol) { + s"$pre/$env/$appkey/${Path.provider}" + + } else if ("http" == protocol) { + s"$pre/$env/$appkey/${Path.providerHttp}" + } else { + s"$pre/$env/$appkey/providers/$protocol" + } + } +} diff --git a/nsc/src/main/scala/com/meituan/octo/mnsc/zkWatcher/appProviderWatcher.scala b/nsc/src/main/scala/com/meituan/octo/mnsc/zkWatcher/appProviderWatcher.scala new file mode 100644 index 0000000..1b514f4 --- /dev/null +++ b/nsc/src/main/scala/com/meituan/octo/mnsc/zkWatcher/appProviderWatcher.scala @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.zkWatcher + +import com.meituan.octo.mnsc.dataCache.{appProviderDataCache, appProviderHttpDataCache} +import com.meituan.octo.mnsc.model.{Env, Path} +import com.meituan.octo.mnsc.remote.zk +import com.meituan.octo.mnsc.utils.mnscCommon +import org.apache.curator.framework.api.CuratorWatcher +import org.apache.zookeeper.WatchedEvent +import org.apache.zookeeper.Watcher.Event.{EventType, KeeperState} +import org.slf4j.{Logger, LoggerFactory} + +object appProviderWatcher { + private val LOG: Logger = LoggerFactory.getLogger(appProviderWatcher.getClass) + private val pre = mnscCommon.rootPre + private val prodPath = s"$pre/${Env.prod}" + private var apps = mnscCommon.allApp() + + //watch provider节点下的服务节点是否有变更 + class ProviderWatcher(appkey: String, env: String) extends CuratorWatcher { + def process(event: WatchedEvent): Unit = { + LOG.info(s"ProviderWatcher event $event for appKey|env = $appkey|$env") + val watcherPath = s"$pre/$env/$appkey/${Path.provider}" + + event.getType match { + case EventType.NodeDataChanged => + val watcherPath = event.getPath + val (_, mtime) = zk.getNodeVersion(watcherPath) + appProviderDataCache.mnscWatcherAction(appkey, env, Path.provider.toString) + + val interval = System.currentTimeMillis - mtime + LOG.debug(s"ProviderWatcher process for appKey|env = $appkey|$env --> cost ${interval} ms") + case _ => //do nothing + } + + /*避免reconnect时watcher instance 指数级增加,导致的OOM问题 + 同时,加快新session中Watcher的playback速度,提高网络抖动后自愈的速度 + */ + if(EventType.NodeDataChanged == event.getType || KeeperState.Expired == event.getState){ + zk.addDataWatcher(watcherPath, new ProviderWatcher(appkey, env)) + } + } + } + + //watch provider-http节点下的服务节点是否有变更 + class ProviderHttpWatcher(appkey: String, env: String) extends CuratorWatcher { + def process(event: WatchedEvent): Unit = { + LOG.info(s"ProviderHttpWatcher event $event for appKey|env = $appkey|$env") + + val watcherPath = s"$pre/$env/$appkey/${Path.providerHttp}" + + event.getType match { + case EventType.NodeDataChanged => + val watcherPath = event.getPath + val (_, mtime) = zk.getNodeVersion(watcherPath) + appProviderHttpDataCache.mnscWatcherAction(appkey, env, Path.providerHttp.toString) + + val interval = System.currentTimeMillis - mtime + LOG.debug(s"ProviderHttpWatcher process for appKey|env = $appkey|$env --> cost ${interval} ms") + case _ => //do nothing + } + + /*避免reconnect时watcher instance 指数级增加,导致的OOM问题 + 同时,加快新session中Watcher的playback速度,提高网络抖动后自愈的速度 + */ + if(EventType.NodeDataChanged == event.getType || KeeperState.Expired == event.getState){ + zk.addDataWatcher(watcherPath, new ProviderHttpWatcher(appkey, env)) + } + } + } + + //watch是否有appKey的新增或删除 + class appWatcher(path: String) extends CuratorWatcher { + def process(event: WatchedEvent): Unit = { + LOG.info(s"appWatcher event $event for path=$path") + + event.getType match { + case EventType.NodeChildrenChanged => + val newApps = mnscCommon.allApp() + LOG.info(s"new apps $newApps") + newApps.filter(!apps.contains(_)).foreach { + appkey => registryProviderWatcher4AllEnv(appkey) + } + + appProviderDataCache.deleteNonexistentAppKey() + appProviderHttpDataCache.deleteNonexistentAppKey() + + apps = newApps + + case _ => //do nothing + } + + if(EventType.NodeDataChanged == event.getType || + EventType.NodeChildrenChanged == event.getType || + KeeperState.Expired == event.getState) { + zk.addChildrenWatcher(path, new appWatcher(path)) + } + + } + } + + def registryProviderWatcher4AllEnv(appkey: String) = { + Env.values.foreach { + env => + val providerWatcherPath = s"$pre/$env/$appkey/${Path.provider}" + zk.addDataWatcher(providerWatcherPath, new ProviderWatcher(appkey, env.toString)) + val providerHTTPWatcherPath = s"$pre/$env/$appkey/${Path.providerHttp}" + zk.addDataWatcher(providerHTTPWatcherPath, new ProviderHttpWatcher(appkey, env.toString)) + } + } + + def initWatcherApp() = { + val watcherPath = prodPath + zk.addChildrenWatcher(watcherPath, new appWatcher(prodPath)) + } + + def initWatcherProvider() = { + LOG.info("init provider watcher") + apps.par.foreach { + appkey => + registryProviderWatcher4AllEnv(appkey) + } + } + + def initWatcher() = { + initWatcherApp() + initWatcherProvider() + } +} diff --git a/nsc/src/test/java/com/meituan/octo/mnsc/MNSCacheApiTest.java b/nsc/src/test/java/com/meituan/octo/mnsc/MNSCacheApiTest.java new file mode 100644 index 0000000..7c201d9 --- /dev/null +++ b/nsc/src/test/java/com/meituan/octo/mnsc/MNSCacheApiTest.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.meituan.octo.mnsc.service.apiProviders; +import com.meituan.octo.mnsc.utils.mnscCommon; +import com.meituan.octo.mnsc.service.apiService; +import org.junit.Test; +import play.libs.Json; + +import java.util.HashMap; + +public class MNSCacheApiTest extends SpringBaseTest { + @Test + public void getProviders() throws Exception { + assert(Json.parse(apiProviders.getProviders("com.sankuai.inf.sg_sentinel", 3, "thrift")).get("ret").asInt() == 200); + assert(Json.parse(apiProviders.getProviders("com.sankuai.inf.msgp", 3, "http")).get("ret").asInt() == 200); + assert(Json.parse(apiProviders.getProviders("com.sankuai.invalid.appkey", 3, "thrift")).get("ret").asInt() == 404); + } + + @Test + public void getAllAppkeys() throws Exception { + assert(!mnscCommon.allAppkeysList().isEmpty()); + } + + @Test + public void getSentinels() throws Exception { + String ip = "10.20.50.135"; + String env = "prod"; + String appkey = "com.sankuai.inf.sg_sentinel"; + HashMap result = new ObjectMapper().readValue(apiService.getServiceList(appkey.trim(), env.trim(), ip.trim()), HashMap.class); + System.out.println(result.get("data")); + assert(result.get("ret").equals(200)); + } +} \ No newline at end of file diff --git a/nsc/src/test/java/com/meituan/octo/mnsc/MNSCacheServiceTest.java b/nsc/src/test/java/com/meituan/octo/mnsc/MNSCacheServiceTest.java new file mode 100644 index 0000000..480b3e7 --- /dev/null +++ b/nsc/src/test/java/com/meituan/octo/mnsc/MNSCacheServiceTest.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc; + +import com.meituan.octo.mnsc.service.mnscService; +import com.meituan.octo.mnsc.web.api.ProvidersController; +import com.octo.mnsc.idl.thrift.model.mnsc_dataConstants; +import com.octo.mnsc.idl.thrift.model.MnsRequest; +import com.octo.mnsc.idl.thrift.model.Protocols; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +public class MNSCacheServiceTest extends SpringBaseTest{ + static final Logger LOG = LoggerFactory.getLogger(ProvidersController.class); + + @Test + public void getAppKeyByIP() throws Exception { + long start = System.currentTimeMillis(); + assert(!mnscService.getAppkeyListByIP("10.72.221.226").isEmpty()); + System.out.println(System.currentTimeMillis() - start); + } + + @Test + public void getProvidersByIP() throws Exception { + assert(!mnscService.getProvidersByIP("10.72.221.226").defaultMNSCache.isEmpty()); + } + + @Test + public void getMNSCacheWithVersionCheck() throws Exception { + MnsRequest request = new MnsRequest(); + request.appkey = "com.sankuai.inf.sg_sentinel"; + request.env = "prod"; + request.protoctol= Protocols.THRIFT; + assert(mnscService.getMnsc(request).code == mnsc_dataConstants.SUCCESS); + + request.appkey = "com.sankuai.invalid.appkey"; + assert(mnscService.getMnsc(request).code == mnsc_dataConstants.NOT_FOUND); + + request.appkey = "com.sankuai.inf.msgp"; + request.protoctol= Protocols.HTTP; + assert(mnscService.getMnsc(request).code == mnsc_dataConstants.SUCCESS); + + request.appkey = "com.sankuai.invalid.appkey"; + assert(mnscService.getMnsc(request).code == mnsc_dataConstants.NOT_FOUND); + } + + @Test + public void getMNSCacheByAppkeys() throws Exception { + List appkeys = new ArrayList(); + appkeys.add("com.sankuai.inf.sg_sentinel"); + appkeys.add("com.sankuai.inf.msgp"); + appkeys.add("com.sankuai.invalid.appkey"); + assert(!mnscService.getMNSCacheByAppkeys(appkeys, "thrift").cache.get("com.sankuai.inf.sg_sentinel").get("prod").isEmpty()); + assert(mnscService.getMNSCacheByAppkeys(appkeys, "thrift").cache.get("com.sankuai.invalid.appkey").get("prod").isEmpty()); + + assert(!mnscService.getMNSCacheByAppkeys(appkeys, "http").cache.get("com.sankuai.inf.msgp").get("prod").isEmpty()); + assert(mnscService.getMNSCacheByAppkeys(appkeys, "http").cache.get("com.sankuai.invalid.appkey").get("prod").isEmpty()); + } + + @Test + public void getMNSCache() throws Exception { + assert(!mnscService.getMnsc("com.sankuai.inf.sg_sentinel","0|0|1","prod").defaultMNSCache.isEmpty()); + assert(mnscService.getMnsc("com.sankuai.inf.sg_sentinel","0|0|99999999","prod").code == mnsc_dataConstants.NOT_MODIFIED); + } + + @Test + public void getMNSCacheHttp() throws Exception { + assert(!mnscService.getMNSCache4HLB("com.sankuai.inf.msgp","0|0|1","prod").defaultMNSCache.isEmpty()); + assert(mnscService.getMNSCache4HLB("com.sankuai.inf.msgp","0|0|99999999","prod").code == mnsc_dataConstants.NOT_MODIFIED); + + assert(mnscService.getMnsc("com.sankuai.invalid.appkey","0|0|1","prod").code == mnsc_dataConstants.NOT_FOUND); + assert(mnscService.getMNSCache4HLB("com.sankuai.invalid.appkey","0|0|99999999","prod").code == mnsc_dataConstants.NOT_FOUND); + } + /*@Test + public void getSG_Agent() throws Exception { + System.out.println(apiService.getServiceList("com.sankuai.inf.sg_sentinel", "test", "10.22.16.146")); + }*/ + +} diff --git a/nsc/src/test/java/com/meituan/octo/mnsc/SpringBaseTest.java b/nsc/src/test/java/com/meituan/octo/mnsc/SpringBaseTest.java new file mode 100644 index 0000000..29369de --- /dev/null +++ b/nsc/src/test/java/com/meituan/octo/mnsc/SpringBaseTest.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration({"classpath:applicationContext.xml"}) +public class SpringBaseTest { + + @BeforeClass + public static void init(){ + String appkeys = "com.sankuai.inf.sg_sentinel,com.sankuai.inf.msgp,com.sankuai.octo.tmy"; + System.setProperty("mnscCacheLoadAppkeys4Test", appkeys); + } + @Test + public void test(){} +} diff --git a/nsc/src/test/resources/applicationContext.xml b/nsc/src/test/resources/applicationContext.xml new file mode 100644 index 0000000..c4b2e63 --- /dev/null +++ b/nsc/src/test/resources/applicationContext.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + diff --git a/nsc/src/test/resources/log4j2.xml b/nsc/src/test/resources/log4j2.xml new file mode 100644 index 0000000..4e4c30a --- /dev/null +++ b/nsc/src/test/resources/log4j2.xml @@ -0,0 +1,28 @@ + + + + com.meituan.octo.mnsc + mnsc-server + + + + + + + + %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/nsc/src/test/resources/webmvc-config.xml b/nsc/src/test/resources/webmvc-config.xml new file mode 100644 index 0000000..cc918f8 --- /dev/null +++ b/nsc/src/test/resources/webmvc-config.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + diff --git a/nsc/src/test/scala/com/meituan/octo/mnsc/test/EnvSuite.scala b/nsc/src/test/scala/com/meituan/octo/mnsc/test/EnvSuite.scala new file mode 100644 index 0000000..3be0091 --- /dev/null +++ b/nsc/src/test/scala/com/meituan/octo/mnsc/test/EnvSuite.scala @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.test + +import com.meituan.octo.mnsc.model.Env +import org.junit.runner.RunWith +import org.scalatest.junit.JUnitRunner +import org.scalatest.{BeforeAndAfter, FunSuite} +import org.junit.Assert.assertEquals + +@RunWith(classOf[JUnitRunner]) +class EnvSuite extends FunSuite with BeforeAndAfter { + test("envInvalid") { + assertEquals(false, Env.isValid(4)) + assertEquals(true, Env.isValid(1)) + assertEquals(true, Env.isValid(2)) + assertEquals(true, Env.isValid(3)) + } +} + diff --git a/nsc/src/test/scala/com/meituan/octo/mnsc/test/ServiceSuite.scala b/nsc/src/test/scala/com/meituan/octo/mnsc/test/ServiceSuite.scala new file mode 100644 index 0000000..8f2f920 --- /dev/null +++ b/nsc/src/test/scala/com/meituan/octo/mnsc/test/ServiceSuite.scala @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.test + +import com.octo.mnsc.idl.thrift.service.MNSCacheService +import org.apache.thrift.protocol.{TBinaryProtocol, TProtocol} +import org.apache.thrift.transport.{TFramedTransport, TSocket} +import org.joda.time.DateTime +import org.junit.runner.RunWith +import org.scalatest.junit.JUnitRunner +import org.scalatest.{BeforeAndAfter, FunSuite} + +import scala.collection.parallel.ForkJoinTaskSupport + +@RunWith(classOf[JUnitRunner]) +class ServiceSuite extends FunSuite with BeforeAndAfter { + + test("service") { + val timeout = 3000 + val ip = "127.0.0.1" + val port = 8091 + val transport = new TFramedTransport(new TSocket(ip, port, timeout), 16384000) + val protocol: TProtocol = new TBinaryProtocol(transport) + val mnsc = new MNSCacheService.Client(protocol) + val appkey = "com.sankuai.cos.mtconfi" + val env = "prod" + // val path = List("/mns/sankuai", env, appkey, Path.provider).mkString("/") + // val version = zk.getNodeVersion(path) + transport.open + while (true) { + val start = new DateTime().getMillis + println(mnsc.getMNSCache(appkey, "0", env)) + val end = new DateTime().getMillis + println(s"cost ${end - start}") + Thread.sleep(2000) + } + } + + test("par") { + val a = (0 to 30).toList.par + a.tasksupport = new ForkJoinTaskSupport(new scala.concurrent.forkjoin.ForkJoinPool(1000)) + val b = (0 to 100000).toList.par + b.tasksupport = new ForkJoinTaskSupport(new scala.concurrent.forkjoin.ForkJoinPool(1000)) + val result = a.map { + x => + val at = Thread.currentThread().getName + println(b.map(x => Thread.currentThread().getName).distinct.length) + at + }.distinct.length + println("ss" + result) + } +} diff --git a/nsc/src/test/scala/com/meituan/octo/mnsc/test/mnscDataCacheSuite.scala b/nsc/src/test/scala/com/meituan/octo/mnsc/test/mnscDataCacheSuite.scala new file mode 100644 index 0000000..48c9f19 --- /dev/null +++ b/nsc/src/test/scala/com/meituan/octo/mnsc/test/mnscDataCacheSuite.scala @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.test + +import com.meituan.octo.mnsc.dataCache._ +import com.meituan.octo.mnsc.model.Path +import com.meituan.octo.mnsc.service.mnscService +import com.octo.mnsc.idl.thrift.model.{mnsc_dataConstants, MnsRequest, Protocols} +import org.junit.runner.RunWith +import org.scalatest.junit.JUnitRunner +import org.scalatest.{BeforeAndAfter, FunSuite} + + +@RunWith(classOf[JUnitRunner]) +class mnscServiceSuite extends FunSuite with BeforeAndAfter { + test("test ip affiliation") { + val apps = new java.util.ArrayList[String]() + apps.add("com.sankuai.inf.sg_sentinel") + apps.add("com.sankuai.inf.msgp") + val thrift_cache = mnscService.getMNSCacheByAppkeys(apps, "thrift") + println(thrift_cache.cache) + assert(thrift_cache.cache.get("com.sankuai.inf.sg_sentinel").get("prod").isEmpty) + val http_cache = mnscService.getMNSCacheByAppkeys(apps, "http") + assert(http_cache.cache.get("com.sankuai.inf.msgp").get("prod").isEmpty) + + assert(mnscService.getAppkeyListByIP("10.72.221.226").isEmpty) + assert(mnscService.getProvidersByIP("10.72.221.226").defaultMNSCache.isEmpty) + + appProviderDataCache.renewAllProviderForce(Path.provider.toString, true) + appProviderHttpDataCache.renewAllProviderForce(Path.providerHttp.toString, true) + + assert(!mnscService.getAppkeyListByIP("10.72.221.226").isEmpty) + assert(!mnscService.getProvidersByIP("10.72.221.226").defaultMNSCache.isEmpty) + } + + test("get MNSCache service API1") { + assert(!mnscService.getMnsc("com.sankuai.inf.sg_sentinel","0|0|1","prod").defaultMNSCache.isEmpty) + assert(mnscService.getMnsc("com.sankuai.inf.sg_sentinel","0|0|99999999","prod").code == mnsc_dataConstants.NOT_MODIFIED) + assert(!mnscService.getMNSCache4HLB("com.sankuai.inf.msgp","0|0|1","prod").defaultMNSCache.isEmpty) + assert(mnscService.getMNSCache4HLB("com.sankuai.inf.msgp","0|0|99999999","prod").code == mnsc_dataConstants.NOT_MODIFIED) + + assert(mnscService.getMnsc("com.sankuai.invalid.appkey","0|0|1","prod").code == mnsc_dataConstants.NOT_FOUND) + assert(mnscService.getMNSCache4HLB("com.sankuai.invalid.appkey","0|0|99999999","prod").code == mnsc_dataConstants.NOT_FOUND) + } + + test("get MNSCache service API2") { + val request = new MnsRequest() + request.appkey = "com.sankuai.inf.sg_sentinel" + request.env = "prod" + request.protoctol= Protocols.THRIFT + assert(mnscService.getMnsc(request).code == mnsc_dataConstants.SUCCESS) + + request.appkey = "com.sankuai.invalid.appkey" + assert(mnscService.getMnsc(request).code == mnsc_dataConstants.NOT_FOUND) + + request.appkey = "com.sankuai.inf.msgp" + request.protoctol= Protocols.HTTP + assert(mnscService.getMnsc(request).code == mnsc_dataConstants.SUCCESS) + + request.appkey = "com.sankuai.invalid.appkey" + assert(mnscService.getMnsc(request).code == mnsc_dataConstants.NOT_FOUND) + } +} \ No newline at end of file diff --git a/nsc/src/test/scala/com/meituan/octo/mnsc/test/providerCacheSuite.scala b/nsc/src/test/scala/com/meituan/octo/mnsc/test/providerCacheSuite.scala new file mode 100644 index 0000000..e5fcd04 --- /dev/null +++ b/nsc/src/test/scala/com/meituan/octo/mnsc/test/providerCacheSuite.scala @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.test + +import com.meituan.octo.mnsc.dataCache._ +import com.meituan.octo.mnsc.model.Path +import com.meituan.octo.mnsc.model.service.CacheValue +import com.meituan.octo.mnsc.service.apiProviders +import com.octo.naming.common.thrift.model.SGService +import org.junit.runner.RunWith +import org.scalatest.junit.JUnitRunner +import org.scalatest.{BeforeAndAfter, FunSuite} + + +@RunWith(classOf[JUnitRunner]) +class providerCacheSuite extends FunSuite with BeforeAndAfter { + test("getPovidersCache") { + val thrift_valid_services = appProvidersCommCache.getProviderCache("com.sankuai.inf.sg_sentinel", 3, "thrift") + assert(thrift_valid_services.Providers.nonEmpty) + val thrift_invalid_services = appProvidersCommCache.getProviderCache("com.sankuai.inf.sg_sentinel", 3, "http") + assert(thrift_invalid_services.Providers.isEmpty) + + val http_valid_services = appProvidersCommCache.getProviderCache("com.sankuai.inf.msgp", 3, "thrift") + assert(http_valid_services.Providers.isEmpty) + val http_invalid_services = appProvidersCommCache.getProviderCache("com.sankuai.inf.msgp", 3, "http") + assert(http_invalid_services.Providers.nonEmpty) + + val api_service = apiProviders.getProviders("com.sankuai.inf.sg_sentinel", 3, "thrift") + assert(api_service.nonEmpty) + } + + test("get provider cache from remote") { + //appProviderDataCache.renewAllProviderForce(Path.provider.toString, true) + val emptyValue = CacheValue("invalid-version", List[SGService]()) + + //thrift + val local_cache = appProviderDataCache.getProviderCache("com.sankuai.inf.sg_sentinel", "prod", false) + assert(local_cache.getOrElse(emptyValue).version == "invalid-version") + assert(local_cache.getOrElse(emptyValue).SGServices.isEmpty) + + val remote_cache = appProviderDataCache.getProviderCache("com.sankuai.inf.sg_sentinel", "prod", true) + assert(remote_cache.getOrElse(emptyValue).version != "invalid-version") + assert(remote_cache.getOrElse(emptyValue).SGServices.nonEmpty) + + //http + val local_cache_http = appProviderHttpDataCache.getProviderHttpCache("com.sankuai.inf.msgp", "prod", false) + assert(local_cache_http.getOrElse(emptyValue).version == "invalid-version") + assert(local_cache_http.getOrElse(emptyValue).SGServices.isEmpty) + + val remote_cache_http = appProviderHttpDataCache.getProviderHttpCache("com.sankuai.inf.msgp", "prod", true) + assert(remote_cache_http.getOrElse(emptyValue).version != "invalid-version") + assert(remote_cache_http.getOrElse(emptyValue).SGServices.nonEmpty) + } + + test("get provider cache from local") { + val emptyValue = CacheValue("invalid-version", List[SGService]()) + + appProviderDataCache.renewAllProviderForce(Path.provider.toString, true) + val cache = appProviderDataCache.getProviderCache("com.sankuai.inf.sg_sentinel", "prod", false) + assert(cache.getOrElse(emptyValue).version != "invalid-version") + assert(cache.getOrElse(emptyValue).SGServices.nonEmpty) + val invalidCache = appProviderDataCache.getProviderCache("com.sankuai.invalid.test", "prod", false) + assert(invalidCache.getOrElse(emptyValue).version == "invalid-version") + assert(invalidCache.getOrElse(emptyValue).SGServices.isEmpty) + + appProviderHttpDataCache.renewAllProviderForce(Path.providerHttp.toString, true) + val cache_http = appProviderHttpDataCache.getProviderHttpCache("com.sankuai.inf.msgp", "prod", false) + assert(cache_http.getOrElse(emptyValue).version != "invalid-version") + assert(cache_http.getOrElse(emptyValue).SGServices.nonEmpty) + + val invalid_cache_http = appProviderHttpDataCache.getProviderHttpCache("com.sankuai.invalid.test", "prod", false) + assert(invalid_cache_http.getOrElse(emptyValue).version == "invalid-version") + assert(invalid_cache_http.getOrElse(emptyValue).SGServices.isEmpty) + } +} + +@RunWith(classOf[JUnitRunner]) +class providerCacheScheduleSuite extends FunSuite with BeforeAndAfter { + test("schedule job worker") { + val emptyValue = CacheValue("invalid-version", List[SGService]()) + val cache = appProviderDataCache.getProviderCache("com.sankuai.inf.sg_sentinel", "prod", false) + assert(cache.getOrElse(emptyValue).version == "invalid-version") + + val cache_http = appProviderHttpDataCache.getProviderHttpCache("com.sankuai.inf.msgp", "prod", false) + assert(cache_http.getOrElse(emptyValue).version == "invalid-version") + + appProviderHttpDataCache.doRenew() + appProviderDataCache.doRenew() + Thread.sleep(1000*60) + + val cache_valid = appProviderDataCache.getProviderCache("com.sankuai.inf.sg_sentinel", "prod", false) + assert(cache_valid.getOrElse(emptyValue).version != "invalid-version") + + val invalidCache = appProviderDataCache.getProviderCache("com.sankuai.invalid.test", "prod", false) + assert(invalidCache.getOrElse(emptyValue).version == "invalid-version") + + val cache_http_valid = appProviderHttpDataCache.getProviderHttpCache("com.sankuai.inf.msgp", "prod", false) + assert(cache_http_valid.getOrElse(emptyValue).version != "invalid-version") + + val invalid_cache_http = appProviderHttpDataCache.getProviderHttpCache("com.sankuai.invalid.test", "prod", false) + assert(invalid_cache_http.getOrElse(emptyValue).version == "invalid-version") + + val ip_valid = "10.72.221.226" + val ip_invalid = "invalid_ip" + assert(appProviderDataCache.getProvidersByIP(ip_valid).nonEmpty) + assert(appProviderDataCache.getProvidersByIP(ip_invalid).isEmpty) + + val http_ip_valid = "10.24.124.94" + assert(appProviderHttpDataCache.getProvidersByIP(http_ip_valid).nonEmpty) + assert(appProviderHttpDataCache.getProvidersByIP(ip_invalid).isEmpty) + } +} \ No newline at end of file diff --git a/nsc/src/test/scala/com/meituan/octo/mnsc/test/zkSuite.scala b/nsc/src/test/scala/com/meituan/octo/mnsc/test/zkSuite.scala new file mode 100644 index 0000000..0655a7f --- /dev/null +++ b/nsc/src/test/scala/com/meituan/octo/mnsc/test/zkSuite.scala @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.meituan.octo.mnsc.test + +import com.meituan.octo.mnsc.model.Path +import com.meituan.octo.mnsc.remote.zk +import com.meituan.octo.mnsc.service.apiProviders +import com.meituan.octo.mnsc.utils.mnscCommon +import com.meituan.octo.mnsc.zkWatcher.appProviderWatcher +import com.octo.naming.common.thrift.model.SGService +import org.apache.curator.framework.api.CuratorWatcher +import org.apache.zookeeper.WatchedEvent +import org.junit.runner.RunWith +import org.scalatest.{BeforeAndAfter, FunSuite} +import org.scalatest.junit.JUnitRunner + +@RunWith(classOf[JUnitRunner]) +class zkSuite extends FunSuite with BeforeAndAfter with CuratorWatcher { + val env = "prod" + val appkey = "com.sankuai.octo.tmy" + val path = s"${mnscCommon.rootPre}/$env/$appkey/${Path.provider}" + + val service = new SGService() + service.setAppkey(appkey) + .setVersion("thrift") + .setIp("10.4.229.159") + .setPort(8830) + .setWeight(10) + .setStatus(4) + .setRole(0) + .setEnvir(3) + .setLastUpdateTime(1543395127) + .setFweight(10.0) + .setServerType(0) + .setProtocol("thrift") + .setHeartbeatSupport(0) + + test("test zk addDataWatcher") { + zk.addDataWatcher(path, this) + val services = new java.util.ArrayList[SGService]() + services.add(service) + Thread.sleep(1000*5) + apiProviders.postProviders(services) + Thread.sleep(1000*5) + } + + override def process(event: WatchedEvent): Unit = { + assert(event.getPath == path) + println(zk.getData(event.getPath)) + zk.addDataWatcher(path, this) + } + + + test ("test zk addChildrenWatcher") { + val services = new java.util.ArrayList[SGService]() + services.add(service) + apiProviders.deleteProviders(services) + + zk.addChildrenWatcher(path,this) + Thread.sleep(1000*5) + apiProviders.postProviders(services) + Thread.sleep(1000*5) + } + + test ("test version check") { + assert(zk.versionCompare("0|0|1", "0|0|2", false, (arg1: Long, arg2: Long) => arg1 <= arg2)) + assert(!zk.versionCompare("0|0", "0|0|2", false, (arg1: Long, arg2: Long) => arg1 <= arg2)) + assert(!zk.versionCompare("0|0|1", "0|0", false, (arg1: Long, arg2: Long) => arg1 <= arg2)) + assert(!zk.versionCompare("0|0|3", "0|0|2", true, (arg1: Long, arg2: Long) => arg1 <= arg2)) + assert(zk.versionCompare("0|0", "0|0|2", true, (arg1: Long, arg2: Long) => arg1 <= arg2)) + assert(zk.versionCompare("0|0|3", "0|0", true, (arg1: Long, arg2: Long) => arg1 <= arg2)) + } +} + +@RunWith(classOf[JUnitRunner]) +class zkProviderSuite extends FunSuite with BeforeAndAfter { + val appkey = "com.sankuai.octo.tmy" + + val service = new SGService() + service.setAppkey(appkey) + .setVersion("thrift") + .setIp("10.4.229.159") + .setPort(8830) + .setWeight(10) + .setStatus(4) + .setRole(0) + .setEnvir(3) + .setLastUpdateTime(1543395127) + .setFweight(10.0) + .setServerType(0) + .setProtocol("thrift") + .setHeartbeatSupport(0) + + test ("init watcher for app") { + appProviderWatcher.initWatcher() + + val services = new java.util.ArrayList[SGService]() + services.add(service) + apiProviders.postProviders(services) + Thread.sleep(1000*3) + + apiProviders.postProviders(services) + Thread.sleep(1000*2) + } + + service.setProtocol("http") + test ("init watcher for http app") { + appProviderWatcher.initWatcher() + + val services = new java.util.ArrayList[SGService]() + services.add(service) + apiProviders.postProviders(services) + Thread.sleep(1000*3) + + apiProviders.postProviders(services) + Thread.sleep(1000*2) + } + + //TODO:watch是否有appKey的新增或删除 +} \ No newline at end of file diff --git a/scanner/.gitignore b/scanner/.gitignore new file mode 100644 index 0000000..82eca33 --- /dev/null +++ b/scanner/.gitignore @@ -0,0 +1,25 @@ +/target/ +!.mvn/wrapper/maven-wrapper.jar + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/build/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ \ No newline at end of file diff --git a/scanner/README.md b/scanner/README.md new file mode 100644 index 0000000..e673822 --- /dev/null +++ b/scanner/README.md @@ -0,0 +1,56 @@ +# OCTO Scanner 介绍 + +## 背景描述 +Scaner 是 OCTO 服务治理体系内的一个独立的服务健康检查子系统. + +开发语言: Java + +运行环境要求: JDK 1.8及以上、maven3、zookeeper + +组件依赖: [Dorado](https://github.com/Meituan-Dianping/octo-rpc/tree/master/dorado) + +主要功能点: + +1.持续检测 OCTO 系统内所有服务节点的端口存活状态, 并自动维护节点的状态信息 + + +## 整体架构 +![架构图](./docs/img/architecture.png) + +## 设计细节 +### 自定义心跳 +对于 OCTO 系统内的服务提供者,Scanner支持使用应用层心跳来代替端口检测,能够更准确地判断服务节点的存活状态。 + +### 快慢线程 +Scanner的扫描线程分为两类,正常节点和异常节点分为两个线程池扫描,用户也可以自定义两个线程池的线程数。 + +### 超时重试 +对于检测超时的节点,Scanner会进行重试探测,避免网络抖动或闪断带来的影响 + +### 检测关键参数 + 端口连通性检查 -> Socket Refused. + 端口超时检查 -> Socket Timeout + +### 核心功能图示 +1.Provider 状态转换图 +![状态转换图](./docs/img/providerstatus.png) + +## 快速上手 +### 编译安装dorado到本地maven仓库 +参考[Dorado 源码编译说明](https://github.com/Meituan-Dianping/octo-rpc/blob/master/dorado/dorado-doc/manual-developer/Compile.md) + +### 打包运行Scanner +```bash +git clone git@github.com:Meituan-Dianping/octo-ns.git + +cd octo-ns/scanner + +mvn clean package -Dmaven.test.skip=true + +cd target +#需要在启动参数中指定zookeeper地址,也可以在src/main/resources/application.yaml指定 +java -Dzookeeper.url=xxx.xxx.xxx.xxx:xxxx -jar octo-scanner-0.0.1-SNAPSHOT.jar #日志会输出到当前路径下"octo-scanner/log/octo-scanner.log"文件 + +``` + + diff --git a/scanner/docs/img/architecture.png b/scanner/docs/img/architecture.png new file mode 100644 index 0000000..90bec8d Binary files /dev/null and b/scanner/docs/img/architecture.png differ diff --git a/scanner/docs/img/providerstatus.png b/scanner/docs/img/providerstatus.png new file mode 100644 index 0000000..cc6a52d Binary files /dev/null and b/scanner/docs/img/providerstatus.png differ diff --git a/scanner/pom.xml b/scanner/pom.xml new file mode 100644 index 0000000..54dba81 --- /dev/null +++ b/scanner/pom.xml @@ -0,0 +1,78 @@ + + + 4.0.0 + + com.sankuai.octo + octo-scanner + 0.0.1-SNAPSHOT + jar + + octo-scanner + octo scanner open source + + + org.springframework.boot + spring-boot-starter-parent + 1.5.18.RELEASE + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-logging + + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + + org.apache.curator + curator-framework + 2.12.0 + + + + com.alibaba + fastjson + 1.2.47 + + + + com.meituan.octo + dorado + 1.0.0-SNAPSHOT + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/scanner/src/main/java/com/meituan/octo/mns/scanner/OctoScannerApplication.java b/scanner/src/main/java/com/meituan/octo/mns/scanner/OctoScannerApplication.java new file mode 100644 index 0000000..0e80b98 --- /dev/null +++ b/scanner/src/main/java/com/meituan/octo/mns/scanner/OctoScannerApplication.java @@ -0,0 +1,30 @@ +/* + * Copyright 2018 Meituan Dianping. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.meituan.octo.mns.scanner; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; + +@SpringBootApplication +@EnableScheduling +public class OctoScannerApplication { + + public static void main(String[] args) { + SpringApplication.run(OctoScannerApplication.class, args); + } +} diff --git a/scanner/src/main/java/com/meituan/octo/mns/scanner/configuration/CuratorConfiguration.java b/scanner/src/main/java/com/meituan/octo/mns/scanner/configuration/CuratorConfiguration.java new file mode 100644 index 0000000..1e99545 --- /dev/null +++ b/scanner/src/main/java/com/meituan/octo/mns/scanner/configuration/CuratorConfiguration.java @@ -0,0 +1,34 @@ +/* + * Copyright 2018 Meituan Dianping. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.meituan.octo.mns.scanner.configuration; + +import org.apache.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.retry.RetryForever; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class CuratorConfiguration { + @Bean + public CuratorFramework curatorFramework(@Value("${zookeeper.url}") String zkUrl) { + CuratorFramework client = CuratorFrameworkFactory.newClient(zkUrl, 10000, 10000, new RetryForever(10000)); + client.start(); + return client; + } +} diff --git a/scanner/src/main/java/com/meituan/octo/mns/scanner/configuration/ExecutorConfiguration.java b/scanner/src/main/java/com/meituan/octo/mns/scanner/configuration/ExecutorConfiguration.java new file mode 100644 index 0000000..8fea4cf --- /dev/null +++ b/scanner/src/main/java/com/meituan/octo/mns/scanner/configuration/ExecutorConfiguration.java @@ -0,0 +1,38 @@ +/* + * Copyright 2018 Meituan Dianping. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.meituan.octo.mns.scanner.configuration; + +import com.meituan.dorado.common.thread.DefaultThreadFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +@Configuration +public class ExecutorConfiguration { + @Bean("aliveCheckExecutor") + public Executor aliveCheckExecutor(@Value("${executor.alive.threadCount}") int threadCount) { + return Executors.newFixedThreadPool(threadCount, new DefaultThreadFactory("aliveCheckExecutor")); + } + + @Bean("deadCheckExecutor") + public Executor deadCheckExecutor(@Value("${executor.dead.threadCount}") int threadCount) { + return Executors.newFixedThreadPool(threadCount, new DefaultThreadFactory("deadCheckExecutor")); + } +} diff --git a/scanner/src/main/java/com/meituan/octo/mns/scanner/model/Provider.java b/scanner/src/main/java/com/meituan/octo/mns/scanner/model/Provider.java new file mode 100644 index 0000000..98cc603 --- /dev/null +++ b/scanner/src/main/java/com/meituan/octo/mns/scanner/model/Provider.java @@ -0,0 +1,71 @@ +/* + * Copyright 2018 Meituan Dianping. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.meituan.octo.mns.scanner.model; + +public class Provider { + private String ip; + private int port; + private String env; + private String appkey; + + public String getIpPort() { + return ip + ":" + port; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getEnv() { + return env; + } + + public void setEnv(String env) { + this.env = env; + } + + public String getAppkey() { + return appkey; + } + + public void setAppkey(String appkey) { + this.appkey = appkey; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("Provider{"); + sb.append("ip='").append(ip).append('\''); + sb.append(", port=").append(port); + sb.append(", env='").append(env).append('\''); + sb.append(", appkey='").append(appkey).append('\''); + sb.append('}'); + return sb.toString(); + } +} diff --git a/scanner/src/main/java/com/meituan/octo/mns/scanner/service/ProviderDetectService.java b/scanner/src/main/java/com/meituan/octo/mns/scanner/service/ProviderDetectService.java new file mode 100644 index 0000000..9360e1d --- /dev/null +++ b/scanner/src/main/java/com/meituan/octo/mns/scanner/service/ProviderDetectService.java @@ -0,0 +1,108 @@ +/* + * Copyright 2018 Meituan Dianping. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.meituan.octo.mns.scanner.service; + +import com.alibaba.fastjson.JSONObject; +import com.meituan.octo.mns.scanner.model.Provider; +import com.meituan.octo.mns.scanner.util.Constant; +import com.meituan.octo.mns.scanner.util.SocketDetector; +import com.meituan.octo.mns.scanner.util.heartbeat.HeartbeatDetector; +import org.apache.curator.framework.CuratorFramework; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.concurrent.Executor; +import java.util.regex.Pattern; + +@Service +public class ProviderDetectService { + private static final Logger log = LoggerFactory.getLogger(ProviderDetectService.class); + private static final Pattern IP_PORT_PATTERN = Pattern.compile("\\d+.\\d+.\\d+.\\d+:\\d+"); + + @Value("${zookeeper.basePath}") + private String basePath; + + @Autowired + private CuratorFramework zkClient; + + @Autowired + private Executor aliveCheckExecutor; + + @Autowired + private Executor deadCheckExecutor; + + @Autowired + private ProviderUpdateService updateService; + + public void detect(long round, Provider provider) { + if (IP_PORT_PATTERN.matcher(provider.getIpPort()).matches()) { + JSONObject providerJson = getProviderJson(provider); + if (providerJson != null) { + int originalStatus = providerJson.getInteger("status"); + Executor executor = null; + + if (originalStatus == Constant.STATUS_STOPPED) { + log.info("round={}, detecting provider:{}, status:{}", round, provider, Constant.STATUS_STOPPED); + return; + } else if (originalStatus == Constant.STATUS_ALIVE) { + executor = aliveCheckExecutor; + } else { + executor = deadCheckExecutor; + } + + executor.execute(() -> { + try { + Integer heartbeatType = providerJson.getInteger("heartbeatSupport"); + if (heartbeatType == null) { + heartbeatType = 0; + } + int status; + if (Constant.HEARTBEAT_SUPPORT_SCANNER == heartbeatType + || Constant.HEARTBEAT_SUPPORT_BOTH == heartbeatType) { + status = HeartbeatDetector.detect(provider.getIp(), provider.getPort()); + } else { + status = SocketDetector.detect(provider.getIp(), provider.getPort()); + } + log.info("round={}, detecting provider:{}, status:{}", round, provider, status); + if (status != originalStatus) { + updateService.update(round, provider, providerJson, status); + } + } catch (Exception e) { + log.error("", e); + } + }); + } + } else { + log.warn("invalid provider: {} ", provider); + } + } + + private JSONObject getProviderJson(Provider provider) { + try { + byte[] data = zkClient.getData().forPath( + basePath + "/" + provider.getEnv() + "/" + provider.getAppkey() + "/provider/" + provider + .getIpPort()); + return JSONObject.parseObject(new String(data)); + } catch (Exception e) { + log.warn("get provider json exception:{}, message:{}", e.getClass(), e.getMessage()); + } + return null; + } +} diff --git a/scanner/src/main/java/com/meituan/octo/mns/scanner/service/ProviderScanService.java b/scanner/src/main/java/com/meituan/octo/mns/scanner/service/ProviderScanService.java new file mode 100644 index 0000000..d9e0f99 --- /dev/null +++ b/scanner/src/main/java/com/meituan/octo/mns/scanner/service/ProviderScanService.java @@ -0,0 +1,118 @@ +/* + * Copyright 2018 Meituan Dianping. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.meituan.octo.mns.scanner.service; + +import com.meituan.octo.mns.scanner.model.Provider; +import org.apache.curator.framework.CuratorFramework; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Service +public class ProviderScanService { + private static final Logger log = LoggerFactory.getLogger(ProviderScanService.class); + private static final Pattern IP_PORT_PATTERN = Pattern.compile("\\d+.\\d+.\\d+.\\d+:\\d+"); + private final AtomicLong scanRoundCounter = new AtomicLong(1); + private final String[] ENV_LIST = new String[] { "prod", "stage", "test" }; + @Value("${zookeeper.basePath}") + private String basePath; + + @Autowired + private CuratorFramework zkClient; + + @Autowired + private ProviderDetectService detectService; + + @Scheduled(fixedRate = 5000) + public void scanZk() { + try { + long start = System.currentTimeMillis(); + long round = scanRoundCounter.getAndIncrement(); + Set appkeys = getAllAppkeys(); + appkeys.parallelStream().forEach(appkey -> { + log.info("round={}, scan appkey:{}", round, appkey); + try { + List providers = getProviders(appkey); + for (Provider provider : providers) { + try { + detectService.detect(round, provider); + } catch (Exception e) { + log.error("scan provider:{} exception:{}, message:{}", provider, e.getCause(), + e.getMessage()); + } + } + } catch (Exception e) { + log.error("scan appkey:{} exception:{}, message:{}", appkey, e.getCause(), e.getMessage()); + } + }); + long end = System.currentTimeMillis(); + log.info("round={}, scan {} appkeys cost {} ms", round, appkeys.size(), (end - start)); + } catch (Exception e) { + log.error("scan zk exception:{}, message:{}", e.getCause(), e.getMessage()); + } + } + + private Set getAllAppkeys() { + return Arrays.stream(ENV_LIST).flatMap(env -> { + try { + return zkClient.getChildren().forPath(basePath + "/" + env).stream(); + } catch (Exception e) { + return Stream.empty(); + } + }).collect(Collectors.toSet()); + } + + private List getProviders(String appkey) { + try { + return Arrays.stream(ENV_LIST).flatMap(env -> { + try { + return zkClient.getChildren().forPath(basePath + "/" + env + "/" + appkey + "/provider").stream() + .map(ipPort -> { + if (!IP_PORT_PATTERN.matcher(ipPort).matches()) { + return null; + } + String ip = ipPort.split(":")[0]; + int port = Integer.parseInt(ipPort.split(":")[1]); + Provider provider = new Provider(); + provider.setIp(ip); + provider.setPort(port); + provider.setAppkey(appkey); + provider.setEnv(env); + return provider; + }).filter(Objects::nonNull); + } catch (Exception e) { + return null; + } + }).filter(Objects::nonNull).collect(Collectors.toList()); + } catch (Exception e) { + return Collections.emptyList(); + } + } +} diff --git a/scanner/src/main/java/com/meituan/octo/mns/scanner/service/ProviderUpdateService.java b/scanner/src/main/java/com/meituan/octo/mns/scanner/service/ProviderUpdateService.java new file mode 100644 index 0000000..a4017a9 --- /dev/null +++ b/scanner/src/main/java/com/meituan/octo/mns/scanner/service/ProviderUpdateService.java @@ -0,0 +1,58 @@ +/* + * Copyright 2018 Meituan Dianping. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.meituan.octo.mns.scanner.service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.meituan.octo.mns.scanner.model.Provider; +import org.apache.curator.framework.CuratorFramework; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +public class ProviderUpdateService { + private static final Logger log = LoggerFactory.getLogger(ProviderUpdateService.class); + @Value("${zookeeper.basePath}") + private String basePath; + + @Autowired + private CuratorFramework zkClient; + + public void update(long round, Provider provider, JSONObject providerJson, int status) { + log.info("round={}, updating provider:{}, status:{}", round, provider, status); + try { + long lastUpdateTime = System.currentTimeMillis() / 1000; + providerJson.put("status", status); + providerJson.put("lastUpdateTime", lastUpdateTime); + String providerPath = + basePath + "/" + provider.getEnv() + "/" + provider.getAppkey() + "/provider/" + provider + .getIpPort(); + byte[] data = JSON.toJSONBytes(providerJson); + zkClient.setData().forPath(providerPath, data); + String serverPath = basePath + "/" + provider.getEnv() + "/" + provider.getAppkey() + "/provider"; + byte[] serverPathData = zkClient.getData().forPath(serverPath); + JSONObject serverPathJson = JSON.parseObject(new String(serverPathData)); + serverPathJson.put("lastUpdateTime", lastUpdateTime); + zkClient.setData().forPath(serverPath, serverPathData); + } catch (Exception e) { + log.error("update provider exception:{}, message:{}", e.getClass(), e.getMessage()); + } + } +} diff --git a/scanner/src/main/java/com/meituan/octo/mns/scanner/util/Constant.java b/scanner/src/main/java/com/meituan/octo/mns/scanner/util/Constant.java new file mode 100644 index 0000000..ccc66de --- /dev/null +++ b/scanner/src/main/java/com/meituan/octo/mns/scanner/util/Constant.java @@ -0,0 +1,49 @@ +/* + * Copyright 2018 Meituan Dianping. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.meituan.octo.mns.scanner.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Constant { + public static final int timeout; + public static final int STATUS_ALIVE = 2; + public static final int STATUS_DEAD = 0; + public static final int STATUS_STOPPED = 4; + public static final int HEARTBEAT_SUPPORT_SCANNER = 2; + public static final int HEARTBEAT_SUPPORT_BOTH = 3; + private static final Logger log = LoggerFactory.getLogger(Constant.class); + private static final int DEFAULT_TIMEOUT = 1000; + + static { + int finalTimeout; + String timeoutValue = System.getProperty("provider.detect.timeout"); + if (timeoutValue != null) { + try { + finalTimeout = Integer.parseInt(timeoutValue); + log.info("set timeout to {}", finalTimeout); + } catch (Exception e) { + log.warn("parse provider.detect.timeout exception, will use default value {}", DEFAULT_TIMEOUT); + finalTimeout = DEFAULT_TIMEOUT; + } + } else { + log.info("provider.detect.timeout is not provided, use default value {}", DEFAULT_TIMEOUT); + finalTimeout = DEFAULT_TIMEOUT; + } + timeout = finalTimeout; + } +} diff --git a/scanner/src/main/java/com/meituan/octo/mns/scanner/util/SocketDetector.java b/scanner/src/main/java/com/meituan/octo/mns/scanner/util/SocketDetector.java new file mode 100644 index 0000000..160d307 --- /dev/null +++ b/scanner/src/main/java/com/meituan/octo/mns/scanner/util/SocketDetector.java @@ -0,0 +1,78 @@ +/* + * Copyright 2018 Meituan Dianping. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.meituan.octo.mns.scanner.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketException; +import java.net.SocketTimeoutException; + +public class SocketDetector { + private static final Logger log = LoggerFactory.getLogger(SocketDetector.class); + + public static int detect(String ip, int port) { + Socket socket = new Socket(); + initSocket(socket); + try { + socket.connect(new InetSocketAddress(ip, port), Constant.timeout); + return Constant.STATUS_ALIVE; + } catch (SocketTimeoutException e) { + return detectAgain(ip, port); + } catch (Exception e) { + log.warn("provider:{}:{}, exception:{}", ip, port, e.getMessage()); + return Constant.STATUS_DEAD; + } finally { + try { + socket.close(); + } catch (IOException e) { + //ignored + } + } + } + + private static int detectAgain(String ip, int port) { + Socket socket = new Socket(); + initSocket(socket); + try { + socket.connect(new InetSocketAddress(ip, port), Constant.timeout); + return Constant.STATUS_ALIVE; + } catch (Exception e) { + log.warn("provider:{}:{}, exception:{}", ip, port, e.getMessage()); + return Constant.STATUS_DEAD; + } finally { + try { + socket.close(); + } catch (IOException e) { + //ignored + } + } + } + + private static void initSocket(Socket socket) { + try { + socket.setSoLinger(false, Constant.STATUS_DEAD); + socket.setTcpNoDelay(true); + socket.setSoTimeout(Constant.timeout); + } catch (SocketException e) { + log.error("init socket error", e); + } + } +} diff --git a/scanner/src/main/java/com/meituan/octo/mns/scanner/util/heartbeat/HeartbeatClient.java b/scanner/src/main/java/com/meituan/octo/mns/scanner/util/heartbeat/HeartbeatClient.java new file mode 100644 index 0000000..1f67a95 --- /dev/null +++ b/scanner/src/main/java/com/meituan/octo/mns/scanner/util/heartbeat/HeartbeatClient.java @@ -0,0 +1,104 @@ +/* + * Copyright 2018 Meituan Dianping. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.meituan.octo.mns.scanner.util.heartbeat; + +import com.google.common.util.concurrent.SettableFuture; +import com.meituan.dorado.codec.octo.meta.CallType; +import com.meituan.dorado.codec.octo.meta.Header; +import com.meituan.dorado.codec.octo.meta.MessageType; +import com.meituan.dorado.codec.octo.meta.RequestInfo; +import com.meituan.octo.mns.scanner.util.Constant; +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class HeartbeatClient { + private static final Logger log = LoggerFactory.getLogger(HeartbeatClient.class); + private static final Header header; + private static EventLoopGroup heartbeatGroup = new NioEventLoopGroup(); + + static { + header = new Header(); + header.setMessageType((byte) MessageType.ScannerHeartbeat.getValue()); + + RequestInfo requestInfo = new RequestInfo(); + requestInfo.setSequenceId(1); + requestInfo.setTimeout(Constant.timeout); + requestInfo.setServiceName("ScannerHeartbeat"); + requestInfo.setCallType((byte) CallType.Reply.getValue()); + header.setRequestInfo(requestInfo); + header.setMessageType(((byte) MessageType.ScannerHeartbeat.getValue())); + } + + public static int detect(String ip, int port) { + SettableFuture result = SettableFuture.create(); + Bootstrap bootstrap = new Bootstrap(); + bootstrap.group(heartbeatGroup).option(ChannelOption.TCP_NODELAY, true).option(ChannelOption.SO_REUSEADDR, true) + .channel(NioSocketChannel.class).handler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel socketChannel) throws Exception { + socketChannel.pipeline().addLast(new HeartbeatCodec()).addLast(new HeartbeatHandler(result)); + } + }); + Channel channel = null; + try { + ChannelFuture future = bootstrap.connect(ip, port); + future.get(Constant.timeout, TimeUnit.MILLISECONDS); + channel = future.channel(); + if (channel.isActive() && channel.isWritable()) { + channel.writeAndFlush(header); + try { + return result.get(Constant.timeout, TimeUnit.MILLISECONDS); + } catch (TimeoutException e) { + log.warn("detect:{}:{} timeout, timeout:{}", ip, port, Constant.timeout); + return Constant.STATUS_DEAD; + } catch (Exception e) { + log.error("", e); + return Constant.STATUS_DEAD; + } + } else { + return Constant.STATUS_DEAD; + } + } catch (TimeoutException e) { + log.warn("detect:{}:{} timeout, timeout:{}", ip, port, Constant.timeout); + return Constant.STATUS_DEAD; + } catch (ExecutionException e) { + log.warn("detect:{}:{} exception, exception:{}, message:{}", ip, port, e.getClass(), e.getMessage()); + return Constant.STATUS_DEAD; + } catch (Exception e) { + log.error("", e); + return Constant.STATUS_DEAD; + } finally { + if (channel != null) { + channel.disconnect(); + } + } + + } +} diff --git a/scanner/src/main/java/com/meituan/octo/mns/scanner/util/heartbeat/HeartbeatCodec.java b/scanner/src/main/java/com/meituan/octo/mns/scanner/util/heartbeat/HeartbeatCodec.java new file mode 100644 index 0000000..e7ef326 --- /dev/null +++ b/scanner/src/main/java/com/meituan/octo/mns/scanner/util/heartbeat/HeartbeatCodec.java @@ -0,0 +1,121 @@ +/* + * Copyright 2018 Meituan Dianping. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.meituan.octo.mns.scanner.util.heartbeat; + +import com.meituan.dorado.codec.octo.DoradoCodec; +import com.meituan.dorado.codec.octo.meta.Header; +import com.meituan.dorado.common.exception.ProtocolException; +import com.meituan.dorado.transport.meta.DefaultRequest; +import com.meituan.dorado.util.BytesUtil; +import com.meituan.dorado.util.CompressUtil; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageCodec; +import org.apache.thrift.TDeserializer; +import org.apache.thrift.TException; +import org.apache.thrift.TSerializer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public class HeartbeatCodec extends ByteToMessageCodec
{ + private static final Logger log = LoggerFactory.getLogger(HeartbeatCodec.class); + private static final DoradoCodec codec = new DoradoCodec(); + + @Override + protected void encode(ChannelHandlerContext channelHandlerContext, Header header, ByteBuf byteBuf) + throws Exception { + byte[] headerBytes; + try { + headerBytes = new TSerializer().serialize(header); + } catch (TException e) { + log.error("", e); + return; + } + + DefaultRequest request = new DefaultRequest(); + request.setDoChecksum(false); + request.setCompressType(CompressUtil.CompressType.NO); + request.setVersion((byte) 0x00); + request.setSerialize((byte) 0x01); + + byte[] total = codec.generateSendMessageBuff(request, headerBytes, new byte[0]); + byteBuf.writeBytes(total); + } + + @Override + protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) + throws Exception { + if (byteBuf.readableBytes() < 10) { + return; + } + byte[] buffer = new byte[byteBuf.readableBytes()]; + byteBuf.markReaderIndex(); + byteBuf.readBytes(buffer); + if (!isXMDProtocol(buffer)) { + throw new RuntimeException(); + } else { + byte[] headerBodyBytes = this.getHeaderBodyBuff(buffer); + int headerBodyLength = headerBodyBytes.length; + short headerLength = BytesUtil.bytes2short(buffer, 8); + byte[] headerBytes = new byte[headerLength]; + System.arraycopy(headerBodyBytes, 0, headerBytes, 0, headerLength); + byte[] bodyBytes = new byte[headerBodyLength - headerLength]; + System.arraycopy(headerBodyBytes, headerLength, bodyBytes, 0, headerBodyLength - headerLength); + + Header header = null; + + try { + header = decodeXMDHeader(headerBytes); + list.add(header); + } catch (TException var13) { + throw new ProtocolException("Deserialize XMD header failed.", var13); + } + } + + } + + private Header decodeXMDHeader(byte[] headerBytes) throws TException { + TDeserializer deserializer = new TDeserializer(); + Header header = new Header(); + deserializer.deserialize(header, headerBytes); + return header; + } + + private boolean isXMDProtocol(byte[] buffer) { + short magic = BytesUtil.bytes2short(buffer, 0); + return magic == -21574; + } + + private byte[] getHeaderBodyBuff(byte[] buffer) { + int readerIndex = 4; + int totalLength = BytesUtil.bytes2int(buffer, readerIndex); + readerIndex += 6; + + int msgNeedLength = totalLength + 8; + if (buffer.length < msgNeedLength) { + throw new RuntimeException("Message length less than need length"); + } + + int headerBodyLength = totalLength - 2; + + byte[] headerBodyBytes = new byte[headerBodyLength]; + System.arraycopy(buffer, readerIndex, headerBodyBytes, 0, headerBodyLength); + return headerBodyBytes; + } +} diff --git a/scanner/src/main/java/com/meituan/octo/mns/scanner/util/heartbeat/HeartbeatDetector.java b/scanner/src/main/java/com/meituan/octo/mns/scanner/util/heartbeat/HeartbeatDetector.java new file mode 100644 index 0000000..390913c --- /dev/null +++ b/scanner/src/main/java/com/meituan/octo/mns/scanner/util/heartbeat/HeartbeatDetector.java @@ -0,0 +1,23 @@ +/* + * Copyright 2018 Meituan Dianping. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.meituan.octo.mns.scanner.util.heartbeat; + +public class HeartbeatDetector { + public static int detect(String ip, int port) { + return HeartbeatClient.detect(ip, port); + } +} diff --git a/scanner/src/main/java/com/meituan/octo/mns/scanner/util/heartbeat/HeartbeatHandler.java b/scanner/src/main/java/com/meituan/octo/mns/scanner/util/heartbeat/HeartbeatHandler.java new file mode 100644 index 0000000..bbf067b --- /dev/null +++ b/scanner/src/main/java/com/meituan/octo/mns/scanner/util/heartbeat/HeartbeatHandler.java @@ -0,0 +1,44 @@ +/* + * Copyright 2018 Meituan Dianping. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.meituan.octo.mns.scanner.util.heartbeat; + +import com.google.common.util.concurrent.SettableFuture; +import com.meituan.dorado.codec.octo.meta.Header; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HeartbeatHandler extends SimpleChannelInboundHandler
{ + private static final Logger log = LoggerFactory.getLogger(HeartbeatHandler.class); + private final SettableFuture result; + + public HeartbeatHandler(SettableFuture result) { + this.result = result; + } + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, Header header) throws Exception { + result.set(header.getHeartbeatInfo().getStatus()); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + log.error("", cause); + ctx.close(); + } +} diff --git a/scanner/src/main/resources/application.yaml b/scanner/src/main/resources/application.yaml new file mode 100644 index 0000000..5419207 --- /dev/null +++ b/scanner/src/main/resources/application.yaml @@ -0,0 +1,9 @@ +zookeeper: + basePath: /octo/nameservice + #url: 127.0.0.1:2181 + +executor: + alive: + threadCount: 16 + dead: + threadCount: 16 \ No newline at end of file diff --git a/scanner/src/main/resources/log4j2.xml b/scanner/src/main/resources/log4j2.xml new file mode 100644 index 0000000..3d71035 --- /dev/null +++ b/scanner/src/main/resources/log4j2.xml @@ -0,0 +1,27 @@ + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} %5p [%15.15t] %-40.40c{1.} : %m%n%ex + + octo-scanner/log + + + + + + ${LOG_PATTERN} + + + + + + + + + + + + + \ No newline at end of file diff --git a/sdk/mns-invoker/README.md b/sdk/mns-invoker/README.md new file mode 100644 index 0000000..b6826c0 --- /dev/null +++ b/sdk/mns-invoker/README.md @@ -0,0 +1,389 @@ +# 1 概述说明 +Mns-Invoker是OCTO-NS的轻量级SDK,提供服务注册与注销,服务发现,基础工具类等功能。 + +# 2 服务注册和发现 +## 2.1 服务注册 +### 描述 +用于注册thrift和http协议的服务节点 + +``` +public static void registServiceWithCmd(int uptCmd, SGService sgService) throws TException +``` + +### 请求参数 + +参数名 | 参数类型 | 描述 +------------- | ------------- | ------------ +uptCmd | int | 注册服务的命令码 +sgService | SGService | 参见相关结构体一节 + +注册服务的命令码: + +0,重置(代表后面的serviceName list就是该应用支持的全量接口); +1,增加(代表后面的serviceName list是该应用新增的接口); +2,减少(代表后面的serviceName list是该应用删除的接口)。 + +【NOTE】 + +服务注册和注销的接口是异步的,因此,注册完后,获取服务列表的接口调用需要一定的反应时间,在正常情况下是20秒内。 + +### 请求示例 +``` +String providerAppkey = "com.XXX.XXX.server"; +SGService service = getDefaultSGService(providerAppkey, 5198, true); + service.setProtocol("thrift"); + MnsInvoker.registServiceWithCmd(0,service); +private static SGService getDefaultSGService(final String appkey, final int port, final boolean isThrift) { + String protocol = isThrift ? "thrift" : "http"; + SGService service = new SGService(); + service.setAppkey(appkey); + service.setPort(port); + service.setVersion("original"); + service.setIp(localIp); + service.setLastUpdateTime((int) (System.currentTimeMillis() / 1000)); + service.setServerType(isThrift ? 0 : 1); + service.setWeight(10); + service.setFweight(10.d); + return service; +} +``` +## 2.2 服务注销 +### 描述 +用于注销thrift和http协议的服务节点 + +``` +public static void unRegisterService(SGService sgService) throws TException +``` + +### 请求参数 +参数名 | 参数类型 | 描述 +------------- | ------------- | ------------ +sgService | SGService | 参见相关结构体一节 + +【NOTE】 + +注销接口不会从OCTO上删除节点。调用该接口会有以下变化: + +* 如果服务器上的status不等于4(禁用),则status的值会直接置成0,忽略调用者在sgService中设定的值。否则,status保持为4。 +* 使用sgService的version,extend值覆盖服务器上的旧值 +* lastUpdateTime改为当前系统的时间(sg_agent所在的机器) + +### 请求示例 + +~~~ +MnsInvoker.unRegisterService(getSGService()); +// SGService的appkey,port,localIp,protocal,version等变量请自定义 +private SGService getSGService() { + SGService service = new SGService(); + service.setAppkey(appKey) + .setPort(port).setIp(localIP) + .setLastUpdateTime((int) (System.currentTimeMillis() / 1000)) + .setServerType(1) + .setWeight(10).setFweight(10.d) + .setProtocol(protocal); + service.setStatus(fb_status.DEAD.getValue())//fb_status.DEAD值为0 + .setVersion(version); + return service; +} +~~~ + +## 2.3 服务发现 +### 描述 +获取自定义协议的服务节点 + +~~~ +public static List getServiceList(ProtocolRequest req) +public static List getOriginServiceList(ProtocolRequest req) +~~~ + +### 请求参数 +参数名 | 参数类型 | 描述 +------------- | ------------- | ------------ +req | ProtocolRequest | 参见相关结构体一节 + +### 返回值 +参数类型 | 描述 +------------- | ------------ +List | 不会返回null,但会返回空列表 + +【NOTE】 + +服务节点的获取接口,在第一次获取时,会去远程获取并保存到内存中,此后的调用都是读缓存。而服务节点列表由专门的线程进行更新,读写分离,因此该接口不会堵塞。第一次从远程获取的timeout = 300毫秒,服务节点列表的更新周期在5秒内。 + +### 请求示例 +~~~ +final String consumerAppkey = "XXX"; +final String remoteAppkey = "XXX"; +ProtocolRequest httpReq = new ProtocolRequest() + .setLocalAppkey(consumerAppkey) + .setRemoteAppkey(remoteAppkey) + .setProtocol("http"); +ProtocolRequest thriftReq = new ProtocolRequest() + .setLocalAppkey(consumerAppkey) + .setRemoteAppkey(remoteAppkey) + .setProtocol("thrift"); +​ +List httpList = MnsInvoker.getServiceList(httpReq); +List thriftList = MnsInvoker.getServiceList(thriftReq); +~~~ +## 2.4 服务列表监听 +### 描述 +为自定义协议的请求添加或删除监听器,监听器的作用是当服务列表发生变化时产生回调。 + +~~~ +public static int addServiceListener(ProtocolRequest req, IServiceListChangeListener listener) +public static int removeServiceListener(ProtocolRequest req, IServiceListChangeListener listener) +~~~ +### 请求参数 +参数名 | 参数类型 | 描述 +------------- | ------------- | ------------ +req | ProtocolRequest | 参见相关结构体一节 +listener | IServiceListChangeListener | 服务监听器 +oldList | List | 旧服务列表 +newList | List | 新服务列表 +addList | List | 新增服务节点 +deletedList | List | 被删除的服务节点 +modifiedList | List | 发生变化的服务节点 +### 返回值 +参数类型 | 描述 +------------- | ------------ +int | 成功返回0,失败返回-1 + +【NOTE】 + +* SGService里面的appkey,ip,envir,port,protocol字段一般不会有改变,以下字段的变更会触发modifiedList:status,weight,fweight,version,role,serviceInfo +* mns-invoker对于所有的服务列表监听器只起了一个线程去触发回调callback,因此,强烈建议用户不要在监听器的chaned()方法中做有阻塞的操作,否则会阻塞所有的监听器。 +* 可以对同一份服务列表添加多个监听器,但监听器必须是不同的(hashCode不同)。 +* 强烈建议用户不要自行修改ProtocolRequest和IServiceListChangeListener的hashCode和equals方法。 + +~~~ +ProtocolRequest thriftReq = new ProtocolRequest() + .setLocalAppkey(localAppkey) + .setRemoteAppkey(remoteAppkey) + .setProtocol("thrift"); +IServiceListChangeListener thriftListener = new MyListener(); +MnsInvoker.addServiceListener(thriftReq, thriftListener); +//进行服务注册or注销逻辑 +MnsInvoker.removeServiceListener(thriftReq, thriftListener); +private class MyListener implements IServiceListChangeListener { + @Override + public void changed(ProtocolRequest req, List oldList, List newList, List addList, List deletedList, List modifiedList) { + //以下为自定义的业务逻辑,本例只打印变量内容。 + System.out.println("req protocol: " + req.getProtocol()); + if (!addList.isEmpty()) { + addCallback = true; + print("addList:", addList); + } + if (!deletedList.isEmpty()) { + deletedCallback = true; + print("deletedList:", deletedList); + } +​ + } + private void print(String msg, List list) { + System.out.println(msg); + for (SGService service : list) { + System.out.println(service); + } + } + } +~~~ + +# 4 工具类 +## 4.1 根据ip查询idc内网信息 +### 描述 +根据ip列表获取对应的idc信息 + +~~~ +public static Map getIdcInfo(List ips) throws MnsException +~~~ + +### 请求参数 +参数名 | 参数类型 | 描述 +------------- | ------------- | ------------ +ips | List | ip列表 + +### 返回值 +参数类型 | 描述 +------------- | ------------ +Map | key为传入ip,valude为Idc信息,未查询到的返回Idc(unknown, unknown, unknown) + +## 4.2 全部idc内网信息获取 +### 描述 +查询获取对应的idc信息 + +~~~ +public static List getIdcs() +~~~ + +### 返回值 +参数类型 | 描述 +------------- | ------------ +List | 所有Idc信息的列表 + +## 4.3 查询本机ipv4地址 +### 描述 +查询本机ipv4地址 + +~~~ +public static String getLocalIpV4() +~~~ + +### 返回值 +参数类型 | 描述 +------------- | ------------ +String | 返回ipv4 + +## 4.4 查询本机环境 +### 描述 +查询本机octo.cfg配置文件里记录的环境信息 + +~~~ +public static String getAppEnv() +~~~ + +### 返回值 +参数类型 | 描述 +------------- | ------------ +String | 环境信息,prod、stage、dev、ppe、test其中之一 + +## 4.5 查询本机是否为线上环境 +### 描述 +查询本机octo.cfg配置文件里记录的环境是否属于线上环境 + +~~~ +public static boolean isLocalHostOnline() +~~~ + +### 返回值 +参数类型 | 描述 +------------- | ------------ +boolean | true为线上环境,即prod或stage,其他dev、ppe、test均为线下环境 +## 4.6 查询Mns的zookeeper地址 +### 描述 +查询本机octo.cfg配置文件里面记录的服务注册中心mns的zookeeper地址 + +~~~ +public static String getMnsZKUrl() +~~~ + +### 返回值 +参数类型 | 描述 +------------- | ------------ +String | ip:port连接的字符串,如配置文件不存在返回null。 +## 4.7 查询Mnsc服务的域名 +### 描述 +查询本机octo.cfg配置文件记录的mnsc服务域名 + +~~~ +public static String getMnsZKUrl() +~~~ +### 返回值 +参数类型 | 描述 +------------- | ------------ +String | 以http://开头的域名,如配置文件不存在返回null。 + +## 4.8 查询idc文件的存储目录 +### 描述 +查询本机octo.cfg配置文件记录的idc文件位置 + +~~~ +public static String getIdcPath() +~~~ +### 返回值 +参数类型 | 描述 +------------- | ------------ +String | idc文件所在位置,如配置文件不存在返回null。 + +## 4.9 查询sg_agent代理的端口号 +### 描述 +查询本机octo.cfg配置文件记录的sg_agent端口号 + +~~~ +public static int getSgagentPort() +~~~ +### 返回值 +参数类型 | 描述 +------------- | ------------ +int | 端口号 +## 4.10 查询sg_agent代理的appkey +### 描述 +查询本机octo.cfg配置文件记录的sg_agent的appkey + +~~~ +public static String getSgagentAppkey() // sg_agent本地代理的appkey +public static String getSgsentinelAppkey() // sg_sentinel即哨兵的appkey +~~~ + +### 返回值 +参数类型 | 描述 +------------- | ------------ +String | appkey,如配置文件不存在返回null。 + +# 5 相关结构体 +## 5.1 ProtocolRequest +~~~ +struct ProtocolRequest { + +1:string localAppkey; + +2:string remoteAppkey; + +3:string protocol; + +4:string serviceName; + +} + +/* + +*因为是由thrift产生的类,如果该结构体的字段顺序发生变化,则对应的带参的构造方法也会随着变化, + +*为了更好地兼容,因此,不建议使用带参的构造方法。 + +*建议构建方式如下 + +*/ + +ProtocolRequest req = new ProtocolRequest(); + +req.setLocalAppkey("本地appkey") + +.setRemoteAppkey("服务端appkey") + +.setProtocol("协议"); +~~~ +## 5.2 SGService +~~~ +struct SGService + +{ + +1:string appkey; //不能为空 + +2:string version; + +3:string ip; //不能为空 + +4:i32 port; //不能为空 + +5:i32 weight; //一般设置为10 + +6:i32 status; //2正常状态,0未启动 + +7:i32 role; //backup角色,当其他服务无法服务的时候,启用backup状态;0(主)1(备) + +8:i32 envir; //运行环境,线上:prod=3,stage=2, 线下:dev=3,ppe=2,test=1 + +9:i32 lastUpdateTime; //最后修改时间 + +10:string extend; //扩展 + +11:double fweight; //浮点型权重 一般设置为10.0 + +12:i32 serverType; //用于区分http(1)和thrift(0) + +13:string protocol; //协议 + +} +~~~ \ No newline at end of file diff --git a/sdk/mns-invoker/docs/Compile.md b/sdk/mns-invoker/docs/Compile.md new file mode 100644 index 0000000..185df78 --- /dev/null +++ b/sdk/mns-invoker/docs/Compile.md @@ -0,0 +1,29 @@ + +# mns-invoker 源码编译说明 + +## 1.下载工程 +``` + git clone https://github.com/Meituan-Dianping/octo-ns.git +``` + +## 2.构建Jar包 +环境要求: + +- Java version >= 1.8 +- Maven version >= 3.2 + +切换到mns-invoker目录 + +``` +cd sdk/mns-invoker +``` + +本地install,执行后在本地仓库~/.m2/repository/com/meituan/octo/mns-invoker/(假如你的仓库位置是~/ +.m2/repository)下可以找到mns-invoker的jar + +``` +# 切换到mns-invoker 目录下 +mvn clean install -Dmaven.test.skip=true +``` + +``` diff --git a/sdk/mns-invoker/pom.xml b/sdk/mns-invoker/pom.xml new file mode 100644 index 0000000..2f98cef --- /dev/null +++ b/sdk/mns-invoker/pom.xml @@ -0,0 +1,146 @@ + + + 4.0.0 + + com.meituan.octo + mns-invoker + 1.0.0 + + + 1.7 + 2.9.5 + 3.1 + UTF-8 + 3.0.3 + 1024m + + + + + com.meituan.octo + idl-common + 1.0.0 + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + org.slf4j + slf4j-api + 1.7.12 + + + junit + junit + test + 4.12 + + + org.apache.logging.log4j + log4j-api + test + 2.5 + + + org.apache.logging.log4j + log4j-slf4j-impl + test + 2.5 + + + org.apache.logging.log4j + log4j-core + test + 2.5 + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.14 + + true + + **/*Test*.java + + + + + org.apache.maven.plugins + maven-deploy-plugin + 2.7 + + + org.apache.maven.plugins + maven-install-plugin + 2.4 + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.0 + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + ${octo.build.jvmsize} + true + true + + + + + org.apache.maven.plugins + maven-resources-plugin + 2.6 + + ${project.build.sourceEncoding} + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + package + + jar-no-fork + test-jar-no-fork + + + + + + + + ${basedir}/src/test/resources + true + + + + diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/Consts.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/Consts.java new file mode 100644 index 0000000..b2cf089 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/Consts.java @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns; + +import com.meituan.octo.mns.util.ProcessInfoUtil; + +public class Consts { + public static final String LOCALHOST = "127.0.0.1"; + // public static final boolean isOnline = ProcessInfoUtil.isLocalHostOnline(); + + // private static final String mnsUrl = isOnline ? "http://mns.sankuai.com" : "http://mns.inf.test.sankuai.com"; + + + public static final String UNKNOWN = "unknown"; + public static final int DEFALT_MAX_RESPONSE_MESSAGE_BYTES = 10 * 1024 * 1024; + public static final int DEFAULT_TIMEOUT_IN_MILLS = 5000; + public static final int SERVICES_THRESHOLD = 10; + public static final int RETRY_TIMES = 3; + public static final int CONNECT_TIMEOUT = 500; + public static final String GET_SERVER_LIST_API = ProcessInfoUtil.getMnsUrl() + "/api/servicelist?"; + + public static final int DEFAULT_UPDATE_TIME = 5; + + public static final String CONFIG_FILE = "/data/webapps/octo.cfg"; + + + public static final String ENV_KEY = "env"; + public static final String IDC_PATH = "idc_path"; + public static final String SG_AGENT_PORT = "port"; + public static final String SG_SENTINEL_APPKEY = "sg_sentinel_appkey"; + public static final String SGAENT_APPKEY = "sgagent_appkey"; + public static final String MNSZK_URL = "mnszk_url"; + public static final String MNS_URL = "mns_url"; + + public static final String MNS_DEFAULT_VERSION = "original"; + + +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/InvokeProxy.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/InvokeProxy.java new file mode 100644 index 0000000..0f0f180 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/InvokeProxy.java @@ -0,0 +1,110 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns; + +import com.meituan.octo.mns.model.SGAgentClient; +import com.meituan.octo.mns.sentinel.AgentClientFactory; +import com.octo.naming.service.thrift.model.ServiceAgent; +import org.apache.thrift.transport.TTransportException; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Arrays; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class InvokeProxy implements InvocationHandler { + private static final Logger LOG = LoggerFactory.getLogger(InvokeProxy.class); + private final SGAgentClient.ClientType type; + private static boolean isMock = false; + private static Object mockValue; + + //lock + private static final Object MULTI_PROTO_LOCK = new Object(); + + public static void setIsMock(boolean isMock) { + InvokeProxy.isMock = isMock; + } + + public static void setMockValue(Object mock) { + mockValue = mock; + } + + public InvokeProxy(SGAgentClient.ClientType clientType) { + this.type = clientType; + } + + public SGAgentClient.ClientType getType() { + return type; + } + + public ServiceAgent.Iface getProxy() { + return (ServiceAgent.Iface) Proxy.newProxyInstance(ServiceAgent.class.getClassLoader(), + ServiceAgent.Client.class.getInterfaces(), this); + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) { + Object result = null; + + // to ensure proper use of locks, do not optimized the redundant case codes. + switch (type) { + case multiProto: + synchronized (MULTI_PROTO_LOCK) { + result = doInvoker(proxy, method, args); + } + break; + default: + // no lock for temp sg_agent connection. + result = doInvoker(proxy, method, args); + break; + } + + + return result; + } + + private Object doInvoker(Object proxy, Method method, Object[] args) { + Object result = null; + + // get the sg_agent connection + SGAgentClient client = AgentClientFactory.borrowClient(type); + + try { + result = isMock ? mockValue : method.invoke(client.getIface(), args); + + } catch (Exception e) { + LOG.debug("Invoker Exception, method: {} args: {}", method.getName(), Arrays.toString(args)); + LOG.debug(e.getMessage(), e); + + if (e.getCause() instanceof TTransportException) { + client.destory(); + } + + } finally { + // return the sg_agent connection + AgentClientFactory.returnClient(client); + } + return result; + } + + +} \ No newline at end of file diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/MnsInvoker.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/MnsInvoker.java new file mode 100644 index 0000000..30c8890 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/MnsInvoker.java @@ -0,0 +1,71 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns; + +import com.meituan.octo.mns.cache.MnsCacheManager; +import com.meituan.octo.mns.listener.IServiceListChangeListener; +import com.octo.naming.common.thrift.model.ProtocolRequest; +import com.octo.naming.common.thrift.model.SGService; +import org.apache.thrift.TException; + +import java.util.List; + +public class MnsInvoker { + + private static MnsCacheManager cacheManager = new MnsCacheManager(); + + private static RegistryManager registryManager = new RegistryManager(); + + + public static void registServiceWithCmd(int uptCmd, SGService sgService) throws TException { + registryManager.registerServiceWithCmd(uptCmd, sgService); + } + + public static void unRegisterService(SGService sgService) throws TException { + registryManager.unRegisterService(sgService); + } + + + public static int addServiceListener(ProtocolRequest req, IServiceListChangeListener listener) { + return cacheManager.addServiceListListener(req, listener); + } + + public static int removeServiceListener(ProtocolRequest req, IServiceListChangeListener listener) { + return cacheManager.removeServiceListListener(req, listener); + } + + public static List getServiceList(ProtocolRequest req) { + return cacheManager.getServiceList(req); + } + + public static List getOriginServiceList(ProtocolRequest req) { + return cacheManager.getOriginServiceList(req); + } + + public static int addOriginServiceListener(ProtocolRequest req, IServiceListChangeListener listener) { + return cacheManager.addOriginServiceListListener(req, listener); + } + + public static int removeOriginServiceListener(ProtocolRequest req, IServiceListChangeListener listener) { + return cacheManager.removeOriginServiceListListener(req, listener); + } + +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/RegistryManager.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/RegistryManager.java new file mode 100644 index 0000000..c0c17cf --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/RegistryManager.java @@ -0,0 +1,104 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns; + +import com.meituan.octo.mns.model.SGAgentClient; +import com.meituan.octo.mns.util.IpUtil; +import com.octo.naming.common.thrift.model.SGService; +import com.octo.naming.service.thrift.model.ServiceAgent; +import org.apache.commons.lang3.StringUtils; +import org.apache.thrift.TException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class RegistryManager { + + private static final Logger LOG = LoggerFactory.getLogger(RegistryManager.class); + private final ServiceAgent.Iface tempClient = new InvokeProxy(SGAgentClient.ClientType.temp).getProxy(); + private ExecutorService executors = Executors.newFixedThreadPool(1); + + + public void registerServiceWithCmd(final int cmd, final SGService sgService) throws TException { + if (!isSGServiceValid(sgService)) { + return; + } + executors.submit(new Runnable() { + @Override + public void run() { + try { + synchronized (tempClient) { + LOG.info("Mns service provider registration, cmd ={} | param = {}", cmd, + sgService.toString()); + tempClient.registServicewithCmd(cmd, sgService); + } + } catch (Exception e) { + LOG.error(e.getMessage(), e); + } + } + }); + } + + public void unRegisterService(final SGService sgService) throws TException { + if (!isSGServiceValid(sgService)) { + return; + } + executors.submit(new Runnable() { + @Override + public void run() { + try { + synchronized (tempClient) { + LOG.info("Mns service provider unRegistration, param = {}", sgService.toString()); + tempClient.unRegistService(sgService); + } + } catch (Exception e) { + LOG.error(e.getMessage(), e); + } + } + }); + } + + + private static boolean isSGServiceValid(SGService service) { + if (null == service) { + LOG.error("Cannot register null."); + return false; + } + int port = service.getPort(); + String appkey = service.getAppkey(); + String ip = service.getIp(); + if (port < 1) { + LOG.error("Invalid port: port|" + port + "|appkey:" + appkey); + return false; + } + if (StringUtils.isEmpty(appkey)) { + LOG.error("Invalid appKey: appkey|" + appkey); + return false; + } + + if (!IpUtil.checkIP(ip)) { + LOG.error("Invalid ip: ip|" + ip + "|appkey:" + appkey); + return false; + } + return true; + } +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/cache/CacheLoader.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/cache/CacheLoader.java new file mode 100644 index 0000000..735aca9 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/cache/CacheLoader.java @@ -0,0 +1,25 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.cache; + +public interface CacheLoader { + V reload(R row, C column); +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/cache/MnsCache.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/cache/MnsCache.java new file mode 100644 index 0000000..3d8f24c --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/cache/MnsCache.java @@ -0,0 +1,69 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.cache; + +public class MnsCache { + private MultiMap cache = MultiMap.create(); + private CacheLoader loader; + + public MnsCache() { + } + + public MnsCache(CacheLoader loader) { + this.loader = loader; + } + + public static MnsCache create() { + MnsCache instance = new MnsCache(); + return instance; + } + + public static MnsCache create( + CacheLoader loader) { + MnsCache instance = new MnsCache(loader); + return instance; + } + + public void put(R row, C column, V value) { + cache.put(row, column, value); + } + + public V get(R row, C column) { + return cache.get(row, column); + } + + public boolean contains(R row, C column) { + return cache.contains(row, column); + } + + public void updateAll() { + if (loader != null) { + for (R row : cache.rows()) { + for (C column : cache.columns(row)) { + V value = loader.reload(row, column); + if (null != value) { + put(row, column, value); + } + } + } + } + } +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/cache/MnsCacheManager.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/cache/MnsCacheManager.java new file mode 100644 index 0000000..9109928 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/cache/MnsCacheManager.java @@ -0,0 +1,157 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.cache; + +import com.meituan.octo.mns.Consts; +import com.meituan.octo.mns.listener.IServiceListChangeListener; +import com.meituan.octo.mns.util.ScheduleTaskFactory; +import com.octo.naming.common.thrift.model.ProtocolRequest; +import com.octo.naming.common.thrift.model.SGService; +import org.apache.commons.lang3.StringUtils; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MnsCacheManager { + private static final Logger LOG = LoggerFactory.getLogger(MnsCacheManager.class); + + private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1, new ScheduleTaskFactory("MnsCacheManager-Schedule")); + + private ServiceCache protocolServiceCache = new ServiceCache(); + + private ServiceCache originServiceCache = new OriginServiceCache(); + + + private enum ServiceCacheType { + PROTOCOL, ORIGIN + } + + + public MnsCacheManager() { + LOG.info("init MnsCacheManager, start update scheduler"); + scheduler.scheduleWithFixedDelay(new Runnable() { + @Override + public void run() { + try { + protocolServiceCache.updateAll(); + originServiceCache.updateAll(); + } catch (Exception e) { + LOG.debug("update mns cache exception, " + e.getMessage(), e); + } + } + }, 1, Consts.DEFAULT_UPDATE_TIME, TimeUnit.SECONDS); + } + + private boolean isValid(ProtocolRequest req) { + boolean ret = (null != req) + && !(StringUtils.isEmpty(req.getRemoteAppkey()) && StringUtils.isEmpty(req.getServiceName())) + && !StringUtils.isEmpty(req.getProtocol()); + if (!ret) { + LOG.error("Invalid ProtocolRequest, protocol and remoteAppkey/serviceName cannot be empty."); + } + return ret; + } + + private String handleLocalAppkey(String localAppkey) { + if (null == localAppkey) { + LOG.debug("localAppkey is null, probably not set, please check the settings!"); + localAppkey = ""; + } + return localAppkey; + } + + private void pretreatServiceListRequest(ProtocolRequest req) { + String curLocalAppkey = handleLocalAppkey(req.getLocalAppkey()); + + req.setLocalAppkey(StringUtils.trim(curLocalAppkey)) + .setRemoteAppkey(StringUtils.trim(req.getRemoteAppkey())) + .setServiceName(StringUtils.trim(req.getServiceName())) + .setProtocol(StringUtils.trim(req.getProtocol())); + } + + public List getServiceList(ProtocolRequest req) { + return getServiceListByType(req, ServiceCacheType.PROTOCOL); + } + + public List getOriginServiceList(ProtocolRequest req) { + return getServiceListByType(req, ServiceCacheType.ORIGIN); + } + + private List getServiceListByType(ProtocolRequest req, ServiceCacheType type) { + if (!isValid(req)) { + return Collections.emptyList(); + } + pretreatServiceListRequest(req); + switch (type) { + case PROTOCOL: + return protocolServiceCache.get(req); + case ORIGIN: + return originServiceCache.get(req); + default: + LOG.error("unknown ServiceCacheType = {}", type); + return Collections.emptyList(); + } + } + + + public int addServiceListListener(ProtocolRequest req, IServiceListChangeListener listener) { + return handleListener(protocolServiceCache, req, listener, true); + } + + + public int removeServiceListListener(ProtocolRequest req, IServiceListChangeListener listener) { + return handleListener(protocolServiceCache, req, listener, false); + } + + public int addOriginServiceListListener(ProtocolRequest req, IServiceListChangeListener listener) { + return handleListener(originServiceCache, req, listener, true); + } + + public int removeOriginServiceListListener(ProtocolRequest req, IServiceListChangeListener listener) { + return handleListener(originServiceCache, req, listener, false); + + } + + + void clearCache() { + protocolServiceCache.clearCache(); + originServiceCache.clearCache(); + } + + + private int handleListener(ServiceCache cache, ProtocolRequest req, IServiceListChangeListener listener, boolean isAdd) { + if (!isValid(req) || null == listener) { + return -1; + } + pretreatServiceListRequest(req); + + if (isAdd) { + cache.addListener(req, listener); + } else { + return cache.removeListener(req, listener); + } + return 0; + } +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/cache/MultiMap.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/cache/MultiMap.java new file mode 100644 index 0000000..ec50142 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/cache/MultiMap.java @@ -0,0 +1,90 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.cache; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MultiMap { + private static final Logger LOG = LoggerFactory.getLogger(MultiMap.class); + private Map> maps = new ConcurrentHashMap>(); + + public static MultiMap create() { + return new MultiMap(); + } + + public Set rows() { + return maps.keySet(); + } + + public Set columns(R row) { + Map subMap = get(row); + if (subMap != null) { + return subMap.keySet(); + } else { + return Collections.emptySet(); + } + } + + public void put(R row, C column, V value) { + if (row != null && column != null && value != null) { + Map subMap = getOrCreate(row); + subMap.put(column, value); + } else { + LOG.debug("row {} or column {} or value {} is null", + new Object[]{row, column, value}); + } + } + + public V get(R row, C column) { + Map subMap = get(row); + if (subMap != null && column != null) { + return subMap.get(column); + } else { + return null; + } + } + + public Map get(R row) { + if (row == null) { + return null; + } else { + return maps.get(row); + } + } + + public Map getOrCreate(R row) { + Map subMap = get(row); + if (null == subMap && row != null) { + subMap = new ConcurrentHashMap(); + maps.put(row, subMap); + } + return subMap; + } + + public boolean contains(R row, C column) { + return get(row, column) != null; + } +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/cache/OriginServiceCache.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/cache/OriginServiceCache.java new file mode 100644 index 0000000..09ddf78 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/cache/OriginServiceCache.java @@ -0,0 +1,36 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.cache; + +import com.octo.naming.common.thrift.model.ProtocolRequest; +import com.octo.naming.common.thrift.model.ProtocolResponse; +import com.octo.naming.service.thrift.model.ServiceAgent; +import org.apache.thrift.TException; + +/** + * not public class, visible within package. + */ +class OriginServiceCache extends ServiceCache { + @Override + protected ProtocolResponse doGetServiceList(ServiceAgent.Iface client, ProtocolRequest req) throws TException { + return client.getOriginServiceList(req); + } +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/cache/ServiceCache.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/cache/ServiceCache.java new file mode 100644 index 0000000..e9f610b --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/cache/ServiceCache.java @@ -0,0 +1,399 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.cache; + +import com.meituan.octo.mns.Consts; +import com.meituan.octo.mns.InvokeProxy; +import com.meituan.octo.mns.listener.IServiceListChangeListener; +import com.meituan.octo.mns.model.SGAgentClient; +import com.meituan.octo.mns.util.ScheduleTaskFactory; +import com.octo.naming.common.thrift.model.ProtocolRequest; +import com.octo.naming.common.thrift.model.ProtocolResponse; +import com.octo.naming.common.thrift.model.SGService; +import com.octo.naming.common.thrift.model.ServiceDetail; +import com.octo.naming.service.thrift.model.ServiceAgent; +import org.apache.commons.lang3.StringUtils; +import org.apache.thrift.TException; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ServiceCache { + private static final Logger LOG = LoggerFactory.getLogger(ServiceCache.class); + + private Map> requestCache = new ConcurrentHashMap>(); + private Map> sgagentCache = new ConcurrentHashMap>(); + + private Map requestToCacheKey = new ConcurrentHashMap(); + private Map requestCacheToSgagentCache = new HashMap(); + + private ServiceAgent.Iface sgAgent = new InvokeProxy(SGAgentClient.ClientType.multiProto).getProxy(); + + private ServiceListListener listeners = new ServiceListListener(); + + private final Object requestKeyLock = new Object(); + + private static final ExecutorService LISTENER_THREAD_POOL_EXECUTOR = Executors.newFixedThreadPool(2, new ScheduleTaskFactory("MnsInvoker-ServiceList-Listener")); + + + private final int retrySleepTime = 500; + // only for test case + private static boolean runUpdateAll = true; + private static boolean saveNullList = true; + + private static final int SUCCESS = 0; + private static final int ERR_NODE_NOTFIND = -101; + + public List get(ProtocolRequest req) { + ProtocolRequest request = getCacheKey(req); + List list = requestCache.get(request); + return (null == list) ? getServiceFromAgentAndSave(request) : list; + } + + private ProtocolRequest getCacheKey(ProtocolRequest req) { + ProtocolRequest request = requestToCacheKey.get(req); + if (null == request) { + synchronized (requestKeyLock) { + request = requestToCacheKey.get(req); + if (null == request) { + request = handleServiceName(req); + requestToCacheKey.put(req, request); + } + } + } + return request; + } + + private List getServiceFromAgentAndSave(ProtocolRequest req) { + + + // get the service list for the first time. retry up to three times + List list = null; + for (int i = 0; i < Consts.RETRY_TIMES; ++i) { + try { + ProtocolResponse resp = doGetServiceList(sgAgent, req); + if (null != resp && SUCCESS == resp.getErrcode()) { + //success to get service list. + list = resp.getServicelist(); + break; + } else if (null != resp && ERR_NODE_NOTFIND == resp.getErrcode()) { + LOG.warn("Fail to get service list, the remoteAppkey or serviceName doesn't exist. param = {}", req.toString()); + break; + } else { + if (i < 2) { + Thread.sleep(retrySleepTime); + } + } + + } catch (Exception e) { + LOG.error("Fail to get service list, now try to get it again. time = " + i, e); + } + } + + if (null == list) { + if (!saveNullList) { + // only for test case, using mock data. + return list; + } + list = Collections.emptyList(); + } + + // Do not adjust the order of the following codes + sgagentCache.put(req, list); + + ProtocolRequest requestKey = isIgnoreServiceName(req) ? new ProtocolRequest(req) : req; + List filterList = filterWithServiceName(list, requestKey); + requestCache.put(requestKey, filterList); + + requestCacheToSgagentCache.put(requestKey, req); + + return filterList; + } + + void clearCache() { + requestCacheToSgagentCache.clear(); + requestCache.clear(); + sgagentCache.clear(); + requestCacheToSgagentCache.clear(); + } + + static void setSaveNullList(boolean saveNullList) { + ServiceCache.saveNullList = saveNullList; + } + + private boolean isIgnoreServiceName(ProtocolRequest req) { + return "thrift".equals(req.getProtocol()) + && !StringUtils.isEmpty(req.getRemoteAppkey()) + && !StringUtils.isEmpty(req.getServiceName()); + } + + private ProtocolRequest handleServiceName(ProtocolRequest req) { + ProtocolRequest ret = new ProtocolRequest(req); + if (isIgnoreServiceName(req)) { + ret.unsetServiceName(); + } + return ret; + } + + private List filterWithServiceName(List allList, ProtocolRequest req) { + List retList = null; + if (isIgnoreServiceName(req)) { + retList = new ArrayList(); + for (SGService service : allList) { + if (null != service.getServiceInfo() && service.getServiceInfo().containsKey(req.getServiceName())) { + retList.add(service); + } + } + } else { + retList = allList; + } + + return retList; + } + + public void addListener(ProtocolRequest req, IServiceListChangeListener listener) { + listeners.put(req, listener); + } + + public int removeListener(ProtocolRequest req, IServiceListChangeListener listener) { + return listeners.remove(req, listener); + } + + protected ProtocolResponse doGetServiceList(ServiceAgent.Iface client, com.octo.naming.common.thrift.model.ProtocolRequest req) throws TException { + return client.getServiceListByProtocol(req); + } + + private List getServiceFromAgent(ServiceAgent.Iface client, ProtocolRequest req) { + List list = null; + try { + ProtocolResponse resp = doGetServiceList(client, req); + if (0 == resp.getErrcode()) { + list = resp.getServicelist(); + } else { + LOG.debug("Fail to get service list, errorcode = {} | params = {}", resp.getErrcode(), req.toString()); + + + } + } catch (Exception e) { + LOG.debug(e.getMessage(), e); + } + + + return list; + } + + static void setRunUpdateAll(boolean runUpdateAll) { + ServiceCache.runUpdateAll = runUpdateAll; + } + + void updateAll() { + if (!runUpdateAll) { + // only for test case. + return; + } + for (Map.Entry> item : sgagentCache.entrySet()) { + ProtocolRequest req = item.getKey(); + List list = getServiceFromAgent(sgAgent, req); + if (null != list) { + sgagentCache.put(req, list); + } + } + + for (Map.Entry> item : requestCache.entrySet()) { + ProtocolRequest req = item.getKey(); + ProtocolRequest sgagentCacheKey = requestCacheToSgagentCache.get(req); + if (null != sgagentCacheKey) { + List allList = sgagentCache.get(sgagentCacheKey); + if (null != allList) { + List filterList = filterWithServiceName(allList, req); + requestCache.put(req, filterList); + listeners.callIfDiff(req, item.getValue(), filterList); + } + } + } + } + + class ServiceListListener { + private Map> listeners = new ConcurrentHashMap>(); + private final Object listenerLock = new Object(); + + private void initKeyListener(ProtocolRequest req) { + get(req); + } + + public void put(final ProtocolRequest req, final IServiceListChangeListener listener) { + initKeyListener(req); + ProtocolRequest request = getCacheKey(req); + if (!listeners.containsKey(request)) { + synchronized (listenerLock) { + if (!listeners.containsKey(request)) { + listeners.put(request, new HashSet()); + } + } + } + listeners.get(request).add(listener); + } + + public int remove(final ProtocolRequest req, final IServiceListChangeListener listener) { + int ret = 0; + ProtocolRequest request = getCacheKey(req); + Set listenerSet = listeners.get(request); + if (null != listenerSet) { + listenerSet.remove(listener); + } + return ret; + } + + public void callIfDiff(final ProtocolRequest req, final List oldList, final List newList) { + final Set listenerSet = listeners.get(req); + if (null == listenerSet) { + return; + } + + final List addList = new ArrayList(), + deletedList = new ArrayList(), + modifiedList = new ArrayList(); + // if oldlist is small, just go through every item of newlist and oldlist + if (oldList.size() < Consts.SERVICES_THRESHOLD) { + for (SGService newItem : newList) { + boolean isExist = false; + for (SGService oldItem : oldList) { + //the intersection of new and old,check if the value is modified + if (isSameNode(newItem, oldItem)) { + if (isModified(newItem, oldItem)) { + modifiedList.add(newItem); + } + isExist = true; + } + } + if (!isExist) { + //the difference set in the new list + addList.add(newItem); + } + } + //the difference set in the old list + for (SGService oldItem : oldList) { + boolean isExist = false; + for (SGService newItem : newList) { + if (isSameNode(newItem, oldItem)) { + isExist = true; + break; + } + } + if (!isExist) { + deletedList.add(oldItem); + } + } + } else { + + // if oldlist is big, we turn oldlist to map + Map oldMap = new HashMap(); + for (SGService item : oldList) { + String sid = item.getIp() + "_" + item.getPort() + "_" + item.getAppkey(); + oldMap.put(sid, item); + } + + for (SGService item : newList) { + String key = item.getIp() + "_" + item.getPort() + "_" + item.getAppkey(); + + //the intersection of new and old,check if the value is modified + if (oldMap.containsKey(key)) { + if (isModified(item, oldMap.get(key))) { + modifiedList.add(item); + } + } else { + //the difference set in the new list + addList.add(item); + } + //the deletedList + oldMap.remove(key); + } + + //the difference set in the old list + for (Map.Entry e : oldMap.entrySet()) { + deletedList.add(e.getValue()); + } + + } + //modifiedList came first because modifiedList is more often changed + if ((!modifiedList.isEmpty() || !deletedList.isEmpty() || !addList.isEmpty())) { + LISTENER_THREAD_POOL_EXECUTOR.execute(new Runnable() { + @Override + public void run() { + for (IServiceListChangeListener listener : listenerSet) { + try { + listener.changed(req, oldList, newList, addList, deletedList, modifiedList); + } catch (Exception e) { + LOG.error("Failed to execute callback function of mns listener.", e); + } + } + } + }); + } + } + + // appkey for pigeon + private boolean isSameNode(SGService a, SGService b) { + return StringUtils.equals(a.getIp(), b.getIp()) + && a.getPort() == b.getPort() + && StringUtils.equals(a.getAppkey(), b.getAppkey()); + } + + boolean isModified(SGService a, SGService b) { + boolean isServiceInfoDiff = false; + try { + if (a.isSetServiceInfo() && b.isSetServiceInfo()) { + Map serviceInfoA = a.getServiceInfo(); + Map serviceInfoB = b.getServiceInfo(); + if (serviceInfoA.size() == serviceInfoB.size()) { + for (Map.Entry oldItem : serviceInfoA.entrySet()) { + if (!(serviceInfoB.containsKey(oldItem.getKey()) && isServiceDetailEqual(oldItem.getValue(), serviceInfoB.get(oldItem.getKey())))) { + isServiceInfoDiff = true; + break; + } + } + } else { + isServiceInfoDiff = true; + } + } else if (a.isSetServiceInfo() ^ b.isSetServiceInfo()) { + isServiceInfoDiff = true; + } + } catch (Exception e) { + LOG.warn("Fail to compare serviceInfos , simply ignore the error.", e); + } + + boolean isSame = (a.getStatus() == b.getStatus()) + && (a.getWeight() == b.getWeight()) + && (Math.abs(a.getFweight() - b.getFweight()) < 0.0000001d) + && StringUtils.equals(a.getVersion(), b.getVersion()) + && (a.getRole() == b.getRole()) + && !isServiceInfoDiff; + return !isSame; + } + + private boolean isServiceDetailEqual(ServiceDetail detailA, ServiceDetail detailB) { + return (null == detailA && null == detailB) || (null != detailA && detailA.equals(detailB)); + } + } +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/exception/MnsException.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/exception/MnsException.java new file mode 100644 index 0000000..6120861 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/exception/MnsException.java @@ -0,0 +1,27 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.exception; + +public class MnsException extends Exception { + public MnsException(String msg) { + super(msg); + } +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/http/HttpServerPublisher.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/http/HttpServerPublisher.java new file mode 100644 index 0000000..944f91f --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/http/HttpServerPublisher.java @@ -0,0 +1,121 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.http; + +import com.meituan.octo.mns.Consts; +import com.meituan.octo.mns.MnsInvoker; +import com.meituan.octo.mns.util.ProcessInfoUtil; +import com.octo.naming.common.thrift.model.SGService; +import com.octo.naming.common.thrift.model.fb_status; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HttpServerPublisher { + private static final Logger LOG = LoggerFactory.getLogger(HttpServerPublisher.class); + + private String appKey; + private int port = -1; + private String version; + private static String localIP = ProcessInfoUtil.getLocalIpv4(); + + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getAppKey() { + return appKey; + } + + public void setAppKey(String appKey) { + this.appKey = appKey; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + private boolean isValid() { + if (StringUtils.isEmpty(appKey)) { + LOG.error("Http publisher error, appKey cannot be empty."); + return false; + } + if (port < 1) { + LOG.error("Http publisher error, invalid port {}.", port); + return false; + } + return true; + } + + public void publish() { + if (!isValid()) { + return; + } + try { + LOG.info("Http registration appKey = {}, port = {}", appKey, port); + MnsInvoker.registServiceWithCmd(1, getSGService()); + } catch (Exception e) { + LOG.debug("Http registration error.", e); + } + } + + public void destroy() { + if (!isValid()) { + return; + } + try { + LOG.info("Http unRegistration appKey = {}, port = {}", appKey, port); + MnsInvoker.unRegisterService(getSGService()); + Thread.sleep(1000L); + } catch (Exception e) { + LOG.debug("Http unRegistration error.", e); + } + } + + + private SGService getSGService() { + SGService service = new SGService(); + + service.setAppkey(appKey) + .setPort(port).setIp(localIP) + .setLastUpdateTime((int) (System.currentTimeMillis() / 1000)) + .setServerType(1) + .setWeight(10).setFweight(10.d) + .setProtocol("http"); + + if (StringUtils.isEmpty(version)) { + setVersion(Consts.MNS_DEFAULT_VERSION); + } + service.setStatus(fb_status.DEAD.getValue()) + .setVersion(getVersion()); + + return service; + } +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/listener/IServiceListChangeListener.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/listener/IServiceListChangeListener.java new file mode 100644 index 0000000..4e86799 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/listener/IServiceListChangeListener.java @@ -0,0 +1,35 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.listener; + +import com.octo.naming.common.thrift.model.ProtocolRequest; +import com.octo.naming.common.thrift.model.SGService; + +import java.util.List; + +public interface IServiceListChangeListener { + void changed(ProtocolRequest req, + List oldList, + List newList, + List addList, + List deletedList, + List modifiedList); +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/model/AgentInfo.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/model/AgentInfo.java new file mode 100644 index 0000000..f4609e2 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/model/AgentInfo.java @@ -0,0 +1,78 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.model; + +public class AgentInfo { + + private String ip = ""; + private int port; + private String appkey = ""; + private String env = ""; + + public AgentInfo(String ip, int port, String appkey, String env) { + this.ip = ip; + this.port = port; + this.appkey = appkey; + this.env = env; + } + + public String getEnv() { + return env; + } + + public void setEnv(String env) { + this.env = env; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public int getPort() { + return port; + } + + public void setPort(int port) { + this.port = port; + } + + public String getAppkey() { + return appkey; + } + + public void setAppkey(String appkey) { + this.appkey = appkey; + } + + @Override + public String toString() { + return "AgentInfo{" + + "ip='" + ip + '\'' + + ", port=" + port + + ", appkey='" + appkey + '\'' + + ", env='" + env + '\'' + + '}'; + } +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/model/HostEnv.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/model/HostEnv.java new file mode 100644 index 0000000..510630d --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/model/HostEnv.java @@ -0,0 +1,30 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.model; + + +public enum HostEnv { + PROD, + STAGE, + PPE, + TEST, + DEV +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/model/IDC.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/model/IDC.java new file mode 100644 index 0000000..1cc198c --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/model/IDC.java @@ -0,0 +1,88 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.model; + +import com.meituan.octo.mns.util.IpUtil; +import com.octo.idc.model.Idc; + +public class IDC { + private String ip; + private String mask; + private Idc idcinfo; + + private int intMask; + private int ipMaskValue; + private boolean isInit = false; + //private Object lock = new Object(); + + public void init() { + if (!isInit) { + synchronized (this) { + if (!isInit) { + intMask = convertMaskToInt(mask); + ipMaskValue = intMask & IpUtil.getIpv4Value(ip); + isInit = true; + } + } + } + } + + int convertMaskToInt(String mask) { + String[] vnum = mask.split("\\."); + if (4 != vnum.length) { + return -1; + } + + int iMask = 0; + for (int i = 0; i < vnum.length; ++i) { + iMask += (Integer.parseInt(vnum[i]) << ((3 - i) * 8)); + } + return iMask; + } + + public Idc getIdcinfo() { + return idcinfo; + } + + public void setIdcinfo(Idc idcinfo) { + this.idcinfo = idcinfo; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public void setMask(String mask) { + this.mask = mask; + } + + public int getIntMask() { + return intMask; + } + + public int getIpMaskValue() { + return ipMaskValue; + } +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/model/SGAgentClient.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/model/SGAgentClient.java new file mode 100644 index 0000000..4a2f6b8 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/model/SGAgentClient.java @@ -0,0 +1,93 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.model; + +import com.meituan.octo.mns.Consts; +import com.octo.naming.service.thrift.model.ServiceAgent; +import org.apache.thrift.transport.TSocket; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class SGAgentClient { + private static final Logger LOG = LoggerFactory.getLogger(SGAgentClient.class); + private TSocket tSocket; + private ServiceAgent.Iface iface; + private ClientType type; + + public SGAgentClient() { + this(ClientType.temp); + } + + public SGAgentClient(ClientType type) { + this.type = type; + } + + public ClientType getType() { + return type; + } + + public void setType(ClientType type) { + this.type = type; + } + + public TSocket getTSocket() { + return tSocket; + } + + public void setTSocket(TSocket tSocket) { + this.tSocket = tSocket; + } + + public ServiceAgent.Iface getIface() { + return iface; + } + + public void setIface(ServiceAgent.Iface iface) { + this.iface = iface; + } + + public void destory() { + if (null == this.tSocket) { + return; + } + LOG.debug("destroy current tSocket:" + tSocket.getSocket().toString()); + tSocket.close(); + this.tSocket = null; + } + + public boolean isLocal() { + boolean local = false; + try { + String remoteSocketAddress = this.getTSocket().getSocket().getRemoteSocketAddress().toString(); + if (remoteSocketAddress.contains(Consts.LOCALHOST)) { + local = true; + } + } catch (Exception e) { + LOG.debug(e.getMessage(), e); + } + return local; + } + + public enum ClientType { + temp, multiProto + } + +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/sentinel/AgentClientFactory.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/sentinel/AgentClientFactory.java new file mode 100644 index 0000000..f0eefec --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/sentinel/AgentClientFactory.java @@ -0,0 +1,170 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.sentinel; + +import com.meituan.octo.mns.Consts; +import com.meituan.octo.mns.model.AgentInfo; +import com.meituan.octo.mns.model.SGAgentClient; +import com.meituan.octo.mns.util.ProcessInfoUtil; +import com.octo.naming.service.thrift.model.ServiceAgent; +import org.apache.thrift.protocol.TBinaryProtocol; +import org.apache.thrift.protocol.TProtocol; +import org.apache.thrift.transport.TFramedTransport; +import org.apache.thrift.transport.TSocket; +import org.apache.thrift.transport.TTransportException; +import java.util.Collections; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class AgentClientFactory { + private static final Logger LOG = LoggerFactory.getLogger(AgentClientFactory.class); + private static SGAgentClient multiProtoClient = null; + + private static final int SGAGENT_PORT = ProcessInfoUtil.getSgagentPort(); + + + public static SGAgentClient borrowClient(SGAgentClient.ClientType type) { + SGAgentClient client = null; + switch (type) { + case temp: + client = getSGAgentClient(type); + break; + case multiProto: + if (null == multiProtoClient) { + multiProtoClient = getSGAgentClient(type); + } + client = multiProtoClient; + break; + default: + LOG.debug(""); + + } + return client; + + } + + public static void returnClient(SGAgentClient client) { + if (client == null) { + return; + } + switch (client.getType()) { + case temp: + client.destory(); + break; + case multiProto: + multiProtoClient = checkHealthLocality(client); + break; + default: + break; + } + } + + public static SGAgentClient getSGAgentClient(SGAgentClient.ClientType type) { + SGAgentClient client = null; + List customizedList = CustomizedManager.getCustomizedAgentList(); + + if (customizedList.isEmpty()) { + client = createAgentClient(Consts.LOCALHOST, SGAGENT_PORT); + if (null != client) { + client.setType(type); + return client; + } + List sentinelList = SentinelManager.getSentinelAgentList(); + + Collections.shuffle(sentinelList); + for (AgentInfo agentInfo : sentinelList) { + client = createAgentClient(agentInfo.getIp(), agentInfo.getPort()); + if (null != client) { + client.setType(type); + break; + } + } + if (null == client) { + LOG.warn("SgAgent not available, check the network." + + " ip: " + ProcessInfoUtil.getLocalIpv4() + + "|env: " + ProcessInfoUtil.getAppEnv() + + "|sentinels:" + sentinelList.toString()); + } + } else { + for (AgentInfo agentInfo : customizedList) { + client = createAgentClient(agentInfo.getIp(), agentInfo.getPort()); + if (null != client) { + client.setType(type); + break; + } + } + if (null == client) { + LOG.warn("SgAgent not available, check the network. The customized agent list is {}", customizedList.toString()); + } + } + return client; + } + + private static SGAgentClient createAgentClient(String ip, int port) { + SGAgentClient client = null; + TSocket socket = new TSocket(ip, port, Consts.CONNECT_TIMEOUT); + try { + socket.setTimeout(Consts.DEFAULT_TIMEOUT_IN_MILLS); + socket.open(); + } catch (TTransportException e) { + //no log. because the log may make the RDs confused + LOG.debug("fail to open socket to sg_agent.", e); + return null; + } + + TFramedTransport transport = new TFramedTransport(socket, Consts.DEFALT_MAX_RESPONSE_MESSAGE_BYTES); + TProtocol protocol = new TBinaryProtocol(transport); + ServiceAgent.Client iface = new ServiceAgent.Client(protocol); + client = new SGAgentClient(); + client.setIface(iface); + client.setTSocket(socket); + + return client; + + } + + /** + * check health & locality; if not, try to recreate client + */ + private static SGAgentClient checkHealthLocality(SGAgentClient client) { + + SGAgentClient newClient = client; + if (null == client) { + // TODO 这种情况下需要如何处理? + LOG.warn("checkHealthLocality failed, client is null"); + } else if (null == client.getTSocket()) { + newClient = getSGAgentClient(client.getType()); + } else if (!client.isLocal() && CustomizedManager.getCustomizedAgentList().isEmpty()) { + //If local sg_agent is OK, using it to replace sg_sentinel and destorying the connection of sg_sentinel. + SGAgentClient localClient = createAgentClient(Consts.LOCALHOST, SGAGENT_PORT); + if ((null != localClient) && (null != localClient.getTSocket())) { + client.destory(); + newClient = localClient; + newClient.setType(client.getType()); + } + } + return newClient; + } + + +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/sentinel/CustomizedManager.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/sentinel/CustomizedManager.java new file mode 100644 index 0000000..59e4097 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/sentinel/CustomizedManager.java @@ -0,0 +1,96 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.sentinel; + +import com.meituan.octo.mns.model.AgentInfo; +import com.meituan.octo.mns.util.IpUtil; +import com.meituan.octo.mns.util.ProcessInfoUtil; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class CustomizedManager { + private static final Logger LOG = LoggerFactory.getLogger(CustomizedManager.class); + private static List customizedAgentList = new ArrayList(); + + private CustomizedManager() { + } + + public static List getCustomizedAgentList() { + return customizedAgentList; + } + + //not recommended to use + public static void setCustomizedSGAgents(String customizedAgentStr) { + customizedAgentList.clear(); + if (StringUtils.isEmpty(customizedAgentStr)) { + LOG.warn("The customized agent list is empty. customizedAgentStr={}", customizedAgentStr); + return; + } + String[] strArray = customizedAgentStr.split(","); + List errorAgentList = new ArrayList(); + for (String item : strArray) { + handleAgentIpPort(item, errorAgentList); + } + if (!errorAgentList.isEmpty()) { + LOG.error("Invalid customized agent list, {}", errorAgentList.toString()); + } + + Collections.shuffle(customizedAgentList); + } + + private static void handleAgentIpPort(String ipPortStr, List errorList) { + if (!ipPortStr.contains(":")) { + errorList.add(ipPortStr); + return; + } + String[] ipPort = ipPortStr.split(":"); + if (2 != ipPort.length) { + errorList.add(ipPortStr); + return; + } + String cusIp = ipPort[0]; + if (!IpUtil.checkIP(cusIp)) { + errorList.add(ipPortStr); + return; + } + int port = Integer.parseInt(ipPort[1]); + if (port < Math.pow(2, 10) || port > Math.pow(2, 16)) { + errorList.add(ipPortStr); + return; + } + boolean isExist = false; + for (AgentInfo info : customizedAgentList) { + if (info.getIp().equals(cusIp) && info.getPort() == port) { + isExist = true; + break; + } + } + if (!isExist) { + AgentInfo item = new AgentInfo(cusIp, port, ProcessInfoUtil.getSgagentAppkey(), ""); + customizedAgentList.add(item); + } + } +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/sentinel/SentinelManager.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/sentinel/SentinelManager.java new file mode 100644 index 0000000..ee3752b --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/sentinel/SentinelManager.java @@ -0,0 +1,87 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.sentinel; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.meituan.octo.mns.Consts; +import com.meituan.octo.mns.model.AgentInfo; +import com.meituan.octo.mns.util.HttpUtil; +import com.meituan.octo.mns.util.ProcessInfoUtil; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class SentinelManager { + private static final Logger LOG = LoggerFactory.getLogger(SentinelManager.class); + private static List sentinelAgentList = new ArrayList(); + private static final Object LOCK = new Object(); + + private SentinelManager() { + + } + + public static void initSentinels() { + String env = ProcessInfoUtil.getOctoEnv(); + String ip = ProcessInfoUtil.getLocalIpv4(); + StringBuilder sb = new StringBuilder(Consts.GET_SERVER_LIST_API); + sb.append("ip=" + ip) + .append("&env=" + env) + .append("&appkey=" + ProcessInfoUtil.getSgsentinelAppkey()); + String result = HttpUtil.get(sb.toString()); + if (StringUtils.isEmpty(result)) { + LOG.warn("failed to get sg_sentinel from {}", Consts.GET_SERVER_LIST_API); + return; + } + + try { + ObjectMapper mapper = new ObjectMapper(); + JsonNode rootNode = mapper.readTree(result); + JsonNode serviceList = rootNode.path("data").path("serviceList"); + if (null != serviceList) { + sentinelAgentList.clear(); + Iterator iter = serviceList.elements(); + while (iter.hasNext()) { + JsonNode serviceNode = iter.next(); + sentinelAgentList.add(new AgentInfo(serviceNode.path("ip").textValue(), + serviceNode.path("port").intValue(), ProcessInfoUtil.getSgsentinelAppkey(), env)); + } + } + } catch (Exception e) { + LOG.warn(e.getMessage(), e); + } + } + + public static List getSentinelAgentList() { + if (sentinelAgentList.isEmpty()) { + synchronized (LOCK) { + if (sentinelAgentList.isEmpty()) { + initSentinels(); + } + } + } + return sentinelAgentList; + } +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/AbractIdcParser.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/AbractIdcParser.java new file mode 100644 index 0000000..12c97d9 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/AbractIdcParser.java @@ -0,0 +1,29 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.util; + +import com.meituan.octo.mns.model.IDC; + +import java.util.List; + +public interface AbractIdcParser { + boolean initIdcXml(String filePath, List idcResult); +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/DefaultIdcParser.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/DefaultIdcParser.java new file mode 100644 index 0000000..ca5bfd1 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/DefaultIdcParser.java @@ -0,0 +1,104 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.util; + +import com.meituan.octo.mns.Consts; +import com.meituan.octo.mns.model.IDC; +import com.octo.idc.model.Idc; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.File; +import java.util.List; + +public class DefaultIdcParser implements AbractIdcParser { + private static final Logger LOG = LoggerFactory.getLogger(DefaultIdcParser.class); + + @Override + public boolean initIdcXml(String filePath, List idcResult) { + boolean ret = false; + try { + // make sure that the cache is empty. + idcResult.clear(); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setIgnoringElementContentWhitespace(true); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document xml = builder.parse(new File(filePath)); + NodeList regionList = xml.getElementsByTagName("Region"); + + for (int regionIter = 0; regionIter < regionList.getLength(); ++regionIter) { + Element region = (Element) regionList.item(regionIter); + + NodeList regionNames = region.getElementsByTagName("RegionName"); + String regionName = regionNames.getLength() > 0 ? regionNames.item(0).getFirstChild().getNodeValue() : Consts.UNKNOWN; + + NodeList idcs = region.getElementsByTagName("IDC"); + for (int idcIter = 0; idcIter < idcs.getLength(); ++idcIter) { + Element idc = (Element) idcs.item(idcIter); + + NodeList idcNames = idc.getElementsByTagName("IDCName"); + String idcName = idcNames.getLength() > 0 ? idcNames.item(0).getFirstChild().getNodeValue() : Consts.UNKNOWN; + + NodeList centerNames = idc.getElementsByTagName("CenterName"); + String centerName = centerNames.getLength() > 0 ? centerNames.item(0).getFirstChild().getNodeValue() : Consts.UNKNOWN; + + NodeList items = idc.getElementsByTagName("Item"); + for (int itemIter = 0; itemIter < items.getLength(); ++itemIter) { + Element item = (Element) items.item(itemIter); + NodeList ips = item.getElementsByTagName("IP"); + NodeList masks = item.getElementsByTagName("MASK"); + if (ips.getLength() <= 0 || masks.getLength() <= 0) { + //idc.xml is error + continue; + } + + String idcIp = ips.item(0).getFirstChild().getNodeValue(); + String idcMask = masks.item(0).getFirstChild().getNodeValue(); + IDC idcItem = new IDC(); + idcItem.setIp(idcIp); + idcItem.setMask(idcMask); + + com.octo.idc.model.Idc idcinfo = new Idc(); + idcinfo.setIdc(idcName); + idcinfo.setRegion(regionName); + idcinfo.setCenter(centerName); + idcItem.setIdcinfo(idcinfo); + + idcItem.init(); + idcResult.add(idcItem); + } + } + } + ret = true; + } catch (Exception e) { + LOG.warn("failed to read local idc file {}", filePath, e); + ret = false; + } finally { + IpUtil.setIsInitSGAgentIDCXml(true); + } + return ret; + } +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/HttpUtil.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/HttpUtil.java new file mode 100644 index 0000000..88edf61 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/HttpUtil.java @@ -0,0 +1,94 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.util; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.Charset; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HttpUtil { + + private static final Logger LOG = LoggerFactory.getLogger(HttpUtil.class); + + private HttpUtil() { + + } + + public static String get(String url) { + HttpURLConnection connection = null; + String response = ""; + int code = -1; + try { + connection = (HttpURLConnection) new URL(url).openConnection(); + if (connection != null) { + connection.setRequestMethod("GET"); + response = readStream(connection); + code = connection.getResponseCode(); + LOG.debug("get {} {} {}", new Object[]{url, connection.getResponseCode(), response}); + } else { + LOG.debug("can't connect to {}" + url); + } + } catch (Exception e) { + LOG.debug("get {} failed {} {}", new Object[]{url, code, e.getMessage()}, e); + } finally { + if (connection != null) { + try { + connection.disconnect(); + } catch (Exception e) { + LOG.debug("close connection failed... " + url, e); + } + } + } + return response; + } + + private static String readStream(HttpURLConnection connection) throws IOException { + connection.setConnectTimeout(10000); + connection.setReadTimeout(10000); + + String result = null; + StringBuilder sb = new StringBuilder(); + InputStream is = null; + try { + is = new BufferedInputStream(connection.getInputStream()); + BufferedReader br = new BufferedReader(new InputStreamReader(is, Charset.forName("utf-8"))); + String inputLine = ""; + while ((inputLine = br.readLine()) != null) { + sb.append(inputLine); + } + result = sb.toString(); + } catch (Exception e) { + LOG.debug("read connection failed... " + connection.getURL(), e); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + LOG.debug("close connection failed... " + connection.getURL(), e); + } + } + } + return result; + } +} \ No newline at end of file diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/IpUtil.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/IpUtil.java new file mode 100644 index 0000000..397dbf7 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/IpUtil.java @@ -0,0 +1,232 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.util; + +import com.meituan.octo.mns.Consts; +import com.meituan.octo.mns.model.IDC; +import com.octo.idc.model.Idc; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; +import java.io.File; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class IpUtil { + private static final Logger LOG = LoggerFactory.getLogger(IpUtil.class); + private static final String IP_REGEX = "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}"; + + + private static final Object LOCK = new Object(); + private static final ReentrantReadWriteLock IDC_XML_LOCK = new ReentrantReadWriteLock(); + + private static boolean isInitSGAgentIDCXml = false; + private static boolean idcXmlValid = false; + + private static long idcLastModifiedTime = 0; + // the exposed idc class in idl-common + private static List idcxml = new ArrayList(); + + private static Map idcMap = null; + private static Set maskSet = null; + + private static DefaultIdcParser idcParser = new DefaultIdcParser(); + + public static ScheduledExecutorService mnsCommonSchedule = Executors.newSingleThreadScheduledExecutor(new ScheduleTaskFactory("MnsInvoker-Schedule")); + + static { + mnsCommonSchedule.scheduleWithFixedDelay(new Runnable() { + @Override + public void run() { + loadIdcTask(); + } + }, 0, 10, TimeUnit.MINUTES); + } + + IpUtil() { + } + + private static void loadIdcTask() { + String idcPath = ProcessInfoUtil.getIdcPath(); + File file = new File(idcPath); + if (file.exists() && idcLastModifiedTime != file.lastModified()) { + List idcs = new ArrayList(); + boolean ret = idcParser.initIdcXml(idcPath, idcs); + if (ret) { + if (!idcs.isEmpty()) { + refreshIdcData(idcs); + LOG.info("success to reload {}", idcPath); + for (IDC idc : idcs) { + LOG.info("region = {}, center = {}, idc = {}, ip = {}", idc.getIdcinfo().getRegion(), idc.getIdcinfo().getCenter(), idc.getIdcinfo().getIdc(), idc.getIp()); + } + idcLastModifiedTime = file.lastModified(); + idcXmlValid = true; + } else { + LOG.info("the {} is empty, not as expected, ignore it", idcPath); + } + } else { + LOG.error("fail to parse {}", idcPath); + } + } + } + + private static void refreshIdcData(List idcs) { + List idcXmlNew = new ArrayList(); + Map idcTmp = new ConcurrentHashMap(); + Set maskTmp = new HashSet(); + + for (IDC idc : idcs) { + Idc idcXmlItem = new Idc(); + idcXmlItem.setRegion(idc.getIdcinfo().getRegion()) + .setCenter(idc.getIdcinfo().getCenter()) + .setIdc(idc.getIdcinfo().getIdc()); + idcXmlNew.add(idcXmlItem); + + idcTmp.put(idc.getIpMaskValue(), idc); + maskTmp.add(idc.getIntMask()); + } + + IDC_XML_LOCK.writeLock().lock(); + idcMap = idcTmp; + maskSet = maskTmp; + idcxml = idcXmlNew; + IDC_XML_LOCK.writeLock().unlock(); + } + + public static void setIsInitSGAgentIDCXml(boolean isInitSGAgentIDCXml) { + IpUtil.isInitSGAgentIDCXml = isInitSGAgentIDCXml; + } + + + static List getAllIdcs() { + List ret = null; + + if (checkAndloadIdcXmlIfNecessary()) { + // local has the idc.xml, try to reload cache from local. + IDC_XML_LOCK.readLock().lock(); + ret = idcxml; + IDC_XML_LOCK.readLock().unlock(); + } + return ret; + } + + + static boolean checkAndloadIdcXmlIfNecessary() { + if (!isInitSGAgentIDCXml) { + synchronized (LOCK) { + if (!isInitSGAgentIDCXml) { + List idcs = new ArrayList(); + idcXmlValid = idcParser.initIdcXml(ProcessInfoUtil.getIdcPath(), idcs); + if (idcXmlValid) { + refreshIdcData(idcs); + } + } + } + } + return idcXmlValid; + } + + + public static int getIpv4Value(String ip) { + if (StringUtils.isEmpty(ip)) { + return -1; + } + String[] vcIp = ip.split("\\."); + if (4 != vcIp.length) { + return -1; + } + + int address = 0; + int filteNum = 0xFF; + for (int i = 0; i < 4; ++i) { + + int pos = i * 8; + if (!NumberUtils.isDigits(vcIp[3 - i])) { + return -1; + } + int vIp = -1; + try { + vIp = Integer.parseInt(vcIp[3 - i]); + } catch (NumberFormatException e) { + //invalid num. + return -1; + } + + if (vIp > 255 || vIp < 0) { + return -1; + } + address |= ((vIp << pos) & (filteNum << pos)); + } + return address; + } + + private static Idc handleIdcInfoFromLocal(String ip) { + try { + IDC_XML_LOCK.readLock().lock(); + for (Integer mask : maskSet) { + IDC curIDC = idcMap.get(mask & getIpv4Value(ip)); + if (curIDC != null && curIDC.getIntMask() == mask) { + return curIDC.getIdcinfo(); + } + } + Idc resIdc = new Idc(); + resIdc.setIdc(Consts.UNKNOWN).setRegion(Consts.UNKNOWN).setCenter(Consts.UNKNOWN); + return resIdc; + } catch (Exception e) { + LOG.error("failed to handleIdcInfoFromLocal, ip: {}", ip, e); + Idc resIdc = new Idc(); + resIdc.setIdc(Consts.UNKNOWN).setRegion(Consts.UNKNOWN).setCenter(Consts.UNKNOWN); + return resIdc; + } finally { + IDC_XML_LOCK.readLock().unlock(); + } + } + + public static Map getIdcInfoFromLocal(List ips) { + Map resIdcInfo = new HashMap(); + if (!checkAndloadIdcXmlIfNecessary() || null == ips) { + return resIdcInfo; + } + + for (String ip : ips) { + if (null != resIdcInfo.get(ip)) { + //if this ip was already parsed, ignore. + continue; + } + Idc idc = IpUtil.handleIdcInfoFromLocal(ip); + if (null != idc) { + resIdcInfo.put(ip, idc); + } + } + return resIdcInfo; + } + + //because of the use of regular expression matching, be careful of its performance while you call it with high concurrency. + public static boolean checkIP(String ip) { + return StringUtils.isNotEmpty(ip) && ip.matches(IP_REGEX); + } + +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/ProcessConfig.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/ProcessConfig.java new file mode 100644 index 0000000..faf59a1 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/ProcessConfig.java @@ -0,0 +1,170 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.util; + +import com.meituan.octo.mns.Consts; +import com.meituan.octo.mns.model.HostEnv; +import org.apache.commons.lang3.StringUtils; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +class ProcessConfig { + + private static final Logger LOG = LoggerFactory.getLogger(ProcessConfig.class); + + static final Map VALUE_MAP_HOST_ENV = initValueMapHostEnv(); + + private static boolean configIsExist = false; + + private static final Properties CONFIG = loadConfigFromFile(); + + private static final boolean VALID_CONFIG = checkEnv(Consts.ENV_KEY); + + private static final HostEnv HOST_ENV = handleHostEnv(); + + private static final String MNS_ZK_URL = getValueFromConfig(Consts.MNSZK_URL); + + private static final String MNS_URL = getValueFromConfig(Consts.MNS_URL); + + private static final String IDC_PATH = getValueFromConfig(Consts.IDC_PATH); + + private static final String SGAGENT_PORT = getValueFromConfig(Consts.SG_AGENT_PORT); + + private static final String SGAGENT_APPKEY = getValueFromConfig(Consts.SGAENT_APPKEY); + + private static final String SGSENTINEL_APPKEY = getValueFromConfig(Consts.SG_SENTINEL_APPKEY); + + + private static Map initValueMapHostEnv() { + Map ret = new HashMap(5); + ret.put("prod", HostEnv.PROD); + ret.put("stage", HostEnv.STAGE); + ret.put("dev", HostEnv.DEV); + ret.put("ppe", HostEnv.PPE); + ret.put("test", HostEnv.TEST); + return ret; + } + + + private static Properties loadConfigFromFile() { + Properties props = new Properties(); + InputStream in = null; + try { + in = new FileInputStream(Consts.CONFIG_FILE); + props.load(in); + configIsExist = true; + } catch (FileNotFoundException e) { + configIsExist = false; + LOG.error(Consts.CONFIG_FILE + " does not exist", e); + } catch (IOException e) { + LOG.error("Failed to load CONFIG from" + Consts.CONFIG_FILE, e); + } finally { + if (in != null) { + try { + in.close(); + } catch (Exception e) { + LOG.error("Failed to close " + Consts.CONFIG_FILE, e); + } + } + } + return props; + } + + private static String getValueFromConfig(String key) { + return StringUtils.trim(CONFIG.getProperty(key)); + } + + private static HostEnv handleHostEnv() { + if (isValidConfig()) { + return strToHostEnv(StringUtils.trim(CONFIG.getProperty(Consts.ENV_KEY))); + } else { + LOG.warn("{} does not exist or is incomplete.", Consts.CONFIG_FILE); + } + return HostEnv.DEV; + } + + private static boolean checkEnv(String key) { + boolean ret = false; + if (isConfigIsExist()) { + String value = StringUtils.trim(CONFIG.getProperty(key)); + ret = !StringUtils.isEmpty(value) && isEnvValid(value); + } else { + ret = false; + } + + return ret; + } + + static Properties getConfig() { + return CONFIG; + } + + static HostEnv getHostEnv() { + return HOST_ENV; + } + + static boolean isValidConfig() { + return VALID_CONFIG; + } + + private static boolean isEnvValid(String envStr) { + return VALUE_MAP_HOST_ENV.containsKey(envStr); + } + + private static HostEnv strToHostEnv(String envStr) { + return isEnvValid(envStr) ? VALUE_MAP_HOST_ENV.get(envStr) : HostEnv.DEV; + } + + static boolean isConfigIsExist() { + return configIsExist; + } + + static String getMnsZkUrl() { + return MNS_ZK_URL; + } + + static String getMnsUrl() { + return MNS_URL; + } + + static String getIdcPath() { + return IDC_PATH; + } + + static int getSgagentPort() { + return SGAGENT_PORT == null ? 5266 : Integer.parseInt(SGAGENT_PORT); + } + + static String getSgagentAppkey() { + return SGAGENT_APPKEY; + } + + static String getSgsentinelAppkey() { + return SGSENTINEL_APPKEY; + } +} diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/ProcessInfoUtil.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/ProcessInfoUtil.java new file mode 100644 index 0000000..9196c15 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/ProcessInfoUtil.java @@ -0,0 +1,179 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.util; + +import com.meituan.octo.mns.exception.MnsException; +import com.meituan.octo.mns.model.HostEnv; +import com.octo.idc.model.Idc; +import org.apache.commons.lang3.StringUtils; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ProcessInfoUtil { + + private static final Logger LOG = LoggerFactory.getLogger(ProcessInfoUtil.class); + + private static final String LOCAL_IPV4 = getIpV4(); + + private static final HostEnv APP_ENV = ProcessConfig.getHostEnv(); + // octo inner env + private static final String OCTO_ENV_STR = parseOctoEnv(); + + public static String getAppEnv() { + return APP_ENV.name(); + } + + public static String getOctoEnv() { + return OCTO_ENV_STR; + } + + private static String parseOctoEnv() { + String env = "prod"; + if (ProcessConfig.isValidConfig()) { + switch (APP_ENV) { + case PROD: + env = "prod"; + break; + case STAGE: + env = "stage"; + break; + case PPE: + env = "stage"; + break; + case DEV: + env = "prod"; + break; + case TEST: + env = "test"; + break; + default: + env = "prod"; + break; + + } + } + return env; + } + + private static String getIpV4() { + String ip = ""; + Enumeration networkInterface; + try { + networkInterface = NetworkInterface.getNetworkInterfaces(); + } catch (SocketException e) { + LOG.error("fail to get network interface information.", e); + return ip; + } + Set ips = new HashSet(); + while (networkInterface.hasMoreElements()) { + NetworkInterface ni = networkInterface.nextElement(); + + Enumeration inetAddress = null; + try { + if (null != ni) { + inetAddress = ni.getInetAddresses(); + } + } catch (Exception e) { + LOG.debug("fail to get ip information.", e); + } + while (null != inetAddress && inetAddress.hasMoreElements()) { + InetAddress ia = inetAddress.nextElement(); + if (ia instanceof Inet6Address) { + continue; // ignore ipv6 + } + String thisIp = ia.getHostAddress(); + // 排除 回送地址 + if (!ia.isLoopbackAddress() && !thisIp.contains(":") && !"127.0.0.1".equals(thisIp)) { + ips.add(thisIp); + if (StringUtils.isEmpty(ip)) { + ip = thisIp; + } + } + } + } + + if (ips.size() >= 2) { + ip = (String) ips.toArray()[0]; + } + + if (StringUtils.isEmpty(ip)) { + LOG.error("cannot get local ip."); + ip = ""; + } + + return ip; + } + + public static String getLocalIpv4() { + return LOCAL_IPV4; + } + + public static boolean isLocalHostOnline() { + return HostEnv.PROD == APP_ENV || HostEnv.STAGE == APP_ENV; + } + + public static List getIdcs() { + return IpUtil.getAllIdcs(); + } + + public static Map getIdcInfo(List ips) throws MnsException { + Map resIdcInfo = new HashMap(); + if (null == ips || ips.isEmpty()) { + return resIdcInfo; + } + + if (IpUtil.checkAndloadIdcXmlIfNecessary()) { + resIdcInfo.putAll(IpUtil.getIdcInfoFromLocal(ips)); + } + + return resIdcInfo; + } + + public static String getMnsZKUrl() { + return ProcessConfig.getMnsZkUrl(); + } + + public static String getMnsUrl() { + return ProcessConfig.getMnsUrl(); + } + + public static String getIdcPath() { + return ProcessConfig.getIdcPath(); + } + + public static int getSgagentPort() { + return ProcessConfig.getSgagentPort(); + } + + public static String getSgagentAppkey() { + return ProcessConfig.getSgagentAppkey(); + } + + public static String getSgsentinelAppkey() { + return ProcessConfig.getSgsentinelAppkey(); + } + +} \ No newline at end of file diff --git a/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/ScheduleTaskFactory.java b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/ScheduleTaskFactory.java new file mode 100644 index 0000000..bfa2e47 --- /dev/null +++ b/sdk/mns-invoker/src/main/java/com/meituan/octo/mns/util/ScheduleTaskFactory.java @@ -0,0 +1,52 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.util; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +public class ScheduleTaskFactory implements ThreadFactory { + + private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1); + private final ThreadGroup group; + private final AtomicInteger threadNumber = new AtomicInteger(1); + private final String namePrefix; + + public ScheduleTaskFactory(String threadPoolName) { + SecurityManager s = System.getSecurityManager(); + group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); + namePrefix = threadPoolName + "-" + + POOL_NUMBER.getAndIncrement() + + "-thread-"; + } + + @Override + public Thread newThread(Runnable r) { + Thread t = new Thread(group, r, + namePrefix + threadNumber.getAndIncrement(), 0); + + t.setDaemon(true); + if (t.getPriority() != Thread.NORM_PRIORITY) { + t.setPriority(Thread.NORM_PRIORITY); + } + return t; + } +} diff --git a/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/AsyncTests.java b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/AsyncTests.java new file mode 100644 index 0000000..45e07bd --- /dev/null +++ b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/AsyncTests.java @@ -0,0 +1,84 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns; + +import com.meituan.octo.mns.sentinel.CustomizedManager; +import com.octo.naming.common.thrift.model.ProtocolRequest; +import com.octo.naming.common.thrift.model.SGService; +import com.octo.naming.service.thrift.model.ServiceAgent; +import org.apache.thrift.TException; +import org.apache.thrift.async.AsyncMethodCallback; +import org.apache.thrift.async.TAsyncClientManager; +import org.apache.thrift.protocol.TBinaryProtocol; +import org.apache.thrift.protocol.TProtocolFactory; +import org.apache.thrift.transport.TNonblockingSocket; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public class AsyncTests { + private static Logger LOG = LoggerFactory.getLogger(AsyncTests.class); + String providerAppkey = "com.sankuai.inf.dorado.server"; + String localAppkey = "com.sankuai.octo.tmy"; + + @Before + public void setCustomizedSgagent() { + CustomizedManager.setCustomizedSGAgents("10.22.23.29:5266"); + } + + @Test + public void testAsync() throws Exception { + TProtocolFactory factory = new TBinaryProtocol.Factory(); + TAsyncClientManager manager = new TAsyncClientManager(); + ServiceAgent.AsyncClient.Factory clientFactory = new ServiceAgent.AsyncClient.Factory(manager, factory); + + ServiceAgent.AsyncClient client = clientFactory.getAsyncClient( + new TNonblockingSocket("10.22.23.29", 5266, Consts.CONNECT_TIMEOUT)); + AsyncMethodCallback callback1 = new ServiceListCallback(); + ProtocolRequest request = new ProtocolRequest(); + request.setProtocol("thrift") + .setLocalAppkey(localAppkey) + .setRemoteAppkey(providerAppkey); + client.getOriginServiceList(request, callback1); + Thread.sleep(10000); + } + + class ServiceListCallback implements AsyncMethodCallback { + + @Override + public void onComplete(ServiceAgent.AsyncClient.getOriginServiceList_call getOriginServiceList_call) { + try { + List list = getOriginServiceList_call.getResult().getServicelist(); + LOG.info("{}", list.size()); + } catch (TException e) { + e.printStackTrace(); + } + } + + @Override + public void onError(Exception e) { + e.printStackTrace(); + } + } +} diff --git a/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/InvokeProxyTests.java b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/InvokeProxyTests.java new file mode 100644 index 0000000..47fdd4e --- /dev/null +++ b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/InvokeProxyTests.java @@ -0,0 +1,97 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns; + + +import com.meituan.octo.mns.model.SGAgentClient; +import com.meituan.octo.mns.sentinel.CustomizedManager; +import com.octo.naming.common.thrift.model.ProtocolRequest; +import com.octo.naming.common.thrift.model.SGService; +import com.octo.naming.service.thrift.model.ServiceAgent; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public class InvokeProxyTests { + private static Logger LOG = LoggerFactory.getLogger(InvokeProxyTests.class); + String remoteAppkey = "com.sankuai.inf.dorado.server"; + String localAppkey = "com.sankuai.octo.tmy"; + + @Before + public void setCustomizedSgagent() { + CustomizedManager.setCustomizedSGAgents("10.22.23.29:5266"); + } + + @Test + public void testProxy() { + InvokeProxy invoker = new InvokeProxy(SGAgentClient.ClientType.temp); + try { + ServiceAgent.Iface proxy = invoker.getProxy(); + ProtocolRequest thriftReq = new ProtocolRequest() + .setLocalAppkey(localAppkey) + .setRemoteAppkey(remoteAppkey) + .setProtocol("thrift"); + List serviceList = proxy.getServiceListByProtocol(thriftReq).getServicelist(); + LOG.info("{}", serviceList); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + // please use jprofiler to run this test case. be careful the memory of the byte[] and full gc. + @Test + public void multiThreadProxy() throws Exception { + final ServiceAgent.Iface multiProtocolClient = new InvokeProxy(SGAgentClient.ClientType.multiProto).getProxy(); + for (int i = 0; i < 5; ++i) { + + + Thread th2 = new Thread(new Runnable() { + @Override + public void run() { + + ProtocolRequest req = new ProtocolRequest(); + req.setProtocol("thrift") + .setRemoteAppkey("com.sankuai.inf.mnsc"); + while (true) { + try { + multiProtocolClient.getServiceListByProtocol(req); + Thread.sleep(10); + } catch (Exception e) { + Assert.assertTrue(false); + } + + } + + + } + }); + + th2.start(); + } + + Thread.sleep(1000 * 120); + } +} diff --git a/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/RegisterTests.java b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/RegisterTests.java new file mode 100644 index 0000000..20221cc --- /dev/null +++ b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/RegisterTests.java @@ -0,0 +1,109 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns; + + +import com.meituan.octo.mns.sentinel.CustomizedManager; +import com.meituan.octo.mns.util.HttpUtilTests; +import com.meituan.octo.mns.util.ProcessInfoUtil; +import com.octo.naming.common.thrift.model.ProtocolRequest; +import com.octo.naming.common.thrift.model.SGService; +import com.octo.naming.common.thrift.model.ServiceDetail; +import org.apache.thrift.TException; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class RegisterTests { + private static Logger LOG = LoggerFactory.getLogger(RegisterTests.class); + String providerAppkey = "com.sankuai.inf.dorado.server"; + String localAppkey = "com.sankuai.octo.tmy"; + int port = 9002; + private static String localIP = ProcessInfoUtil.getLocalIpv4(); + + @Test + public void register() throws TException, InterruptedException { + SGService service = SGServiceUtilTests.getDefaultSGService(providerAppkey, 5198, true); + service.setProtocol("thrift"); + MnsInvoker.registServiceWithCmd(0, service); + Thread.sleep(5000); + } + + @Test + public void testAddRegister() throws InterruptedException, TException { + ProtocolRequest request = new ProtocolRequest(); + request.setProtocol("thrift") + .setLocalAppkey(localAppkey) + .setRemoteAppkey(providerAppkey); + List list = MnsInvoker.getServiceList(request); + int size1 = list.size(); + + SGService service = SGServiceUtilTests.getDefaultSGService(providerAppkey, port, true); + Map serviceNames = new HashMap(); + ServiceDetail detail = new ServiceDetail(); + detail.setUnifiedProto(true); + serviceNames.put("octo.service.base_a", detail); + service.setServiceInfo(serviceNames); + MnsInvoker.registServiceWithCmd(1, service); + Thread.sleep(5000); + + list = MnsInvoker.getServiceList(request); + + service.getServiceInfo().put("octo.service.base_b", detail); + MnsInvoker.registServiceWithCmd(1, service); + + list = MnsInvoker.getServiceList(request); + LOG.info("{}", list.size()); + } + + @Test + public void testServiceName() throws InterruptedException, TException { + int port = 10002; + String serviceName = "octo.service.base_c"; + HttpUtilTests.delete(providerAppkey, "thrift", localIP, port); + SGService service = SGServiceUtilTests.getDefaultSGService(providerAppkey, port, true); + Map serviceNames = new HashMap(); + ServiceDetail detail = new ServiceDetail(); + detail.setUnifiedProto(true); + serviceNames.put(serviceName, detail); + service.setServiceInfo(serviceNames); + MnsInvoker.registServiceWithCmd(0, service); + Thread.sleep(10000); + ProtocolRequest request = new ProtocolRequest(); + request.setProtocol("thrift") + .setLocalAppkey(localAppkey) + .setServiceName(serviceName); + List list = MnsInvoker.getServiceList(request); + boolean isExist = false; + for (SGService item : list) { + if (localIP.equals(item.getIp()) && port == item.getPort() && item.getServiceInfo().containsKey(serviceName)) { + isExist = true; + } + } + Assert.assertTrue(isExist); + } +} diff --git a/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/SGServiceUtilTests.java b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/SGServiceUtilTests.java new file mode 100644 index 0000000..2256cec --- /dev/null +++ b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/SGServiceUtilTests.java @@ -0,0 +1,44 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns; + +import com.meituan.octo.mns.util.ProcessInfoUtil; +import com.octo.naming.common.thrift.model.SGService; + + +public class SGServiceUtilTests { + private static String localIp = ProcessInfoUtil.getLocalIpv4(); + + public static SGService getDefaultSGService(final String appkey, final int port, final boolean isThrift) { + String protocol = isThrift ? "thrift" : "http"; + SGService service = new SGService(); + service.setAppkey(appkey); + service.setPort(port); + service.setVersion("original"); + service.setIp(localIp); + service.setLastUpdateTime((int) (System.currentTimeMillis() / 1000)); + service.setServerType(isThrift ? 0 : 1); + service.setWeight(10); + service.setFweight(10.d); + service.setProtocol(protocol); + return service; + } +} diff --git a/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/SocketClientPortTests.java b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/SocketClientPortTests.java new file mode 100644 index 0000000..d37ad80 --- /dev/null +++ b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/SocketClientPortTests.java @@ -0,0 +1,51 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns; + +import junit.framework.Assert; +import org.apache.thrift.transport.TSocket; +import org.apache.thrift.transport.TTransportException; +import org.junit.Test; + +import java.io.IOException; +import java.net.InetSocketAddress; + +public class SocketClientPortTests { + + private int localPort = 40000; + + @Test + public void clientPortConfig() throws IOException { + TSocket socket = new TSocket("127.0.0.1", 5266, Consts.CONNECT_TIMEOUT); + socket.getSocket().bind(new InetSocketAddress(localPort)); + try { + socket.open(); + socket.setTimeout(Consts.DEFAULT_TIMEOUT_IN_MILLS); + System.out.println(socket.getSocket()); + Assert.assertTrue(socket.getSocket().toString().contains(localPort + "")); + } catch (TTransportException e) { + e.printStackTrace(); + } finally { + socket.close(); + } + + } +} diff --git a/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/cache/MnsCacheTests.java b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/cache/MnsCacheTests.java new file mode 100644 index 0000000..4191bc5 --- /dev/null +++ b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/cache/MnsCacheTests.java @@ -0,0 +1,69 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.cache; + +import com.meituan.octo.mns.util.ProcessInfoUtil; +import com.octo.naming.common.thrift.model.SGService; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class MnsCacheTests { + private static final Logger LOG = LoggerFactory.getLogger(MnsCacheTests.class); + + @Test + public void test() { + + MnsCache cache = new MnsCache>( + new CacheLoader>() { + @Override + public List reload(String row, String column) { + return null; + } + }); + LOG.info("{}", cache.get("local", "remote")); + cache.put("local", "remote", Arrays.asList(randService())); + LOG.info("{}", cache.get("local", "remote")); + cache.updateAll(); + cache.put("local", "remote", Collections.emptyList()); + LOG.info("{}", cache.get("local", "remote")); + cache.put("", "test", "test"); + LOG.info("{}", cache.get("", "test")); + cache.updateAll(); + } + + private SGService randService() { + SGService sgService = new SGService(); + sgService.setAppkey("test"); + sgService.setIp(ProcessInfoUtil.getLocalIpv4()); + sgService.setPort(111); + sgService.setLastUpdateTime((int) (System.currentTimeMillis() / 1000)); + sgService.setVersion("original"); + sgService.setWeight(10); + sgService.setFweight(10.d); + + return sgService; + } +} diff --git a/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/cache/MultiMapTests.java b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/cache/MultiMapTests.java new file mode 100644 index 0000000..c0dd04f --- /dev/null +++ b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/cache/MultiMapTests.java @@ -0,0 +1,73 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.cache; + + +import com.octo.naming.common.thrift.model.SGService; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +public class MultiMapTests { + @Test + public void testMap() { + MultiMap map = new MultiMap(); + Assert.assertTrue(map.rows().isEmpty()); + Assert.assertTrue(map.columns(null).isEmpty()); + Assert.assertTrue(map.columns("test").isEmpty()); + Assert.assertNull(map.get(null)); + Assert.assertNull(map.get("row")); + Assert.assertNull(map.get(null, null)); + Assert.assertNull(map.get("row", null)); + Assert.assertNull(map.get(null, "column")); + Assert.assertNull(map.getOrCreate(null)); + Assert.assertTrue(map.getOrCreate("row").isEmpty()); + Assert.assertFalse(map.rows().isEmpty()); + + Assert.assertTrue(map.columns(null).isEmpty()); + Assert.assertTrue(map.columns("test").isEmpty()); + + map.put(null, null, null); + Assert.assertNull(map.get(null, null)); + + map.put("row", null, null); + Assert.assertNull(map.get("row", null)); + + map.put(null, "column", null); + Assert.assertNull(map.get(null, "column")); + map.put("row", "column", null); + Assert.assertNull(map.get("row", "column")); + map.put("row", "column", "value"); + Assert.assertEquals("value", map.get("row", "column")); + + map.put("row", "column", null); + Assert.assertEquals("value", map.get("row", "column")); + Assert.assertFalse(map.rows().isEmpty()); + Assert.assertTrue(map.columns(null).isEmpty()); + Assert.assertTrue(map.columns("test").isEmpty()); + + Map hashMap = new HashMap(); + String value = hashMap.get(null); + Assert.assertNull(value); + } +} diff --git a/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/cache/getServerTests.java b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/cache/getServerTests.java new file mode 100644 index 0000000..deb943c --- /dev/null +++ b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/cache/getServerTests.java @@ -0,0 +1,105 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.cache; + +import com.meituan.octo.mns.MnsInvoker; +import com.meituan.octo.mns.listener.ServiceListListenerTest; +import com.meituan.octo.mns.sentinel.CustomizedManager; +import com.meituan.octo.mns.util.HttpUtilTests; +import com.octo.naming.common.thrift.model.ProtocolRequest; +import com.octo.naming.common.thrift.model.SGService; +import org.apache.thrift.TException; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; + +public class getServerTests { + private static Logger LOG = LoggerFactory.getLogger(ServiceListListenerTest.class); + + final String consumerAppkey = "com.sankuai.octo.tmy"; + final String remoteAppkey = "com.sankuai.inf.dorado.server"; + + /*@Before + public void setCustomizedSgagent() { + CustomizedManager.setCustomizedSGAgents("10.22.23.29:5266"); + }*/ + + @Test + public void testProtocolServiceList() throws TException, InterruptedException { + System.out.println("【testGetServiceListByProtocol】thrift http redis cunsumerAppkey =" + consumerAppkey + " and remoteAppkey = " + remoteAppkey); + + ProtocolRequest httpReq = new ProtocolRequest() + .setLocalAppkey(consumerAppkey) + .setRemoteAppkey(remoteAppkey) + .setProtocol("http"); + ProtocolRequest thriftReq = new ProtocolRequest() + .setLocalAppkey(consumerAppkey) + .setRemoteAppkey(remoteAppkey) + .setProtocol("thrift"); + + + List httpList = MnsInvoker.getServiceList(httpReq); + List thriftList = MnsInvoker.getServiceList(thriftReq); + LOG.info("{}", httpList.size()); + LOG.info("{}", thriftList.size()); + + } + + + @Test + public void multiThread() throws InterruptedException { + for (int i = 1; i < 3; i++) { + new Thread() { + @Override + public void run() { + try { + try { + testProtocolServiceList(); + } catch (TException e) { + Assert.assertTrue(false); + } + + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + }.start(); + } + Thread.sleep(1000); + } + + + public static void delete(String remoteAppkey, String protocol, String ipPort) throws InterruptedException { + List ipPorts = new ArrayList(); + ipPorts.add(ipPort); + String url = "http://mns.test.sankuai.info/api/providers/delete"; + String data = HttpUtilTests.getDeletedProviderJson(remoteAppkey, protocol, ipPorts, 3); + HttpUtilTests.delete(url, data); + Thread.sleep(5000); + } + + +} diff --git a/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/http/HttpServerPublisherTests.java b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/http/HttpServerPublisherTests.java new file mode 100644 index 0000000..6cdba52 --- /dev/null +++ b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/http/HttpServerPublisherTests.java @@ -0,0 +1,63 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.http; + +import com.meituan.octo.mns.MnsInvoker; +import com.meituan.octo.mns.sentinel.CustomizedManager; +import com.meituan.octo.mns.util.ProcessInfoUtil; +import com.octo.naming.common.thrift.model.ProtocolRequest; +import com.octo.naming.common.thrift.model.SGService; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + + +public class HttpServerPublisherTests { + + @Test + public void testRegist() throws Exception { + //CustomizedManager.setCustomizedSGAgents("10.22.23.29:5266"); + String remoteAppkey = "com.sankuai.inf.dorado.server"; + int port = 5110; + + HttpServerPublisher httpServerPublisher = new HttpServerPublisher(); + httpServerPublisher.setAppKey(remoteAppkey); + httpServerPublisher.setPort(port); + httpServerPublisher.setVersion("original"); + httpServerPublisher.publish(); + + Thread.sleep(3000); + + boolean suc = false; + ProtocolRequest request = new ProtocolRequest(); + request.setProtocol("http") + .setRemoteAppkey(remoteAppkey); + List services = MnsInvoker.getServiceList(request); + for (SGService sgService : services) { + if (sgService.getIp().equals(ProcessInfoUtil.getLocalIpv4()) && sgService.getPort() == port) { + suc = true; + break; + } + } + Assert.assertTrue(suc); + } +} diff --git a/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/listener/ServiceListListenerTest.java b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/listener/ServiceListListenerTest.java new file mode 100644 index 0000000..6ba9881 --- /dev/null +++ b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/listener/ServiceListListenerTest.java @@ -0,0 +1,170 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.listener; + +import com.meituan.octo.mns.MnsInvoker; +import com.meituan.octo.mns.SGServiceUtilTests; +import com.meituan.octo.mns.sentinel.CustomizedManager; +import com.meituan.octo.mns.util.HttpUtilTests; +import com.meituan.octo.mns.util.ProcessInfoUtil; +import com.octo.naming.common.thrift.model.ProtocolRequest; +import com.octo.naming.common.thrift.model.SGService; +import org.apache.thrift.TException; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +public class ServiceListListenerTest { + private static Logger LOG = LoggerFactory.getLogger(ServiceListListenerTest.class); + String remoteAppkey = "com.sankuai.inf.dorado.server"; + String localAppkey = "com.sankuai.octo.tmy"; + int port = 9010; + String localIP = ProcessInfoUtil.getLocalIpv4(); + boolean addCallback = false, deletedCallback = false; + + private enum ServiceType { + PROTOCOL, ORIGIN + } + + + private class MyListener implements IServiceListChangeListener { + @Override + public void changed(ProtocolRequest req, List oldList, List newList, List addList, List deletedList, List modifiedList) { + System.out.println("req protocol: " + req.getProtocol()); + if (!addList.isEmpty()) { + addCallback = true; + print("addList:", addList); + } + + if (!deletedList.isEmpty()) { + deletedCallback = true; + print("deletedList:", deletedList); + } + + } + + private void print(String msg, List list) { + System.out.println(msg); + for (SGService service : list) { + System.out.println(service); + } + } + } + + @Test + public void serviceListListenerTest() throws TException, InterruptedException { + testListener(ServiceType.ORIGIN); + testListener(ServiceType.PROTOCOL); + } + + private void testListener(ServiceType type) throws TException, InterruptedException { + ProtocolRequest httpReq = new ProtocolRequest() + .setLocalAppkey(localAppkey) + .setRemoteAppkey(remoteAppkey) + .setProtocol("http"); + ProtocolRequest thriftReq = new ProtocolRequest() + .setLocalAppkey(localAppkey) + .setRemoteAppkey(remoteAppkey) + .setProtocol("thrift"); + + IServiceListChangeListener thriftListener = new MyListener(); + IServiceListChangeListener httpListener = new MyListener(); + delete(); + + addCallback = false; + deletedCallback = false; + switch (type) { + case PROTOCOL: + Assert.assertEquals(0, MnsInvoker.addServiceListener(thriftReq, thriftListener)); + Assert.assertEquals(0, MnsInvoker.addServiceListener(httpReq, httpListener)); + break; + case ORIGIN: + Assert.assertEquals(0, MnsInvoker.addOriginServiceListener(thriftReq, thriftListener)); + Assert.assertEquals(0, MnsInvoker.addOriginServiceListener(httpReq, httpListener)); + break; + } + + + LOG.info("Now start to test listener"); + register(); + Assert.assertTrue(addCallback); + delete(); + Assert.assertTrue(deletedCallback); + LOG.info("Now start to test remove listener"); + + switch (type) { + case PROTOCOL: + Assert.assertEquals(0, MnsInvoker.removeServiceListener(thriftReq, thriftListener)); + Assert.assertEquals(0, MnsInvoker.removeServiceListener(httpReq, httpListener)); + break; + case ORIGIN: + Assert.assertEquals(0, MnsInvoker.removeOriginServiceListener(thriftReq, thriftListener)); + Assert.assertEquals(0, MnsInvoker.removeOriginServiceListener(httpReq, httpListener)); + break; + } + + addCallback = false; + deletedCallback = false; + register(); + delete(); + Assert.assertFalse(addCallback || deletedCallback); + } + + + private void delete() throws InterruptedException { + HttpUtilTests.delete(remoteAppkey, "thrift", localIP, 10000); + HttpUtilTests.delete(remoteAppkey, "thrift", localIP, 10001); + + HttpUtilTests.delete(remoteAppkey, "http", localIP, 10000); + HttpUtilTests.delete(remoteAppkey, "http", localIP, 10001); + Thread.sleep(10000); + + } + + private void register() throws TException, InterruptedException { + int weigth = 10; + registerHandle("thrift", localIP, 10000, weigth); + registerHandle("thrift", localIP, 10001, weigth); + + registerHandle("http", localIP, 10000, weigth); + registerHandle("http", localIP, 10001, weigth); + Thread.sleep(10000); + + } + + private void registerHandle(String protocol, String ip, int port, int weigth) throws TException, InterruptedException { + SGService service = SGServiceUtilTests.getDefaultSGService(remoteAppkey, port, true); + service.setIp(ip); + service.setProtocol(protocol); + service.setWeight(weigth).setFweight(weigth); + MnsInvoker.registServiceWithCmd(0, service); + } + + @After + public void destroy() throws InterruptedException { + delete(); + } +} diff --git a/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/sentinel/AgentClientFactoryTest.java b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/sentinel/AgentClientFactoryTest.java new file mode 100644 index 0000000..2cac8e0 --- /dev/null +++ b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/sentinel/AgentClientFactoryTest.java @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.sentinel; + + +import com.meituan.octo.mns.model.SGAgentClient; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + + +public class AgentClientFactoryTest { + @Before + public void setCustomizedSgagent() { + CustomizedManager.setCustomizedSGAgents("10.22.23.29:5266"); + } + + @Test + public void testConnection() { + checkConnection(SGAgentClient.ClientType.multiProto, true); + checkConnection(SGAgentClient.ClientType.temp, false); + } + + private void checkConnection(SGAgentClient.ClientType type, boolean isLong) { + SGAgentClient client = AgentClientFactory.borrowClient(type); + Assert.assertNotNull(client); + Assert.assertNotNull(client.getTSocket()); + + AgentClientFactory.returnClient(client); + Assert.assertNotNull(client); + if (isLong) { + Assert.assertNotNull(client.getTSocket()); + } else { + Assert.assertNull(client.getTSocket()); + } + Assert.assertEquals(type, client.getType()); + } +} diff --git a/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/sentinel/SentinelTests.java b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/sentinel/SentinelTests.java new file mode 100644 index 0000000..6b3644b --- /dev/null +++ b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/sentinel/SentinelTests.java @@ -0,0 +1,66 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.sentinel; + +import com.meituan.octo.mns.model.AgentInfo; +import com.meituan.octo.mns.util.ProcessInfoUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class SentinelTests { + @Test + public void testGetSentinelAgentList() throws InterruptedException { + for (int i = 0; i < 10; i++) { + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + String strSentinelList = SentinelManager.getSentinelAgentList().toString(); + assertNotNull(strSentinelList); + assertTrue(strSentinelList.contains(ProcessInfoUtil.getSgsentinelAppkey())); + } + }); + thread.start(); + } + Thread.sleep(100000); + } + + @Test + public void testCustomizedSGAgents() { + CustomizedManager.setCustomizedSGAgents("10.1.1.1:5266,10.1.1.2:5266"); + List agentList = CustomizedManager.getCustomizedAgentList(); + Assert.assertFalse(agentList.isEmpty()); + + CustomizedManager.setCustomizedSGAgents("10.1.1.1:5266, 10.1.1.2:5266"); + agentList.clear(); + agentList = CustomizedManager.getCustomizedAgentList(); + Assert.assertTrue(agentList.isEmpty()); + + CustomizedManager.setCustomizedSGAgents("10.1.1.1,10.1.1.2"); + agentList.clear(); + agentList = CustomizedManager.getCustomizedAgentList(); + Assert.assertTrue(agentList.isEmpty()); + } +} diff --git a/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/util/DefaultIdcParserTest.java b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/util/DefaultIdcParserTest.java new file mode 100644 index 0000000..05f3fc5 --- /dev/null +++ b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/util/DefaultIdcParserTest.java @@ -0,0 +1,37 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.util; + +import com.meituan.octo.mns.model.IDC; +import org.junit.Assert; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class DefaultIdcParserTest { + @Test + public void testInitIDCXml() { + List idcResult = new ArrayList(); + Assert.assertTrue(new DefaultIdcParser().initIdcXml(ProcessInfoUtil.getIdcPath(), idcResult)); + Assert.assertFalse(idcResult.isEmpty()); + } +} diff --git a/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/util/HttpUtilTests.java b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/util/HttpUtilTests.java new file mode 100644 index 0000000..466e9e9 --- /dev/null +++ b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/util/HttpUtilTests.java @@ -0,0 +1,163 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.util; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; + + +public class HttpUtilTests { + private static final Logger LOG = LoggerFactory.getLogger(HttpUtil.class); + + public static void delete(String appkey, String protocol, String ip, int port) throws InterruptedException { + List ipPorts = new ArrayList(); + ipPorts.add(ip + ":" + port); + String url = ProcessInfoUtil.getMnsUrl() + "/api/providers/delete"; + String data = getDeletedProviderJson(appkey, protocol, ipPorts, 1); + HttpUtilTests.delete(url, data); + Thread.sleep(6000); + } + + public static String getDeletedProviderJson(String appkey, String protocol, List ipPorts, int env) { + List jsonList = new ArrayList(); + for (String ipPort : ipPorts) { + String[] ipport = ipPort.split(":"); + jsonList.add(getJson(appkey, protocol, ipport[0], ipport[1], env)); + } + return "[" + listToString(jsonList) + "]"; + } + + public static String getJson(String appkey, String protocol, String ip, String port, int env) { + ObjectMapper mapper = new ObjectMapper(); + ObjectNode node = mapper.createObjectNode(); + node.put("appkey", appkey); + node.put("protocol", protocol); + node.put("ip", ip); + node.put("port", Integer.valueOf(port)); + node.put("envir", env); + String ret = node.toString(); + return ret; + } + + public static String listToString(List stringList) { + + StringBuilder result = new StringBuilder(); + boolean flag = false; + for (String string : stringList) { + if (flag) { + result.append(","); + } else { + flag = true; + } + result.append(string); + } + return result.toString(); + } + + public static String delete(String url, String content) { + HttpURLConnection connection = null; + String response = null; + int code = -1; + try { + connection = (HttpURLConnection) new URL(url).openConnection(); + if (connection != null) { + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); + writeContent(connection, content); + response = readStream(connection); + code = connection.getResponseCode(); + LOG.debug("delete {} {} {}", new Object[]{url, connection.getResponseCode(), response}); + } else { + LOG.debug("can't connect to {}" + url); + } + } catch (Exception e) { + LOG.error("delete {} failed {} {}", new Object[]{url, code, e}); + } finally { + if (connection != null) { + try { + connection.disconnect(); + } catch (Exception e) { + LOG.debug("close connection failed... " + url, e); + } + } + } + return response; + } + + private static void writeContent(HttpURLConnection connection, String content) { + OutputStreamWriter out = null; + try { + connection.setDoOutput(true); + out = new OutputStreamWriter(connection.getOutputStream(), Charset.forName("UTF-8")); + out.write(content); + out.flush(); + out.close(); + } catch (Exception e) { + LOG.debug("write content to {} failed {}", new Object[]{connection.getURL(), e}); + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException e) { + LOG.debug("close connection failed... " + connection.getURL(), e); + } + } + } + } + + private static String readStream(HttpURLConnection connection) throws IOException { + connection.setConnectTimeout(10000); + connection.setReadTimeout(10000); + + String result = null; + StringBuilder sb = new StringBuilder(); + InputStream is = null; + try { + is = new BufferedInputStream(connection.getInputStream()); + BufferedReader br = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8"))); + String inputLine = ""; + while ((inputLine = br.readLine()) != null) { + sb.append(inputLine); + } + result = sb.toString(); + } catch (Exception e) { + LOG.debug("read connection failed... " + connection.getURL(), e); + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + LOG.debug("close connection failed... " + connection.getURL(), e); + } + } + } + return result; + } +} diff --git a/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/util/IpUtilTest.java b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/util/IpUtilTest.java new file mode 100644 index 0000000..daeb717 --- /dev/null +++ b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/util/IpUtilTest.java @@ -0,0 +1,138 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.util; + +import com.meituan.octo.mns.model.IDC; +import com.octo.idc.model.Idc; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + + +public class IpUtilTest { + private static final String rootPath = IpUtilTest.class.getResource("/").getFile().toString(); + private static String UNKNOWN = "unknown"; + private static String SHANGHAI = "shanghai"; + private static String BEIJING = "beijing"; + private static String YF = "YF"; + private static String DX = "DX"; + private static String GQ = "GQ"; + + private static String BJ1 = "BJ1"; + private static String BJ2 = "BJ2"; + private static String SH = "SH"; + + private class CheckInfo { + String ip; + String region; + String idc; + String center; + + public CheckInfo(String ip, String region, String idc, String center) { + this.ip = ip; + this.region = region; + this.idc = idc; + this.center = center; + } + } + + private static List infoList = new ArrayList(); + private static List ips = new ArrayList(); + + @Before + public void initBeforeClass() { + + infoList.clear(); + ips.clear(); + infoList.add(new CheckInfo("10.4.245.3", BEIJING, YF, BJ2)); + infoList.add(new CheckInfo("10.32.245.34", BEIJING, DX, BJ1)); + infoList.add(new CheckInfo("10.4.2433333333.121", UNKNOWN, UNKNOWN, UNKNOWN)); + + infoList.add(new CheckInfo("10.4.2s.121", UNKNOWN, UNKNOWN, UNKNOWN)); + infoList.add(new CheckInfo("10.69.23.43", SHANGHAI, GQ, SH)); + + infoList.add(new CheckInfo(null, UNKNOWN, UNKNOWN, UNKNOWN)); + infoList.add(new CheckInfo("", UNKNOWN, UNKNOWN, UNKNOWN)); + + for (CheckInfo item : infoList) { + ips.add(item.ip); + } + } + + + @Test + public void testGetIdcInfoFromLocal() throws Exception{ + List idcTemp = new ArrayList(); + new DefaultIdcParser().initIdcXml(ProcessInfoUtil.getIdcPath(), idcTemp); + + Map idcs = IpUtil.getIdcInfoFromLocal(ips); + check(idcs, true); + + + ExecutorService executor = Executors.newFixedThreadPool(10); + for (int i = 0; i < 10; i++) { + executor.submit(new Runnable() { + @Override + public void run() { + List allIdcs = IpUtil.getAllIdcs(); + Assert.assertTrue(allIdcs != null && !allIdcs.isEmpty()); + } + }); + } + + Thread.sleep(10000); + } + + @Test + public void testCheckAndloadIdcXmlIfNecessary() { + Assert.assertTrue(IpUtil.checkAndloadIdcXmlIfNecessary()); + } + + @Test + public void testCheckIP() { + Assert.assertFalse(IpUtil.checkIP("100.2.2.1q")); + Assert.assertFalse(IpUtil.checkIP("257.2.2.10")); + Assert.assertFalse(IpUtil.checkIP("1-1.2.2.1")); + Assert.assertFalse(IpUtil.checkIP("100.2.2")); + Assert.assertTrue(IpUtil.checkIP("100.2.2.1")); + } + + private void check(Map map, boolean isCheckCenter) { + for (CheckInfo item : infoList) { + Idc idc = map.get(item.ip); + if (null == item.ip || null == idc) { + continue; + } + Assert.assertEquals(item.region, idc.getRegion()); + if (isCheckCenter) { + Assert.assertEquals(item.center, idc.getCenter()); + } + Assert.assertEquals(item.idc, idc.getIdc()); + } + + } +} diff --git a/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/util/ProcessConfigTests.java b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/util/ProcessConfigTests.java new file mode 100644 index 0000000..1a5f057 --- /dev/null +++ b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/util/ProcessConfigTests.java @@ -0,0 +1,72 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.util; + +import com.meituan.octo.mns.Consts; +import com.meituan.octo.mns.model.HostEnv; +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.util.Properties; + +import static com.meituan.octo.mns.util.ProcessConfig.VALUE_MAP_HOST_ENV; + + +public class ProcessConfigTests { + @Test + public void isFileExist() { + InputStream in = null; + try { + in = new FileInputStream(Consts.CONFIG_FILE); + Assert.assertTrue(ProcessConfig.isConfigIsExist()); + } catch (FileNotFoundException e) { + Assert.assertFalse(ProcessConfig.isConfigIsExist()); + } finally { + if (in != null) { + try { + in.close(); + } catch (Exception e) { + } + } + } + } + + @Test + public void checkEnv() { + Properties config = ProcessConfig.getConfig(); + Assert.assertNotNull(config); + + HostEnv hostEnv = ProcessConfig.getHostEnv(); + Assert.assertTrue(hostEnv.equals(HostEnv.DEV) || hostEnv.equals(HostEnv.PPE) || hostEnv.equals(HostEnv.TEST) + || hostEnv.equals(HostEnv.PROD) || hostEnv.equals(HostEnv.STAGE)); + + if (!StringUtils.isEmpty(config.getProperty(Consts.ENV_KEY))) { + Assert.assertTrue(VALUE_MAP_HOST_ENV.get(config.getProperty(Consts.ENV_KEY)) == ProcessConfig.getHostEnv()); + + } else { + Assert.assertTrue(ProcessConfig.getHostEnv() == HostEnv.DEV); + } + } +} diff --git a/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/util/ProcessInfoUtilTests.java b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/util/ProcessInfoUtilTests.java new file mode 100644 index 0000000..723b620 --- /dev/null +++ b/sdk/mns-invoker/src/test/java/com/meituan/octo/mns/util/ProcessInfoUtilTests.java @@ -0,0 +1,212 @@ +/* +* Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ +package com.meituan.octo.mns.util; + +import com.meituan.octo.mns.exception.MnsException; +import com.octo.idc.model.Idc; +import org.junit.Assert; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static org.junit.Assert.*; + +public class ProcessInfoUtilTests { + private static Logger LOG = LoggerFactory.getLogger(ProcessInfoUtilTests.class); + + @Test + public void getIdcs() { + + List idcs = ProcessInfoUtil.getIdcs(); + Assert.assertTrue(!idcs.isEmpty()); + List idcChecks = new ArrayList(); + + idcChecks.add(new IDCCheck("DX", "BJ1", "beijing", false)); + idcChecks.add(new IDCCheck("YF", "BJ2", "beijing", false)); + idcChecks.add(new IDCCheck("CQ", "BJ1", "beijing", false)); + idcChecks.add(new IDCCheck("GQ", "SH", "shanghai", false)); + idcChecks.add(new IDCCheck("GH", "BJ1", "beijing", false)); + + if (!idcs.isEmpty()) { + for (Idc idc : idcs) { + for (IDCCheck check : idcChecks) { + if (check.getIdcName().equalsIgnoreCase(idc.getIdc()) + && check.getCenter().equalsIgnoreCase(idc.getCenter()) + && check.getRegion().equalsIgnoreCase(idc.getRegion())) { + check.setExist(true); + } + } + } + for (IDCCheck check : idcChecks) { + Assert.assertTrue(check.isExist()); + } + } + + + // re-check + idcs = ProcessInfoUtil.getIdcs(); + Assert.assertTrue(!idcs.isEmpty()); + + } + + @Test + public void getIp() { + Assert.assertTrue(IpUtil.checkIP(ProcessInfoUtil.getLocalIpv4())); + } + + @Test + public void getHostInfo() { + String ip = ProcessInfoUtil.getLocalIpv4(); // 获取本地内网 IP + boolean isLocalOnline = ProcessInfoUtil.isLocalHostOnline(); //无需参数, 直接判断本机是否 Online + } + + + @Test + public void testIdcInfoYF() throws IOException { + List ips = new ArrayList(); + String IP = "10.4.243.121"; + ips.add(IP); + try { + Map idcs = ProcessInfoUtil.getIdcInfo(ips); + assertEquals(1, idcs.size()); + Idc idc = idcs.get(IP); + assertEquals("YF", idc.idc); + assertEquals("beijing", idc.region); + } catch (MnsException e) { + e.printStackTrace(); + } + } + + + @Test + public void testIdcInfoGQ() throws IOException { + List ips = new ArrayList(); + String IP = "10.67.243.121"; + ips.add(IP); + ips.add(IP); + try { + Map idcs = ProcessInfoUtil.getIdcInfo(ips); + assertEquals(1, idcs.size()); + Idc idc = idcs.get(IP); + assertEquals("GQ", idc.idc); + assertEquals("shanghai", idc.region); + } catch (MnsException e) { + e.printStackTrace(); + } + + } + + @Test + public void testIdcInfoUnkown() throws IOException { + String IP = "10.44132.243.1212312"; + List ips = new ArrayList(); + ips.add(IP); + try { + Map idcs = ProcessInfoUtil.getIdcInfo(ips); + assertEquals(1, idcs.size()); + } catch (MnsException e) { + e.printStackTrace(); + } + } + + + @Test + public void testIP() { + assertTrue(IpUtil.checkIP("10.4.245.3")); + assertFalse(IpUtil.checkIP("0.4.245.3")); + assertFalse(IpUtil.checkIP(".4.245.3")); + assertFalse(IpUtil.checkIP("10.4.245.")); + assertFalse(IpUtil.checkIP("10.4.2453")); + assertFalse(IpUtil.checkIP("10.4.s.1")); + assertFalse(IpUtil.checkIP("10.4.4,1")); + assertFalse(IpUtil.checkIP("10.4.245.2223")); + assertFalse(IpUtil.checkIP(null)); + assertFalse(IpUtil.checkIP("")); + System.out.println("IpUtil.checkIP pass."); + } + + @Test + public void testOctoCfg() throws IOException { + System.out.println(ProcessInfoUtil.getIdcPath()); + System.out.println(ProcessInfoUtil.getSgagentPort()); + System.out.println(ProcessInfoUtil.getSgagentAppkey()); + System.out.println(ProcessInfoUtil.getSgsentinelAppkey()); + System.out.println(ProcessInfoUtil.getMnsUrl()); + System.out.println(ProcessInfoUtil.getMnsZKUrl()); + System.out.println(ProcessInfoUtil.getAppEnv()); + /*assertEquals(ProcessInfoUtil.getIdcPath(), "/octo/namingservice/chrion/idc.xml"); + assertEquals(ProcessInfoUtil.getSgagentPort(), 5266); + assertEquals(ProcessInfoUtil.getSgagentAppkey(), "com.sankuai.inf.sgagent"); + assertEquals(ProcessInfoUtil.getSgsentinelAppkey(), "com.sankuai.inf.sg_sentinel");*/ + } + + static class IDCCheck { + private String idcName; + private String center; + private String region; + private boolean exist; + + + public IDCCheck(String idcName, String center, String region, boolean exist) { + this.idcName = idcName; + this.center = center; + this.region = region; + this.exist = exist; + } + + public String getIdcName() { + return idcName; + } + + public void setIdcName(String idcName) { + this.idcName = idcName; + } + + public boolean isExist() { + return exist; + } + + public void setExist(boolean exist) { + this.exist = exist; + } + + public String getCenter() { + return center; + } + + public void setCenter(String center) { + this.center = center; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + } +} diff --git a/sdk/mns-invoker/src/test/resources/log4j2.xml b/sdk/mns-invoker/src/test/resources/log4j2.xml new file mode 100644 index 0000000..8dc7237 --- /dev/null +++ b/sdk/mns-invoker/src/test/resources/log4j2.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sdk/mns-sdk/CMakeLists.txt b/sdk/mns-sdk/CMakeLists.txt new file mode 100644 index 0000000..c946fb8 --- /dev/null +++ b/sdk/mns-sdk/CMakeLists.txt @@ -0,0 +1,139 @@ +cmake_minimum_required(VERSION 2.6) + +project(mns_sdk C CXX) + +IF (ENABLE_COVERAGE) + SET(CMAKE_CXX_FLAGS "-g -Wall -O0 -fPIC -DMUDUO_STD_STRING -DHAVE_NETINET_IN_H") +ELSE () + SET(CMAKE_CXX_FLAGS "-g -Wall -O2 -fPIC -DMUDUO_STD_STRING -DHAVE_NETINET_IN_H") +ENDIF () + +MESSAGE(STATUS "CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}") + +SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") +MESSAGE(STATUS "CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}") + +if (CMAKE_BUILD_INIT) + FIND_PACKAGE(Muduo REQUIRED) +else() + find_package(Boost REQUIRED) + find_package(ZLIB REQUIRED) + find_path(LOG4CPLUS_INCLUDE_DIR log4cplus) + find_library(LOG4CPLUS_LIBRARY NAMES log4cplus) + find_program(THRIFT_COMPILER thrift) + find_path(THRIFT_INCLUDE_DIR thrift/Thrift.h) + find_library(THRIFT_LIBRARY NAMES thrift) + find_library(MUDUO_BASE_LIBRARY libmuduo_base.a) + find_library(MUDUO_NET_LIBRARY libmuduo_net.a) + find_library(MUDUO_HTTP_LIBRARY libmuduo_http.a) + find_path(MUDUO_INCLUDE_DIR muduo) + + if(ZLIB_FOUND) + MESSAGE(STATUS "found zlib ${ZLIB_FOUND}") + else() + MESSAGE(STATUS "no found zlib") + SET(SOME_NO_FOUND TRUE) + endif() + + if(THRIFT_COMPILER AND THRIFT_INCLUDE_DIR AND THRIFT_LIBRARY) + MESSAGE(STATUS "found thrift") + else() + MESSAGE(STATUS "no found thrift") + SET(SOME_NO_FOUND TRUE) + endif() + + if(MUDUO_BASE_LIBRARY AND MUDUO_HTTP_LIBRARY AND MUDUO_NET_LIBRARY AND MUDUO_INCLUDE_DIR) + MESSAGE(STATUS "found muduo") + else() + MESSAGE(STATUS "no found muduo") + SET(SOME_NO_FOUND TRUE) + endif() + + if(LOG4CPLUS_INCLUDE_DIR AND LOG4CPLUS_LIBRARY) + MESSAGE(STATUS "found log4cplus") + else() + MESSAGE(STATUS "no found log4cplus") + SET(SOME_NO_FOUND TRUE) + endif() + + if(Boost_INCLUDE_DIRS) + MESSAGE(STATUS "found boost") + else() + MESSAGE(STATUS "no found boost") + SET(SOME_NO_FOUND TRUE) + endif() + + if(SOME_NO_FOUND) + MESSAGE(FATAL_ERROR "Dependency not found please confirm") + endif() + + MESSAGE(STATUS "THRIFT_COMPILER ${THRIFT_COMPILER}") + MESSAGE(STATUS "THRIFT_INCLUDE_DIR ${THRIFT_INCLUDE_DIR}") + MESSAGE(STATUS "LOG4CPLUS_INCLUDE_DIR ${LOG4CPLUS_INCLUDE_DIR}") + MESSAGE(STATUS "ZLIB_INCLUDE_DIR ${ZLIB_INCLUDE_DIR}") + MESSAGE(STATUS "Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIRS}") + MESSAGE(STATUS "ZLIB_LIBRARY ${ZLIB_LIBRARY}") + MESSAGE(STATUS "THRIFT_LIBRARY ${THRIFT_LIBRARY}") + MESSAGE(STATUS "LOG4CPLUS_LIBRARY ${LOG4CPLUS_LIBRARY}") + MESSAGE(STATUS "Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIRS}") + MESSAGE(STATUS "MUDUO_BASE_LIBRARY ${MUDUO_BASE_LIBRARY}") + MESSAGE(STATUS "MUDUO_NET_LIBRARY ${MUDUO_NET_LIBRARY}") + MESSAGE(STATUS "MUDUO_HTTP_LIBRARY ${MUDUO_HTTP_LIBRARY}") + + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) + INCLUDE_DIRECTORIES(${THRIFT_INCLUDE_DIR}) + INCLUDE_DIRECTORIES(${THRIFT_INCLUDE_DIR}/thrift) + INCLUDE_DIRECTORIES(${LOG4CPLUS_INCLUDE_DIR}) + INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR}) + INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}) + INCLUDE_DIRECTORIES(${MUDUO_INCLUDE_DIR}) + + SET(MNS_SRC_PATH ${CMAKE_SOURCE_DIR}) + MESSAGE(STATUS "MNS_SRC_PATH ${MNS_SRC_PATH}") + + #for output + EXECUTE_PROCESS(COMMAND mkdir ${CMAKE_SOURCE_DIR}/build) + SET(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/build) + MESSAGE(STATUS "CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}") + + EXECUTE_PROCESS(COMMAND mkdir ${CMAKE_INSTALL_PREFIX}/include) + SET(INCLUDE_OUTPUT_PATH ${CMAKE_INSTALL_PREFIX}/include) + MESSAGE(STATUS "INCLUDE_OUTPUT_PATH ${INCLUDE_OUTPUT_PATH}") + + EXECUTE_PROCESS(COMMAND mkdir ${CMAKE_INSTALL_PREFIX}/lib) + SET(LIBRARY_OUTPUT_PATH ${CMAKE_INSTALL_PREFIX}/lib) + MESSAGE(STATUS "LIBRARY_OUTPUT_PATH ${LIBRARY_OUTPUT_PATH}") + + EXECUTE_PROCESS(COMMAND mkdir ${CMAKE_INSTALL_PREFIX}/bin) + SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_INSTALL_PREFIX}/bin) + MESSAGE(STATUS "EXECUTABLE_OUTPUT_PATH ${EXECUTABLE_OUTPUT_PATH}") + + EXECUTE_PROCESS(COMMAND mkdir ${INCLUDE_OUTPUT_PATH}/mns_sdk) + SET(INCLUDE_MNS_OUTPUT_PATH ${INCLUDE_OUTPUT_PATH}/mns_sdk) + MESSAGE(STATUS "INCLUDE_MNS_OUTPUT_PATH ${INCLUDE_MNS_OUTPUT_PATH}") + + EXECUTE_PROCESS(COMMAND mkdir ${INCLUDE_OUTPUT_PATH}/mns_sdk/util) + SET(INCLUDE_MNS_UTIL_OUTPUT_PATH ${INCLUDE_OUTPUT_PATH}/mns_sdk/util) + MESSAGE(STATUS "INCLUDE_MNS_UTIL_OUTPUT_PATH ${INCLUDE_MNS_UTIL_OUTPUT_PATH}") + + + SET(OCTO_IDL_PATH ${CMAKE_SOURCE_DIR}/../../common/idl-mns) + MESSAGE(STATUS "OCTO_IDL_PATH ${OCTO_IDL_PATH}") + + SET(INCLUDE_OCTOIDL_OUTPUT_PATH ${INCLUDE_OUTPUT_PATH}/octoidl) + MESSAGE(STATUS "INCLUDE_OCTOIDL_OUTPUT_PATH ${INCLUDE_OCTOIDL_OUTPUT_PATH}") + EXECUTE_PROCESS(COMMAND mkdir ${INCLUDE_OCTOIDL_OUTPUT_PATH}) + + INCLUDE_DIRECTORIES(SYSTEM /usr/include/) + INCLUDE_DIRECTORIES(SYSTEM ${INCLUDE_OUTPUT_PATH}) + + ADD_SUBDIRECTORY(thrid/octoidl) + ADD_SUBDIRECTORY(src) + + if (NOT CMAKE_BUILD_NO_EXAMPLES) + ADD_SUBDIRECTORY(example) + endif () +endif() + + + diff --git a/sdk/mns-sdk/ReadMe.md b/sdk/mns-sdk/ReadMe.md new file mode 100644 index 0000000..14cd4e7 --- /dev/null +++ b/sdk/mns-sdk/ReadMe.md @@ -0,0 +1,136 @@ +# 构建 + +mns-sdk 以静态链接方式编译 + +mns-sdk 依赖下列组件: + +* [muduo](https://github.com/chenshuo/muduo): 网络工具库 +* [boost](https://github.com/boostorg/boost): 基础的C++工具库 +* [zlib](https://github.com/madler/zlib): 压缩工具库 +* [thrift](https://github.com/apache/thrift): rpc通讯框架 +* [log4cplus](https://github.com/log4cplus/log4cplus): 日志库 +* [rapidjson](https://github.com/Tencent/rapidjson): json解析库 + +# 依赖支持 + +| 库依赖 | 版本 | 备注 | +| ------ | ------ | ------ | +| muduo | 1.1.0 | 有http服务补丁,见 patch/0001-add-patch-for-http.patch | +| boost | 1.45 和 1.55 | 建议centos6 使用1.45,建议centos7 使用1.55 | +| zlib | 1.2.3 | | +| thrift | 0.8.0 | | +| log4cplus | 1.1.3 | | +| rapidjson | 1.1.0 | | + +# 支持环境 + +* [CentOS6 和 CentOS7](https://www.centos.org/) + +### 准备依赖 + + +CentOS通常需要安装EPEL,否则许多软件包默认不可用: + +```shell +> sudo yum install epel-release +``` + +安装通用依赖库: + +```shell +> sudo yum install git gcc-c++ cmake +``` + +安装 [boost](https://github.com/boostorg/boost), [zlib](https://github.com/madler/zlib), [log4cplus](https://github.com/log4cplus/log4cplus),[rapidjson](https://github.com/Tencent/rapidjson): + +```shell +> sudo yum install boost-devel zlib-devel log4cplus-devel rapidjson-devel +``` + +安装[thrift](https://github.com/apache/thrift): + +```shell +thrift一般很少有yum源,请自行参照官方使用文档安装 +``` + +安装 [octo-mns](): +[参照octo-mns文档安装环境](./../../docs/ns-quick-start.md) + + +### 使用 build.sh 编译 mns-sdk +```bash +> git clone https://github.com/Meituan-Dianping/octo-ns.git +``` + +**使用 build.sh 初始化** + +```bash +> cd octo-ns/sdk/mns-sdk +> build.sh init +``` + +**使用 build.sh 编译mns-sdk** + +```bash +> cd octo-ns/sdk/mns-sdk +> build.sh only_lib +``` + +**使用 build.sh Run example** + +```bash +> cd octo-ns/sdk/mns-sdk +> build.sh with_example +> cd build/bin/ +> ./mns_sdk_example +``` + +**验证结果** +注册成功标志,客户端输出 + +```bash +> =========registService success========= +``` + +注册失败成功标志,客户端输出 + +```bash +> =========registService failed========= +``` + + +发起获取列表成功标志,客户端输出 + +```bash +> =========start client success========= +``` + +发起获取列表失败标志,客户端输出 + +```bash +> =========start client failed========= +``` + +添加列表监听成功标志,客户端输出 + +```bash +> =========AddUpdateSvrListCallback success========= +``` + +添加列表监听失败标志,客户端输出 + +```bash +> =========AddUpdateSvrListCallback failed========= +``` + +列表回调标志,客户端输出 + +```bash +> =========GetServerList success========= +``` + + +### [详细API](docs/mns_sdk_api.md) + + + diff --git a/sdk/mns-sdk/build.sh b/sdk/mns-sdk/build.sh new file mode 100644 index 0000000..f2eebfc --- /dev/null +++ b/sdk/mns-sdk/build.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +set -x + +if [ $# -ne 1 ] || [ "$1" != "only_lib" -a "$1" != "with_example" -a "$1" != "with_test" -a "$1" != "clean" -a "$1" != "init" ] +then +echo "build.sh + , no argument means all" +exit +fi + +BUILD_NO_EXAMPLES=${BUILD_NO_EXAMPLES:-0} +BUILD_NO_TESTS=${BUILD_NO_TESTS:-0} + +SOURCE_DIR=`pwd` +CPU_CORE_NUM=`cat /proc/cpuinfo | grep processor | wc -l` + + + if [ "$1" == "clean" ] + then + cd tool + sh -x clear4git.sh + cd - + exit + fi + + BUILD_NO_EXAMPLES=1 + BUILD_NO_TESTS=1 + + if [ "$1" == "with_example" ] + then + BUILD_NO_EXAMPLES=0 + elif [ "$1" == "with_test" ] + then + BUILD_NO_TESTS=0 + elif [ "$1" == "init" ] + then + cmake -DCMAKE_BUILD_INIT=1 $SOURCE_DIR && make -j"$CPU_CORE_NUM" + cd tool + sh -x clear4git.sh + cd - + exit + fi + + + cmake \ + -DCMAKE_BUILD_NO_EXAMPLES=$BUILD_NO_EXAMPLES \ + -DCMAKE_BUILD_NO_TESTS=$BUILD_NO_TESTS \ + $SOURCE_DIR \ + && make -j"$CPU_CORE_NUM" + diff --git a/sdk/mns-sdk/cmake/CMakeLists.download_gtest.in b/sdk/mns-sdk/cmake/CMakeLists.download_gtest.in new file mode 100644 index 0000000..1004869 --- /dev/null +++ b/sdk/mns-sdk/cmake/CMakeLists.download_gtest.in @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.8.10) + +project(googletest-download NONE) + +include(ExternalProject) +ExternalProject_Add(googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.8.0 + SOURCE_DIR "${PROJECT_BINARY_DIR}/googletest-src" + BINARY_DIR "${PROJECT_BINARY_DIR}/googletest-build" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" +) \ No newline at end of file diff --git a/sdk/mns-sdk/cmake/DonwloadMuduo.cmake b/sdk/mns-sdk/cmake/DonwloadMuduo.cmake new file mode 100644 index 0000000..371af81 --- /dev/null +++ b/sdk/mns-sdk/cmake/DonwloadMuduo.cmake @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 2.8.10) + +project(muduo-download NONE) + +include(ExternalProject) +ExternalProject_Add(muduo + GIT_REPOSITORY https://github.com/chenshuo/muduo.git + GIT_TAG v1.1.0 + SOURCE_DIR "${PROJECT_BINARY_DIR}/muduo" + PATCH_COMMAND patch -p1 < ${CMAKE_SOURCE_DIR}/patch/0001-add-patch-for-http.patch + CMAKE_COMMAND cmake + CMAKE_ARGS "-DCMAKE_BUILD_NO_EXAMPLES=1 -DCMAKE_CXX_FLAGS=-fPIC" + ) diff --git a/sdk/mns-sdk/cmake/FindGtest.cmake b/sdk/mns-sdk/cmake/FindGtest.cmake new file mode 100644 index 0000000..f7a2500 --- /dev/null +++ b/sdk/mns-sdk/cmake/FindGtest.cmake @@ -0,0 +1,31 @@ +# FindGtest +# -------- +# +# Find gtest +# +# Find the gtest includes and library. Once done this will define +# +# GTEST_INCLUDE_DIR - where to find gtest include, etc. +# GTEST_LIBRARY - List of libraries when using gtest_base. +# GTEST_FOUND - True if gtest found. +# +set(GTEST_INCLUDE_DIR ${COMMON_LIB_PATH}/googletest/googletest/include) +set(GTEST_LIBRARY ${COMMON_LIB_PATH}/googletest/googlemock/gtest/libgtest.a ${COMMON_LIB_PATH}/googletest/googlemock/gtest/libgtest_main.a) +set(GTEST_MOCK_LIBRARY ${COMMON_LIB_PATH}/googletest/googlemock/libmock.a ${COMMON_LIB_PATH}/googletest/googlemock/gtest/libmock_main.a) + +#message(${GTEST_INCLUDE_DIR}) +find_path(GTEST_INCLUDE_DIR NAMES gtest) + +mark_as_advanced(GTEST_LIBRARY GTEST_MOCK_LIBRARY GTEST_INCLUDE_DIR) + +# handle the QUIETLY and REQUIRED arguments and set GTEST_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Gtest REQUIRED_VARS GTEST_LIBRARY GTEST_MOCK_LIBRARY GTEST_INCLUDE_DIR) + +if (GTEST_FOUND) + set(GTEST_INCLUDE_DIR ${GTEST_INCLUDE_DIR}) + set(GTEST_LIBRARY ${GTEST_LIBRARY}) + set(GTEST_MOCK_LIBRARY ${GTEST_MOCK_LIBRARY}) +endif () + diff --git a/sdk/mns-sdk/cmake/FindMuduo.cmake b/sdk/mns-sdk/cmake/FindMuduo.cmake new file mode 100644 index 0000000..4b6054f --- /dev/null +++ b/sdk/mns-sdk/cmake/FindMuduo.cmake @@ -0,0 +1,37 @@ +# FindMuduo +# -------- +# +# Find Muduo +# +# Find the Muduo includes and library. Once done this will define +# +# MUDUO_INCLUDE_DIR - where to find gtest include, etc. +# MUDUO_LIBRARY - List of libraries when using muduo_base. +# MUDUO_FOUND - True if muduo found. +# + + + +set(MUDUO_INCLUDE_DIR_S /usr/local/include) +set(MUDUO_LIBRARY_S /usr/local/lib/) + +find_path(MUDUO_INCLUDE_DIR NAMES muduo PATHS ${MUDUO_INCLUDE_DIR_S}) +find_library(MUDUO_LIBRARY NAMES libmuduo_base.a PATHS ${MUDUO_LIBRARY_S}) + +mark_as_advanced(MUDUO_LIBRARY MUDUO_INCLUDE_DIR) + +# handle the QUIETLY and REQUIRED arguments and set MUDUO_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(MUDUO REQUIRED_VARS MUDUO_LIBRARY MUDUO_INCLUDE_DIR) + +MESSAGE("MUDUO_INCLUDE_DIR ${MUDUO_INCLUDE_DIR}") +MESSAGE("MUDUO_LIBRARY ${MUDUO_LIBRARY}") + +if(MUDUO_FOUND) + set(MUDUO_INCLUDE_DIR ${MUDUO_INCLUDE_DIR}) + set(MUDUO_LIBRARY ${MUDUO_LIBRARY}) +else() + MESSAGE("MUDUO_FOUND NO FOUND Download and compile") + include(DonwloadMuduo) +endif() \ No newline at end of file diff --git a/sdk/mns-sdk/cmake/SetupGtest.cmake b/sdk/mns-sdk/cmake/SetupGtest.cmake new file mode 100644 index 0000000..86c97f4 --- /dev/null +++ b/sdk/mns-sdk/cmake/SetupGtest.cmake @@ -0,0 +1,24 @@ +# Setup googletest +configure_file("${PROJECT_SOURCE_DIR}/cmake/CMakeLists.download_gtest.in" ${PROJECT_BINARY_DIR}/googletest-download/CMakeLists.txt) + +execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/googletest-download + ) +if (result) + message(FATAL_ERROR "CMake step for googletest failed: ${result}") +endif () + +execute_process(COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/googletest-download + ) +if (result) + message(FATAL_ERROR "Build step for googletest failed: ${result}") +endif () + +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +add_subdirectory(${PROJECT_BINARY_DIR}/googletest-src + ${PROJECT_BINARY_DIR}/googletest-build + EXCLUDE_FROM_ALL) \ No newline at end of file diff --git a/sdk/mns-sdk/docs/mns_sdk_api.md b/sdk/mns-sdk/docs/mns_sdk_api.md new file mode 100644 index 0000000..db1a644 --- /dev/null +++ b/sdk/mns-sdk/docs/mns_sdk_api.md @@ -0,0 +1,221 @@ +# 1 概述说明 +mns-sdk是octo-ns的c++侧轻量级sdk,提供服务注册与注销,服务发现,基础工具类等功能。 +# 2 服务注册和发现 +## 2.1 初始化 +进行sdk的初始化。 + +``` +/* +* param mns_path 使用mns做服务注册发现时的配置路径 +* param sec 内部缓存更新时间间隔 +* param timeout 内部获取列表的超时时间 +* ret 返回值 成功返回0 不成功返回-1 +*/ +int InitMNS(const std::string &mns_path, const double &sec, + const double &timeout = 0.5);//初始化mns_sdk客户端,mns_path 环境配置文件, +``` +## 2.2 服务注册 +### 描述 +用于注册thrift 或 http协议的服务节点。 + +``` +/* +* param str_appkey 要注册的app名称 +* param i16_port 要注册的端口号 +* param i32_svr_type 服务类型 0:thrift, 1:http, 2:other +* param str_proto_type 协议类型 默认时“thrift” +* ret 返回值 成功返回0 不成功返回-1 +*/ +int8_t StartSvr(const std::string &str_appkey, + const int16_t &i16_port, + const int32_t &i32_svr_type, + const std::string &str_proto_type = "thrift"); + +/* +* param str_appkey 要注册的app名称 +* param service_name_list 要注册的服务服务,用途为单端口多服务 +* param i16_port 要注册的端口号 +* param i32_svr_type 服务类型 0:thrift, 1:http, 2:other +* param str_proto_type 协议类型 默认时“thrift” +* param b_is_uniform 是否是octo统一协议默认是false +* ret 返回值 成功返回0 不成功返回-1 +*/ +int8_t StartSvr(const std::string &str_appkey, + const std::vector &service_name_list, + const int16_t &i16_port, + const int32_t &i32_svr_type, + const std::string &str_proto_type, + const bool &b_is_uniform = false); + +``` + +### 请求示例 +注册一个appkey名称为"com.test.appkey",端口号是16888,server type是0(thrift),协议类型为thrift。 + +``` + const std::string appkey = "com.test.appkey"; + const int16_t port = 16888; + cosnt int32_t i32_svr_type = 0; + const std::string str_proto_type = "thrift"; + int ret = StartSvr(appkey, port, i32_svr_type, str_proto_type))) ; + if (ret != 0){ + printf("start failed"); + }else{ + printf("start success"); + } +``` + +## 2.3 服务发现 +### 描述 +返回服务列表,存入用户传入的res_svr_list中。 + +``` +/* +* param str_svr_appkey 要获取的app名称 +* param str_cli_appkey 本地的app名称 +* param str_proto_type 要获取的协议类型 +* param i32_svr_type 服务类型 0:thrift, 1:http, 2:other +* param str_service_name 按照服务名进行过滤 +* param out p_svr_list 返回的服务列表 +* ret 返回值 成功返回0 不成功返回-1 +*/ + +int8_t getSvrList(const std::string &str_svr_appkey, + const std::string &str_cli_appkey, + const std::string &str_proto_type, + const std::string &str_service_name, + std::vector *p_svr_list); +``` + + +## 2.4 服务列表监听 +### 描述 +为自定义协议的请求添加或删除监听器,监听器的作用是当服务列表发生变化时产生回调。 +获取所有类型服务节点,推荐,支持在一条业务线程中多次绑定不同的appkey。 + +~~~ +/* +* param str_svr_appkey 要获取的app名称 +* param str_cli_appkey 本地的app名称 +* param str_proto_type 要获取的协议类型 +* param i32_svr_type 服务类型 0:thrift, 1:http, 2:other +* param str_service_name IDL文件中的service名字,可按这个名字来过滤服务节点,可填空串返回全部服务节点 + +* param cb 回调函数,当有数据更新时通知的函数,全量更新 +* ret 返回值 成功返回0 不成功返回-1 +*/ +int8_t StartClient(const std::string &str_svr_appkey, + const std::string &str_cli_appkey, + const std::string &str_proto_type, + const std::string &str_service_name, + const SvrListCallback &cb); + +/* +* param str_svr_appkey 要获取的app名称 +* param str_cli_appkey 本地的app名称 +* param str_proto_type 要获取的协议类型 +* param i32_svr_type 服务类型 0:thrift, 1:http, 2:other +* param str_service_name IDL文件中的service名字,可按这个名字来过滤服务节点,可填空串返回全部服务节点 + +* param cb 回调函数,当有数据更新时通知的函数,与上函数不同的是这个回调区分更新的类型 +* ret 返回值 成功返回0 不成功返回-1 +*/ +int8_t StartClient(const std::string &str_svr_appkey, + const std::string &str_cli_appkey, + const std::string &str_proto_type, + const std::string &str_service_name, + const UpdateSvrListCallback &cb); +~~~ + +添加对appkey的回调通知,可以支持多个通知对象,实现观察者模式。 + +~~~ +/* +* param str_svr_appkey 要获取的app名称 +* param cb 接收回调函数,全量更新 +* ret 返回值 成功返回0 不成功返回-1 +*/ +int8_t AddSvrListCallback(const std::string &str_svr_appkey, + const SvrListCallback &cb, + std::string *p_err_info); + +/* +* param str_svr_appkey 要获取的app名称 +* param cb 接收回调函数,与上不同的是分类更新 +* ret 返回值 成功返回0 不成功返回-1 +*/ +int8_t AddUpdateSvrListCallback(const std::string &str_svr_appkey, + const UpdateSvrListCallback &cb, + std::string *p_err_info); +~~~ +### 请求示例 +注册一个appkey名称为"com.test.appkey",端口号是16888,server type是0(thrift),协议类型为thrift。 + +``` + void JobList(const vector &vec_add, + const vector &vec_del, + const vector &vec_chg, + const string &appkey) { + cout << "AddUpdateSvrListCallback appkey " << appkey << endl; +} + + + boost::function &vec_add, + const vector &vec_del, + const vector &vec_chg, + const string &appkey)> job1(boost::bind(&JobList, _1, _2, _3, _4)); + string err_info = ""; + if (MNS_UNLIKELY(AddUpdateSvrListCallback("com.sankuai.inf.newct", + job1, + &err_info))) { + cout << "AddUpdateSvrListCallback failed: " << err_info << endl; + } else { + cout << "start client success" << endl; + } +``` + + +### NOTE + +> - SGService里面的appkey,ip,envir,port,protocol字段一般不会有改变,以下字段的变更会触发modifiedList:status,weight,fweight,version,role,serviceInfo。 +> - mns-sdk对于所有的服务列表监听器只起了一个线程去触发回调callback,因此,强烈建议用户不要在监听器的chaned()方法中做有阻塞的操作,否则会阻塞所有的监听器。 +> - 可以对同一份服务列表添加多个监听器。 + + + +# 3 相关结构体 +## 3.1 SGService +~~~ +struct SGService + +{ + +1:string appkey; //不能为空 + +2:string version; + +3:string ip; //不能为空 + +4:i32 port; //不能为空 + +5:i32 weight; //一般设置为10 + +6:i32 status; //2正常状态,0未启动 + +7:i32 role; //backup角色,当其他服务无法服务的时候,启用backup状态;0(主)1(备) + +8:i32 envir; //运行环境,prod(线上环境3),stag(线上测试环境2),test(测试环境1) + +9:i32 lastUpdateTime; //最后修改时间 + +10:string extend; //扩展 + +11:double fweight; //浮点型权重 一般设置为10.0d + +12:i32 serverType; //用于区分http(1)和thrift(0) + +13:string protocol; //支持tair, sql等其他协议的服务 + +} +~~~ \ No newline at end of file diff --git a/sdk/mns-sdk/example/CMakeLists.txt b/sdk/mns-sdk/example/CMakeLists.txt new file mode 100644 index 0000000..6d9cfe2 --- /dev/null +++ b/sdk/mns-sdk/example/CMakeLists.txt @@ -0,0 +1,13 @@ +INCLUDE_DIRECTORIES(SYSTEM echo) +INCLUDE_DIRECTORIES(SYSTEM ${INCLUDE_OUTPUT_PATH}) +LINK_DIRECTORIES(${LIBRARY_OUTPUT_PATH}) + +LINK_DIRECTORIES(${LIBRARY_OUTPUT_PATH}) + +ADD_EXECUTABLE(mns_sdk_example mns_sdk_example.cc) + +TARGET_LINK_LIBRARIES(mns_sdk_example -Xlinker "-(" libmns_sdk.a + ${MUDUO_BASE_LIBRARY} ${MUDUO_NET_LIBRARY} ${MUDUO_HTTP_LIBRARY} + pthread rt uuid ${ZLIB_LIBRARY} ${LOG4CPLUS_LIBRARY} liboctoidl.a + ${THRIFT_LIBRARY} -Xlinker "-)") + diff --git a/sdk/mns-sdk/example/mns_sdk_example.cc b/sdk/mns-sdk/example/mns_sdk_example.cc new file mode 100644 index 0000000..def6797 --- /dev/null +++ b/sdk/mns-sdk/example/mns_sdk_example.cc @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include + +#include + +using namespace std; +using namespace mns_sdk; + +void Job(const vector &vec_add, + const vector &vec_del, + const vector &vec_chg, + const string &appkey) { + + cout << "=========GetServerList success=========" << endl; + + cout << "recv add.size " << vec_add.size() << endl; + for (int i = 0; i < static_cast(vec_add.size()); i++) { + cout << "[" << i << "]" << ": " + << MnsSdkCommon::SGService2String(vec_add[i]) << endl; + } + + cout << "recv del.size " << vec_del.size() << endl; + for (size_t i = 0; i < vec_del.size(); i++) { + cout << "[" << i << "]" << ": " + << MnsSdkCommon::SGService2String(vec_del[i]) << endl; + } + + cout << "recv chg.size " << vec_chg.size() << endl; + for (size_t i = 0; i < vec_chg.size(); i++) { + cout << "[" << i << "]" << ": " + << MnsSdkCommon::SGService2String(vec_chg[i]) << endl; + } + + cout << "appkey " << appkey << endl; +} + +void JobList(const vector &vec_add, + const vector &vec_del, + const vector &vec_chg, + const string &appkey) { + cout << "AddUpdateSvrListCallback appkey " << appkey << endl; +} + +int main(void) { + + //初始化mns_sdk + log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT("log4cplus.conf")); + + InitMNS("/opt/octo.cfg", 10); + + if (MNS_UNLIKELY(StartSvr("com.sankuai.inf.newct", + 7776, + 0))) { //只是注册了一个ip:port,如果该网络地址未真实存在,将在OCTO管理界面上显示未启动,但注册本身没有问题. + cerr << "=========registService failed=========" << endl; + } else { + cout << "=========registService success=========" << endl; + } + + vector service_list; + service_list.push_back("name1"); + service_list.push_back("name2"); + if (MNS_UNLIKELY(StartSvr("com.sankuai.inf.newct", + service_list, + 17776, + 0, + "thrift"))) { //只是注册了一个ip:port,如果该网络地址未真实存在,将在OCTO管理界面上显示未启动,但注册本身没有问题. + cerr << "=========registService failed=========" << endl; + } else { + cout << "=========registService success=========" << endl; + } + + boost::function &vec_add, + const vector &vec_del, + const vector &vec_chg, + const string &appkey)> job(boost::bind(&Job, _1, _2, _3, _4)); + + if (MNS_UNLIKELY(StartClient("com.sankuai.inf.newct", + "com.sankuai.inf.newct.client", + "thrift", + "", + job))) { + cerr << "=========start client failed=========" << endl; + } else { + cout << "=========start client success=========" << endl; + } + + boost::function &vec_add, + const vector &vec_del, + const vector &vec_chg, + const string &appkey)> job1(boost::bind(&JobList, _1, _2, _3, _4)); + string err_info = ""; + if (MNS_UNLIKELY(AddUpdateSvrListCallback("com.sankuai.inf.newct", + job1, + &err_info))) { + cout << "=========AddUpdateSvrListCallback client failed=========" << err_info << endl; + } else { + cout << "=========AddUpdateSvrListCallback client success=========" << + endl; + } + sleep(120); + + DestroyMNS(); +} diff --git a/sdk/mns-sdk/example/octo.cfg b/sdk/mns-sdk/example/octo.cfg new file mode 100644 index 0000000..0cb6ffe --- /dev/null +++ b/sdk/mns-sdk/example/octo.cfg @@ -0,0 +1,7 @@ +env=test +url=mns.xxx.com +chrion_appkey=com.octo.chrion +sentienl_appkey=com.octo.chrion_sentienl +idc_path=/octo/namingservice/chrion +port=5266 + diff --git a/sdk/mns-sdk/example/octo_bak.cfg b/sdk/mns-sdk/example/octo_bak.cfg new file mode 100644 index 0000000..a657096 --- /dev/null +++ b/sdk/mns-sdk/example/octo_bak.cfg @@ -0,0 +1,7 @@ +env=test +url=mns.sankuai.com +chrion_appkey=com.sankuai.inf.sg_agent +sentienl_appkey=com.sankuai.inf.sg_sentinel +idc_path=/data/webapps/appenv +port=5266 + diff --git a/sdk/mns-sdk/patch/0001-add-patch-for-http.patch b/sdk/mns-sdk/patch/0001-add-patch-for-http.patch new file mode 100644 index 0000000..7206124 --- /dev/null +++ b/sdk/mns-sdk/patch/0001-add-patch-for-http.patch @@ -0,0 +1,97 @@ +From 8a663a187142a030d762f111540bf3e2472ae17b Mon Sep 17 00:00:00 2001 +From: huixiangbo +Date: Sun, 16 Dec 2018 01:35:28 +0800 +Subject: [PATCH] add patch for http + +--- + CMakeLists.txt | 2 +- + muduo/net/http/HttpContext.h | 21 +++++++++++++++++++++ + muduo/net/http/HttpRequest.h | 10 ++++++++++ + 3 files changed, 32 insertions(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index fcb8103..b525072 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -11,7 +11,7 @@ endif() + set(CXX_FLAGS + -g + # -DVALGRIND +- # -DMUDUO_STD_STRING ++ -DMUDUO_STD_STRING + -DCHECK_PTHREAD_RETURN_VALUE + -D_FILE_OFFSET_BITS=64 + -Wall +diff --git a/muduo/net/http/HttpContext.h b/muduo/net/http/HttpContext.h +index b550b7f..861c6bd 100644 +--- a/muduo/net/http/HttpContext.h ++++ b/muduo/net/http/HttpContext.h +@@ -43,9 +43,30 @@ class HttpContext : public muduo::copyable + // return false if any error + bool parseRequest(Buffer* buf, Timestamp receiveTime); + ++ bool expectRequestLine() const ++ { return state_ == kExpectRequestLine; } ++ ++ bool expectHeaders() const ++ { return state_ == kExpectHeaders; } ++ ++ bool expectBody() const ++ { return state_ == kExpectBody; } ++ + bool gotAll() const + { return state_ == kGotAll; } + ++ void receiveRequestLine() ++ { state_ = kExpectHeaders; } ++ ++ void receiveHeaders() ++ { state_ = kExpectBody;} // chaoshu ++ ++ void receiveBody() ++ { state_ = kGotAll; } //chaoshu ++ ++ void receiveAll() ++ { state_ = kGotAll; } //chaoshu, use for ONLY head, NO body ++ + void reset() + { + state_ = kExpectRequestLine; +diff --git a/muduo/net/http/HttpRequest.h b/muduo/net/http/HttpRequest.h +index 7ecad6d..d957ef5 100644 +--- a/muduo/net/http/HttpRequest.h ++++ b/muduo/net/http/HttpRequest.h +@@ -162,6 +162,14 @@ class HttpRequest : public muduo::copyable + const std::map& headers() const + { return headers_; } + ++ void setBody(const char* start, const char* end) //chaoshu ++ { ++ body_.assign(start, end); ++ } ++ ++ const string& body() const //chaoshu ++ { return body_; } ++ + void swap(HttpRequest& that) + { + std::swap(method_, that.method_); +@@ -170,6 +178,7 @@ class HttpRequest : public muduo::copyable + query_.swap(that.query_); + receiveTime_.swap(that.receiveTime_); + headers_.swap(that.headers_); ++ body_.assign(that.body_); //chaoshu + } + + private: +@@ -179,6 +188,7 @@ class HttpRequest : public muduo::copyable + string query_; + Timestamp receiveTime_; + std::map headers_; ++ string body_; //chaoshu + }; + + } +-- +1.7.12.4 + diff --git a/sdk/mns-sdk/src/CMakeLists.txt b/sdk/mns-sdk/src/CMakeLists.txt new file mode 100644 index 0000000..c32a707 --- /dev/null +++ b/sdk/mns-sdk/src/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 2.6) + +SET(MNS_SDK_SRC + mns_sdk.cc + mns_worker.cc + thrift_client.cc + util/mns_sdk_common.cc + util/mns_log.cc + util/mns_config.cc + ) + +ADD_LIBRARY(mns_sdk STATIC ${MNS_SDK_SRC}) +ADD_LIBRARY(mns_sdk_dynamic SHARED ${MNS_SDK_SRC}) + +SET_TARGET_PROPERTIES(mns_sdk_dynamic PROPERTIES OUTPUT_NAME "mns_sdk") + +EXECUTE_PROCESS(COMMAND find ${CMAKE_CURRENT_SOURCE_DIR} -path ${CMAKE_CURRENT_SOURCE_DIR}/util -prune -o -name *.h -exec cp -t ${INCLUDE_MNS_OUTPUT_PATH} {} \;) + +#DO NOT add ' OR " to the path +EXECUTE_PROCESS(COMMAND find ${CMAKE_CURRENT_SOURCE_DIR}/util -name *.h -exec cp -t ${INCLUDE_MNS_UTIL_OUTPUT_PATH} {} \;) + +if (NOT CMAKE_BUILD_NO_TESTS) + ADD_SUBDIRECTORY(test) +endif () diff --git a/sdk/mns-sdk/src/mns_sdk.cc b/sdk/mns-sdk/src/mns_sdk.cc new file mode 100644 index 0000000..f92bce7 --- /dev/null +++ b/sdk/mns-sdk/src/mns_sdk.cc @@ -0,0 +1,755 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include + +#include + +#include "mns_sdk.h" + +using namespace std; +using namespace mns_sdk; + +namespace mns_sdk { + +extern mns_sdk::MnsConfig g_config; + +struct ServiceInfo { + meituan_mns::ProtocolRequest protoreq_; + vector cb_list_; + vector update_cb_list_; + vector sgservice_; + + boost::unordered_map + map_ipport_sgservice_; + + ServiceInfo() { + } + + void SetProtocolReq(const string &str_cli_appkey, + const string &str_svr_appkey, + const string &str_proto_type, + const string &str_service_name) { + protoreq_.__set_localAppkey(str_cli_appkey); + protoreq_.__set_remoteAppkey(str_svr_appkey); + protoreq_.__set_protocol(str_proto_type); + protoreq_.__set_serviceName(str_service_name); + } + + void AddSvrListCallback(const SvrListCallback &cb) { + cb_list_.push_back(cb); + } + + void AddUpdateSvrListCallback(const UpdateSvrListCallback &cb) { + update_cb_list_.push_back(cb); + } +}; + +string g_local_ip_port; + +int ref_count_ = 0; + +muduo::MutexLock init_mutex; +muduo::net::EventLoop *mns_eventloop_p_ = NULL; + +boost::shared_ptr mns_worker_thread_sp_; + +typedef muduo::ThreadLocalSingleton > + ThreadLocalSingletonSGAgentClientSharedPtr; + +typedef muduo::ThreadLocalSingleton > + ThreadLocalSingletonMap; + +void UptSvrList(const string &, ServiceInfo &); +bool FilterService(const meituan_mns::SGService &sg, + const string &service_name); +void GetSvrList(void); +void GetSvrList(const string &str_svr_appkey, + const string &str_cli_appkey, + const string &str_proto_type, + const string &str_service_name, + vector *res_svr_list, + muduo::CountDownLatch *p_countdown); +void DoAddUpdateSvrListCallback(const string &str_svr_appkey, + const UpdateSvrListCallback &cb, + string *p_err_info, + muduo::CountDownLatch *countdown_set_callback); +void DoAddSvrListCallback(const string &str_svr_appkey, + const SvrListCallback &cb, + string *p_err_info, + muduo::CountDownLatch *countdown_set_callback); +void InitCthrift(void); +void InitMap(void); +void InitWorkerWithSvrListCB(const string &str_svr_appkey, + const string &str_cli_appkey, + const string &str_proto_type, + const string &str_service_name, + const SvrListCallback &cb); +void InitWorkerWithUptSvrListCB(const string &str_svr_appkey, + const string &str_cli_appkey, + const string &str_proto_type, + const string &str_service_name, + const UpdateSvrListCallback &cb); +int8_t StartSvr(const meituan_mns::SGService &sgService); + +string InitLocalAddr(void); +} // namespace mns_sdk + +string mns_sdk::InitLocalAddr(void) { + string str_sgagent_default_port; + try { + str_sgagent_default_port = + boost::lexical_cast(g_config.local_chrion_port_); + } catch (boost::bad_lexical_cast &e) { + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << " port : " + << g_config.local_chrion_port_); + } + + return g_config.str_local_ip_ + ":" + str_sgagent_default_port; +} + +void mns_sdk::UptSvrList(const string &appkey, ServiceInfo &service_info) { + vector::const_iterator it_vec; + boost::unordered_map::iterator + it_map_sgservice; + + string str_port; + + vector vec_sgservice_add; + vector vec_sgservice_del; + vector vec_sgservice_chg; + + const vector &vec_sgservice = service_info.sgservice_; + boost::unordered_map + &g_map_ipport_sgservice_ = + service_info.map_ipport_sgservice_; + if (MNS_UNLIKELY( + 0 == g_map_ipport_sgservice_.size() && 0 == vec_sgservice.size())) { + MNS_LOG_WARN("Init svr list but empty srvlist"); + } else if (MNS_UNLIKELY(0 == g_map_ipport_sgservice_.size())) { + it_vec = vec_sgservice.begin(); + MNS_LOG_INFO("Init svr list for appkey: " << it_vec->appkey); + + while (it_vec != vec_sgservice.end()) { + if (MNS_UNLIKELY(2 != it_vec->status)) { + MNS_LOG_DEBUG("svr info: " << MnsSdkCommon::SGService2String(*it_vec) + << " IGNORED"); + ++it_vec; + continue; + } + + try { + str_port = boost::lexical_cast(it_vec->port); + } catch (boost::bad_lexical_cast &e) { + MNS_LOG_ERROR("boost::bad_lexical_cast :" + << e.what() << "svr info : " + << MnsSdkCommon::SGService2String( + *it_vec)); + ++it_vec; + continue; + } + + g_map_ipport_sgservice_.insert(make_pair(it_vec->ip + ":" + str_port, + *it_vec)); + + vec_sgservice_add.push_back(*(it_vec++)); + } + } else if (MNS_UNLIKELY(0 == vec_sgservice.size())) { + MNS_LOG_WARN("vec_sgservice empty"); + + it_map_sgservice = g_map_ipport_sgservice_.begin(); + while (it_map_sgservice != g_map_ipport_sgservice_.end() + && (g_local_ip_port) + != it_map_sgservice->first) { //exclude local sgagent since sentinel list NOT include it + vec_sgservice_del.push_back(it_map_sgservice->second); + g_map_ipport_sgservice_.erase(it_map_sgservice++); + } + } else { + boost::unordered_map + map_tmp_locate_del(g_map_ipport_sgservice_); + + map_tmp_locate_del.erase(g_local_ip_port); //exclude local sgagent + + it_vec = vec_sgservice.begin(); + while (it_vec != vec_sgservice.end()) { + if (MNS_UNLIKELY(2 != it_vec->status)) { + MNS_LOG_DEBUG("svr info: " << MnsSdkCommon::SGService2String(*it_vec) + << " IGNORED"); + ++it_vec; + continue; + } + + try { + str_port = boost::lexical_cast(it_vec->port); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "svr info : " + << MnsSdkCommon::SGService2String( + *it_vec)); + + ++it_vec; + continue; + } + + string str_key(it_vec->ip + ":" + str_port); + it_map_sgservice = g_map_ipport_sgservice_.find(str_key); + if (g_map_ipport_sgservice_.end() == it_map_sgservice) { + MNS_LOG_DEBUG("ADD svr list info: " + << MnsSdkCommon::SGService2String(*it_vec)); + + vec_sgservice_add.push_back(*it_vec); + g_map_ipport_sgservice_.insert(make_pair(str_key, *it_vec)); + } else { + map_tmp_locate_del.erase(str_key); + + if (it_map_sgservice->second != *it_vec) { + MNS_LOG_DEBUG( + "UPDATE svr list. old info: " + << MnsSdkCommon::SGService2String(it_map_sgservice->second) + << " new info: " + << MnsSdkCommon::SGService2String(*it_vec)); + + it_map_sgservice->second = *it_vec; + + vec_sgservice_chg.push_back(*it_vec); + + map_tmp_locate_del.erase(str_key); + } + } + + ++it_vec; + } + + if (map_tmp_locate_del.size()) { + MNS_LOG_DEBUG("DEL svr list"); + + it_map_sgservice = map_tmp_locate_del.begin(); + while (it_map_sgservice != map_tmp_locate_del.end()) { + MNS_LOG_DEBUG( + "del svr info: " + << MnsSdkCommon::SGService2String(it_map_sgservice->second)); + + vec_sgservice_del.push_back(it_map_sgservice->second); + g_map_ipport_sgservice_.erase((it_map_sgservice++)->first); + } + } + } + + if (MNS_UNLIKELY(vec_sgservice_add.size() || vec_sgservice_del.size() + || vec_sgservice_chg.size())) { + for (vector::const_iterator + itr = service_info.update_cb_list_.begin(); + service_info.update_cb_list_.end() != itr; ++itr) { + (*itr)(vec_sgservice_add, + vec_sgservice_del, + vec_sgservice_chg, + appkey); + } + + for (vector::const_iterator + itr = service_info.cb_list_.begin(); + service_info.cb_list_.end() != itr; ++itr) { + (*itr)(vec_sgservice, + appkey); + } + } +} + +void mns_sdk::GetSvrList(void) { + typedef boost::unordered_map::iterator MAP_IT; + meituan_mns::ProtocolResponse rsp; + rsp.__set_errcode(-1); + for (MAP_IT iter = (ThreadLocalSingletonMap::instance()).begin(); + iter != (ThreadLocalSingletonMap::instance()).end(); ++iter) { + MNS_LOG_INFO("appkey: " << iter->first << " Do getsvrlist"); + try { + (ThreadLocalSingletonSGAgentClientSharedPtr::instance()) + ->GetServiceList(rsp, iter->second.protoreq_); + } catch (apache::thrift::TException &tx) { + MNS_LOG_ERROR("appkey: " << iter->first << " service getsvrlist error " + << tx.what()); + return; + } + + if (0 != rsp.errcode) { + MNS_LOG_ERROR( + "appkey: " << iter->first << " meituan_mns::ProtocolResponse errcode " + << rsp.errcode); + return; + } + + //filter service name + const string &tmp_service = iter->second.protoreq_.serviceName; + if (!tmp_service.empty()) { + MNS_LOG_INFO( + "Get service list with serviceName filter: " << tmp_service); + rsp.servicelist.erase(remove_if(rsp.servicelist.begin(), + rsp.servicelist.end(), + boost::bind(mns_sdk::FilterService, + _1, + tmp_service)), + rsp.servicelist.end()); + } + (iter->second.sgservice_).assign(rsp.servicelist.begin(), + rsp.servicelist.end()); + + MNS_LOG_DEBUG("appkey: " << iter->first << " recv vec_sgservice.size " + << (iter->second.sgservice_).size()); + for (int i = 0; i < static_cast((iter->second.sgservice_).size()); + i++) { + MNS_LOG_DEBUG( + "[" << i << "]" << ": " + << MnsSdkCommon::SGService2String((iter->second.sgservice_)[i])); + } + + UptSvrList(iter->first, iter->second); + } +} + +void mns_sdk::GetSvrList(const string &str_svr_appkey, + const string &str_cli_appkey, + const string &str_proto_type, + const string &str_service_name, + vector *p_res_svr_list, + muduo::CountDownLatch *p_countdown_get_svr_list) { + meituan_mns::ProtocolRequest protoreq; + protoreq.__set_localAppkey(str_cli_appkey); + protoreq.__set_remoteAppkey(str_svr_appkey); + protoreq.__set_protocol(str_proto_type); + protoreq.__set_serviceName(str_service_name); + + meituan_mns::ProtocolResponse rsp; + rsp.__set_errcode(-1); + try { + (ThreadLocalSingletonSGAgentClientSharedPtr::instance()) + ->GetServiceList(rsp, protoreq); + } catch (apache::thrift::TException &tx) { + MNS_LOG_ERROR("appkey: " << str_svr_appkey << " service getsvrlist error " + << tx.what()); + p_countdown_get_svr_list->countDown(); + return; + } + + if (0 != rsp.errcode) { + MNS_LOG_ERROR("appkey: " << str_svr_appkey + << " meituan_mns::ProtocolResponse errcode " + << rsp.errcode); + p_countdown_get_svr_list->countDown(); + return; + } + + //filter service name + if (!str_service_name.empty()) { + MNS_LOG_INFO( + "Get service list with serviceName filter: " << str_service_name); + rsp.servicelist.erase(remove_if(rsp.servicelist.begin(), + rsp.servicelist.end(), + boost::bind(mns_sdk::FilterService, + _1, + str_service_name)), + rsp.servicelist.end()); + } + p_res_svr_list->assign(rsp.servicelist.begin(), rsp.servicelist.end()); + MNS_LOG_DEBUG("appkey: " << str_svr_appkey << " recv vec_sgservice.size " + << p_res_svr_list->size()); + p_countdown_get_svr_list->countDown(); + //no need to update status. +} + +void mns_sdk::InitMap() { + MNS_LOG_DEBUG("begin to init global map."); + ThreadLocalSingletonMap::instance() = + boost::unordered_map(); +} + +int mns_sdk::InitMNS(const std::string &mns_path, const double &sec, const +double &timeout) { + + if (g_config.LoadConfig(mns_path) != 0) { + MNS_LOG_DEBUG("load config file failed." << mns_path); + return -1; + } + + muduo::MutexLockGuard lock(init_mutex); + + if (NULL == mns_eventloop_p_) { + mns_worker_thread_sp_ = boost::make_shared( + muduo::net::EventLoopThread::ThreadInitCallback(), + "mns_sdk"); + + mns_eventloop_p_ = mns_worker_thread_sp_->startLoop(); + + mns_eventloop_p_->runInLoop(mns_sdk::InitCthrift); + + mns_eventloop_p_->runInLoop(mns_sdk::InitMap); + + mns_eventloop_p_->runEvery(sec, + boost::bind(&GetSvrList)); + + } + ref_count_++; + + return 0; +} + +void mns_sdk::InitCthrift(void) { + MNS_LOG_DEBUG("Init Cthrift & sg_agent client"); + + if (!ThreadLocalSingletonSGAgentClientSharedPtr::instance()) { + ThreadLocalSingletonSGAgentClientSharedPtr::instance() = + boost::make_shared(); + + ThreadLocalSingletonSGAgentClientSharedPtr::instance()->Init(); + g_local_ip_port = InitLocalAddr(); + } +} + +void mns_sdk::InitWorkerWithSvrListCB(const string &str_svr_appkey, + const string &str_cli_appkey, + const string &str_proto_type, + const string &str_service_name, + const SvrListCallback &cb) { + ServiceInfo &service_info = + (ThreadLocalSingletonMap::instance())[str_svr_appkey]; + service_info.SetProtocolReq(str_cli_appkey, str_svr_appkey, + str_proto_type, str_service_name); + service_info.AddSvrListCallback(cb); + + GetSvrList(); +} + +void mns_sdk::InitWorkerWithUptSvrListCB(const string &str_svr_appkey, + const string &str_cli_appkey, + const string &str_proto_type, + const string &str_service_name, + const UpdateSvrListCallback &cb) { + ServiceInfo &service_info = + (ThreadLocalSingletonMap::instance())[str_svr_appkey]; + service_info.SetProtocolReq(str_cli_appkey, str_svr_appkey, + str_proto_type, str_service_name); + service_info.AddUpdateSvrListCallback(cb); + + GetSvrList(); +} + +int8_t mns_sdk::getSvrList(const string &str_svr_appkey, + const string &str_cli_appkey, + const string &str_proto_type, + const string &str_service_name, + vector *p_svr_list) { + if (str_svr_appkey.empty() || NULL == p_svr_list) { + MNS_LOG_ERROR( + "Input server appkey can not empty, and result point of " + "meituan_mns::SGService list should not NULL"); + return -1; + } + + if (MNS_LIKELY(mns_eventloop_p_)) { + + muduo::CountDownLatch countdown_get_svr_list(1); + mns_eventloop_p_->runInLoop(boost::bind(&GetSvrList, + str_svr_appkey, + str_cli_appkey, + str_proto_type, + str_service_name, + p_svr_list, + &countdown_get_svr_list)); + + countdown_get_svr_list.wait(); + } else { + MNS_LOG_ERROR("Please init mns_sdk first"); + return -1; + } + return 0; +} + +void mns_sdk::DoAddSvrListCallback(const string &str_svr_appkey, + const SvrListCallback &cb, + string *p_err_info, + muduo::CountDownLatch *countdown_set_callback) { + boost::unordered_map + &map_serviceInfo = ThreadLocalSingletonMap::instance(); + if (map_serviceInfo.end() == map_serviceInfo.find(str_svr_appkey)) { + p_err_info->assign("Has not set protocol type for " + str_svr_appkey + + ". Please use StartClient set first."); + MNS_LOG_DEBUG(*p_err_info); + countdown_set_callback->countDown(); + return; + } + map_serviceInfo[str_svr_appkey].AddSvrListCallback(cb); + countdown_set_callback->countDown(); +} + +int8_t mns_sdk::AddSvrListCallback(const string &str_svr_appkey, + const SvrListCallback &cb, + string *p_err_info) { + bool appkey_empty = str_svr_appkey.empty(); + bool cb_empty = cb.empty(); + bool p_err_info_null = (NULL == p_err_info); + if (MNS_UNLIKELY(appkey_empty || cb_empty || p_err_info_null)) { + string str_err_info("input appkey empty " + (appkey_empty ? string("true;") + : string("false;")) + + + " input callback func empty " + + (cb_empty ? string("true;") : string("false;")) + + " input err info pointer null " + + (p_err_info_null ? string("true.") : string( + "false."))); + MNS_LOG_ERROR(str_err_info); + if (p_err_info) { + p_err_info->assign(str_err_info); + } + return -1; + } + if (MNS_LIKELY(mns_eventloop_p_)) { + muduo::CountDownLatch countdown_set_callback(1); + mns_eventloop_p_->runInLoop(boost::bind(&mns_sdk::DoAddSvrListCallback, + str_svr_appkey, + cb, + p_err_info, + &countdown_set_callback)); + countdown_set_callback.wait(); + } else { + MNS_LOG_ERROR("Please init mns_sdk first"); + return -1; + } + return p_err_info->empty() ? 0 : -1; +} + +void mns_sdk::DoAddUpdateSvrListCallback(const string &str_svr_appkey, + const UpdateSvrListCallback &cb, + string *p_err_info, + muduo::CountDownLatch *countdown_set_callback) { + boost::unordered_map + &map_serviceInfo = ThreadLocalSingletonMap::instance(); + if (map_serviceInfo.end() == map_serviceInfo.find(str_svr_appkey)) { + p_err_info->assign("Has not set protocol type for " + str_svr_appkey + + ". Please use StartClient set first."); + MNS_LOG_DEBUG(*p_err_info); + countdown_set_callback->countDown(); + return; + } + map_serviceInfo[str_svr_appkey].AddUpdateSvrListCallback(cb); + countdown_set_callback->countDown(); +} + +int8_t mns_sdk::AddUpdateSvrListCallback(const string &str_svr_appkey, + const UpdateSvrListCallback &cb, + string *p_err_info) { + bool appkey_empty = str_svr_appkey.empty(); + bool cb_empty = cb.empty(); + bool p_err_info_null = (NULL == p_err_info); + if (MNS_UNLIKELY(appkey_empty || cb_empty || p_err_info_null)) { + string str_err_info("input appkey empty " + (appkey_empty ? string("true;") + : string("false;")) + + + " input callback func empty " + + (cb_empty ? string("true;") : string("false;")) + + " input err info pointer null " + + (p_err_info_null ? string("true.") : string( + "false."))); + MNS_LOG_ERROR(str_err_info); + if (p_err_info) { + p_err_info->assign(str_err_info); + } + return -1; + } + if (MNS_LIKELY(mns_eventloop_p_)) { + muduo::CountDownLatch countdown_set_callback(1); + mns_eventloop_p_->runInLoop(boost::bind(&mns_sdk::DoAddUpdateSvrListCallback, + str_svr_appkey, + cb, + p_err_info, + &countdown_set_callback)); + countdown_set_callback.wait(); + } else { + MNS_LOG_ERROR("Please init mns_sdk first"); + } + return p_err_info->empty() ? 0 : -1; +} + +int8_t mns_sdk::StartClient(const string &str_svr_appkey, + const string &str_cli_appkey, + const string &str_proto_type, + const string &str_service_name, + const SvrListCallback &cb) { + if (str_svr_appkey.empty() || str_cli_appkey.empty()) { + MNS_LOG_ERROR("Input appkeys should not empty"); + return -1; + } + MNS_LOG_DEBUG("str_svr_appkey " << str_svr_appkey << " str_client_appkey " + << str_cli_appkey << " str_proto_type " + << str_proto_type << " " + "str_service_name " << str_service_name); + + if (MNS_LIKELY(mns_eventloop_p_)) { + + mns_eventloop_p_->runInLoop(boost::bind(&mns_sdk::InitWorkerWithSvrListCB, + str_svr_appkey, + str_cli_appkey, + str_proto_type, + str_service_name, + cb)); + } else { + MNS_LOG_ERROR("Please init mns_sdk first"); + return -1; + } + + return 0; +} + +int8_t mns_sdk::StartClient(const string &str_svr_appkey, + const string &str_cli_appkey, + const string &str_proto_type, + const string &str_service_name, + const UpdateSvrListCallback &cb) { + if (str_svr_appkey.empty() || str_cli_appkey.empty()) { + MNS_LOG_ERROR("Input appkeys should not empty"); + return -1; + } + MNS_LOG_DEBUG("str_svr_appkey " << str_svr_appkey << " str_client_appkey " + << str_cli_appkey << " str_proto_type " + << str_proto_type << " " + "str_service_name " << str_service_name); + + if (MNS_LIKELY(mns_eventloop_p_)) { + mns_eventloop_p_->runInLoop(boost::bind(&mns_sdk::InitWorkerWithUptSvrListCB, + str_svr_appkey, + str_cli_appkey, + str_proto_type, + str_service_name, + cb)); + } else { + MNS_LOG_ERROR("Please mns_sdk first"); + } + + return 0; +} + +int8_t mns_sdk::StartSvr(const string &str_appkey, + const vector &service_list, + const int16_t &i16_port, + const int32_t &i32_svr_type, + const string &str_proto_type, + const bool &b_is_uniform) { + meituan_mns::SGService sgService; + sgService.appkey.assign(str_appkey); + sgService.version.assign("mns_sdk-1.3.0"); + sgService.ip.assign(g_config.str_local_ip_); + sgService.port = i16_port; + sgService.weight = 10; + //状态从2-->0,对齐scanner状态图 + sgService.status = 2; + sgService.lastUpdateTime = static_cast(time(0)); + sgService.fweight = 10.0; + sgService.serverType = i32_svr_type; + if (!service_list.empty()) { + meituan_mns::ServiceDetail detail; + detail.__set_unifiedProto(b_is_uniform); + map serviceInfo; + + for (vector::const_iterator iter = service_list.begin(); + iter != service_list.end(); ++iter) { + serviceInfo.insert(make_pair(*iter, detail)); + } + sgService.__set_serviceInfo(serviceInfo); + } + + string tmp; + + switch (i32_svr_type) { + case 0:sgService.protocol.assign("thrift"); + break; + case 1:sgService.protocol.assign("http"); + break; + case 2:tmp.assign(str_proto_type); + transform(tmp.begin(), + tmp.end(), + tmp.begin(), + ::tolower); + if ("thrift" == tmp || "http" == tmp) { + MNS_LOG_ERROR("sgService.serverType 2 but" + " str_proto_type " << str_proto_type); + return -1; + } + + sgService.protocol.assign(str_proto_type); + break; + default: MNS_LOG_ERROR( + "unkown sgService.serverType " << sgService.serverType); + return -1; + } + + MNS_LOG_DEBUG( + "create sgservice " << MnsSdkCommon::SGService2String(sgService)); + + return StartSvr(sgService); +} + +int8_t mns_sdk::StartSvr(const string &str_appkey, + const int16_t &i16_port, + const int32_t &i32_svr_type, + const string &str_proto_type) { + vector service_list; + return StartSvr(str_appkey, + service_list, + i16_port, + i32_svr_type, + str_proto_type); +} + +int8_t mns_sdk::StartSvr(const meituan_mns::SGService &sgService) { + InitCthrift(); + + try { + int32_t i32_ret = + (ThreadLocalSingletonSGAgentClientSharedPtr::instance())->RegistService( + sgService); + if (MNS_UNLIKELY(i32_ret)) { + MNS_LOG_ERROR("registService failed: " << i32_ret); + return -1; + } else { + MNS_LOG_INFO("reg svr done"); + } + } catch (apache::thrift::TException &tx) { + MNS_LOG_ERROR("registService failed: " << tx.what()); + return -1; + } + + return 0; +} + +void mns_sdk::DestroyMNS(void) { + //仿造智能指针,使用引用计数管理资源释放。 + muduo::MutexLockGuard lock(init_mutex); + if (0 == (--ref_count_) && mns_eventloop_p_) { + mns_eventloop_p_->quit(); + usleep(500 * 1000); + mns_eventloop_p_ = NULL; + } +} + +bool mns_sdk::FilterService(const meituan_mns::SGService &sg, + const string &service_name) { + return sg.serviceInfo.find(service_name) == sg.serviceInfo.end(); +} diff --git a/sdk/mns-sdk/src/mns_sdk.h b/sdk/mns-sdk/src/mns_sdk.h new file mode 100644 index 0000000..c17712e --- /dev/null +++ b/sdk/mns-sdk/src/mns_sdk.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_MNS_SDK_H_ +#define OCTO_OPEN_SOURCE_MNS_SDK_H_ + +#include "mns_worker.h" + +namespace mns_sdk { + +//获取服务列表回调函数,允许为空,另外注意MNS库的子线程在执行该函数,注意线程安全问题 +typedef boost::function &vec, + const std::string &str_svr_appkey)> + SvrListCallback; + +//获取服务列表的回调函数, 三个vector分别代表服务列表中新增的,需要删除的, +//内容需要改变的, 三者允许任意为空. 另外注意是MNS库的子线程在执行这个函数, 注意线程安全问题 +typedef boost::function &vec_add, + const std::vector &vec_del, + const std::vector &vec_chg, + const std::string &str_svr_appkey)> + UpdateSvrListCallback; + +//启用clog统一日志,初始化日志系统,程序进程调用一次即可 + +int InitMNS(const std::string &mns_path, const double &sec, + const double &timeout = 0.5);//初始化mns_sdk客户端,mns_path 环境配置文件, +// 并设置服务列表拉取间隔(s),仅初始化一次即可。 + +//服务在一个进程中可以既调用StartSvr注册服务,又调用StartClient获取服务列表 +//同步注册服务, 默认等待时间不超过50ms, 返回非0表示注册失败 + +//注册服务 +int8_t StartSvr(const std::string &str_appkey, + const int16_t &i16_port, + const int32_t &i32_svr_type, //0:thrift, 1:http, 2:other + const std::string &str_proto_type = "thrift"); + +int8_t StartSvr(const std::string &str_appkey, + const std::vector &service_name_list, + const int16_t &i16_port, + const int32_t &i32_svr_type, //0:thrift, 1:http, 2:other + const std::string &str_proto_type,//"thrift", "http" + const bool &b_is_uniform = false); + + +//返回服务列表,存入用户传入的res_svr_list中 +int8_t getSvrList(const std::string &str_svr_appkey, + const std::string &str_cli_appkey, + const std::string &str_proto_type, + const std::string &str_service_name, + std::vector *p_svr_list); + +//获取所有类型服务节点,推荐,支持在一条业务线程中多次绑定不同的str_svr_appkey。 +int8_t StartClient(const std::string &str_svr_appkey, + const std::string &str_cli_appkey, + const std::string &str_proto_type, //client支持的协议类型 thrift/http/cellar..., 定期来取的svrlist将按照这个类型进行过滤 + const std::string &str_service_name, //IDL文件中的service名字,可按这个名字来过滤服务节点,可填空串返回全部服务节点 + const SvrListCallback &cb); //异步用回调定期获取服务列表, 返回非0表示参数错误(str_svr_appkey为空等) + +int8_t StartClient(const std::string &str_svr_appkey, + const std::string &str_cli_appkey, + const std::string &str_proto_type, //client支持的协议类型 thrift/http/cellar..., 定期来取的svrlist将按照这个类型进行过滤 + const std::string &str_service_name, //IDL文件中的service名字,可按这个名字来过滤服务节点,可填空串返回全部服务节点 + const UpdateSvrListCallback &cb); //异步用回调定期获取服务列表, 返回非0表示参数错误(str_svr_appkey为空等) + +int8_t AddSvrListCallback(const std::string &str_svr_appkey, + const SvrListCallback &cb, + std::string *p_err_info); + +int8_t AddUpdateSvrListCallback(const std::string &str_svr_appkey, + const UpdateSvrListCallback &cb, + std::string *p_err_info); + +void DestroyMNS(void);//退出时调用 +} +#endif //OCTO_OPEN_SOURCE_MNS_SDK_H_ + diff --git a/sdk/mns-sdk/src/mns_worker.cc b/sdk/mns-sdk/src/mns_worker.cc new file mode 100644 index 0000000..14f44be --- /dev/null +++ b/sdk/mns-sdk/src/mns_worker.cc @@ -0,0 +1,1306 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include + +#include "mns_worker.h" + +using namespace std; +using namespace muduo::net; +using namespace mns_sdk; + +void ConnInfo::UptSgservice(const meituan_mns::SGService &sgservice) { + double d_old_weight = MnsSdkCommon::FetchOctoWeight(sgservice_.fweight, + static_cast(sgservice_.weight)); + double d_new_weight = MnsSdkCommon::FetchOctoWeight(sgservice.fweight, + static_cast(sgservice.weight)); + + MNS_LOG_DEBUG("d_old_weight " << d_old_weight << " d_new_weight " + << d_new_weight); + + if (!MnsSdkCommon::CheckDoubleEqual(d_old_weight, d_new_weight)) { + MNS_LOG_DEBUG("need update weight buf"); + + //real conn NOT erase, just del index + p_map_weight_tcpclientwp_->erase(it_map_weight_tcpclientwp_index_); + + it_map_weight_tcpclientwp_index_ = + p_map_weight_tcpclientwp_->insert(std::make_pair( + d_new_weight, + sp_tcpclient_)); + } + + sgservice_ = sgservice; +} + +void ConnInfo::setSp_tcpclient_(const TcpClientSharedPtr &sp_tcpclient) { + if (MNS_UNLIKELY(sp_tcpclient_.get())) { + MNS_LOG_ERROR("client ip: " << (sp_tcpclient_->connection() + ->peerAddress()).toIp() << " port: " + << (sp_tcpclient_->connection()->peerAddress()).toPort() + << " replace"); + + p_map_weight_tcpclientwp_->erase(it_map_weight_tcpclientwp_index_); + } + + sp_tcpclient_ = sp_tcpclient; + + double d_weight = MnsSdkCommon::FetchOctoWeight(sgservice_.fweight, + static_cast(sgservice_.weight)); + MNS_LOG_DEBUG("dweight " << d_weight); + + it_map_weight_tcpclientwp_index_ = + p_map_weight_tcpclientwp_->insert(std::make_pair(d_weight, + sp_tcpclient_)); +} + +MnsWorker::MnsWorker() + : cond_avaliable_conn_ready_(mutexlock_avaliable_conn_ready_), + i8_destructor_flag_(0), + unzip_buf_(0), + sentinel_url_addr_(g_config.url_port_) { //atomic_avaliable_conn_num_ + // defalut init + // by value + //start real worker thread + sp_event_thread_ = + boost::make_shared(EventLoopThread::ThreadInitCallback(), + "cthrift_cli_IO"); + p_event_loop_ = sp_event_thread_->startLoop(); + p_event_loop_->runInLoop(boost::bind(&MnsWorker::InitWorker, + this)); //will use event_loop in +} + +void +MnsWorker::OnConn4Sentinel(const muduo::net::TcpConnectionPtr &conn) { + MNS_LOG_INFO(conn->localAddress().toIpPort() << " -> " + << conn->peerAddress().toIpPort() + << " is " + << (conn->connected() ? "UP" + : "DOWN")); + + if (conn->connected()) { + boost::shared_ptr tmp = boost::make_shared(); + conn->setContext(tmp); + conn->setTcpNoDelay(true); + + //maybe send a few duplicate request, but will stop when sentinel addrs filled, acceptable. + if (MNS_UNLIKELY(1 >= map_ipport_spconninfo_.size())) { + MNS_LOG_DEBUG("sgagent still NOT fill sentinel address"); + + muduo::net::Buffer buf; + buf.append(g_config.str_sentinel_http_request_); + + MNS_LOG_DEBUG("Send appkey tags buf " << buf.toStringPiece().data()); + + conn->send(&buf); + } + } else { + //http服务端关闭了链接后,这里的tcp链接应该close tcpclient,避免fd close_wait + if (sp_tcpclient_sentinel_) { + sp_tcpclient_sentinel_->disconnect(); + sp_tcpclient_sentinel_.reset(); + } + } +} + +void +MnsWorker::OnMsg4Sentinel(const muduo::net::TcpConnectionPtr &conn, + muduo::net::Buffer *buf, + muduo::Timestamp receiveTime) { + MNS_LOG_DEBUG("OnMsg buf " << (buf->toStringPiece()).data()); + + if (MNS_UNLIKELY((conn->getContext()).empty())) { + MNS_LOG_ERROR("address: " << (conn->peerAddress()).toIpPort() << " " + "context empty"); //NOT clear here + return; + } + + HttpContextSharedPtr pConnInfo; + try { + pConnInfo = boost::any_cast(conn->getContext()); + } catch (boost::bad_any_cast e) { + MNS_LOG_ERROR("bad_any_cast:" << e.what()); + return; + } + + if (buf->readableBytes() < pConnInfo->u32_want_len) { + MNS_LOG_DEBUG("NOT enough"); + return; + } + + if (!MnsSdkCommon::ParseHttpRequest(&(pConnInfo->u32_want_len), + buf, + &(pConnInfo->http_context), + muduo::Timestamp::now())) { + MNS_LOG_ERROR("parseRequest failed"); + return; + } + + if ((pConnInfo->http_context).gotAll()) { + const muduo::net::HttpRequest + &httpReq = (pConnInfo->http_context).request(); + const string &str_ori_body = httpReq.body(); + + if (0 == str_ori_body.size()) { + MNS_LOG_ERROR("No body from sentinel"); + return; + } + + //decompress + string str_body; + string strCotentCode = httpReq.getHeader("Content-Encoding"); + if (string::npos != strCotentCode.find("gzip")) { + MNS_LOG_DEBUG("strCotentCode " << strCotentCode); + + uLong ulBodyLen = 200000; //fix + int iRet + = + MnsSdkCommon::Httpgzdecompress(reinterpret_cast + (const_cast(str_ori_body.c_str())), + static_cast(str_ori_body.size()), + reinterpret_cast(unzip_buf_), + &ulBodyLen); + if (0 > iRet) { + MNS_LOG_ERROR("Httpgzdecompress failed, iRet " << iRet); + return; + } + + MNS_LOG_DEBUG("ulBodyLen " << ulBodyLen); + str_body.assign(unzip_buf_, ulBodyLen); + } else { + str_body.assign(str_ori_body); + } + + MNS_LOG_DEBUG("str_body " << str_body); + (pConnInfo->http_context).reset(); + + vector vec_sgservice; + if (MnsSdkCommon::ParseSentineSgagentList(str_body, &vec_sgservice)) { + return; + } + + if (MNS_LIKELY(!CheckLocalSgagentHealth())) { + UpdateSvrList(vec_sgservice); + } + } +} + +int8_t MnsWorker::CheckRegion(const double &d_weight) { + if (d_weight < MnsSdkCommon::kDSecondRegionMin) { + return 3; + } else if (d_weight < MnsSdkCommon::kDFirstRegionMin) { + return 2; + } + + return 1; +} + +bool ConnInfo::CheckConnHealthy(void) const { + if (MNS_UNLIKELY(!(sp_tcpclient_.get()))) { + MNS_LOG_ERROR("sp_tcpconn invalid appkey: " << sgservice_.appkey + << " ip:" << sgservice_.ip + << " port: " + << sgservice_.port); + return false; + } + + muduo::net::TcpConnectionPtr sp_tcpconn = sp_tcpclient_->connection(); + if (MNS_UNLIKELY(!sp_tcpconn || !(sp_tcpconn.get()))) { + MNS_LOG_ERROR("sp_tcpconn invalid appkey: " << sgservice_.appkey + << " ip:" << sgservice_.ip + << " port: " + << sgservice_.port); + return false; + } + + if (MNS_UNLIKELY(!(sp_tcpconn->connected()))) { + MNS_LOG_DEBUG("address: " << (sp_tcpconn->peerAddress()).toIpPort() + << "NOT connected"); + return false; + } + + if (MNS_UNLIKELY((sp_tcpconn->getContext()).empty())) { + MNS_LOG_ERROR("address: " << (sp_tcpconn->peerAddress()).toIpPort() << " " + "context empty"); //NOT clear here + return false; + } + + Context4WorkerSharedPtr sp_context; + try { + sp_context = boost::any_cast + (sp_tcpconn->getContext()); + } catch (boost::bad_any_cast e) { + MNS_LOG_ERROR("bad_any_cast:" << e.what() << " peer address " + << (sp_tcpconn->peerAddress()).toIpPort()); + return false; + } + + if (MNS_UNLIKELY(sp_context->b_highwater || sp_context->b_occupied)) { + MNS_LOG_WARN("address: " << (sp_tcpconn->peerAddress()).toIpPort() << + " b_highwater " << sp_context->b_highwater + << " b_occupied " + << sp_context->b_occupied << " ignore"); + return false; + } + + return true; +} + +int8_t MnsWorker::ChooseNextReadyConn(TcpClientWeakPtr *p_wp_tcpcli) { + if (MNS_UNLIKELY(0 == p_multimap_weight_wptcpcli_->size())) { + MNS_LOG_ERROR("multimap_weight_wptcpcli_ empty"); + return -1; + } + + string str_default_sgagent_port; + + try { + str_default_sgagent_port = + boost::lexical_cast(g_config.local_chrion_port_); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "SgagentPort " + << g_config.local_chrion_port_); + } + + UnorderedMapIpPort2ConnInfoSP iter_ipport_spconninfo; + + iter_ipport_spconninfo = map_ipport_spconninfo_.find + (g_config.str_local_ip_ + ":" + //NOT be "127.0.0.1" in normal + // case, but be when cannot fetch local ip + str_default_sgagent_port); + + if (map_ipport_spconninfo_.end() != iter_ipport_spconninfo + && iter_ipport_spconninfo->second->CheckConnHealthy()) { + MNS_LOG_DEBUG("sgagent rpc, local agent work, use it"); + + TcpClientWeakPtr wp_tcpcli + (iter_ipport_spconninfo->second->getSp_tcpclient_()); + *p_wp_tcpcli = wp_tcpcli; + + return 0; + } + + MNS_LOG_INFO("sgagent rpc, local agent NOT work, use sentinel"); + + boost::unordered_map > map_weight_vec; + vector vec_weight; + + double d_last_weight = -1.0; + double d_total_weight = 0.0; + int8_t i8_stop_region = 2; //init not necessary, but for safe + string str_port; + + muduo::net::TcpConnectionPtr sp_tcpconn; + + MultiMapIter iter = p_multimap_weight_wptcpcli_->begin(); + while (p_multimap_weight_wptcpcli_->end() != iter) { + TcpClientSharedPtr sp_tcpcli((iter->second).lock()); + if (MNS_UNLIKELY(!sp_tcpcli || !(sp_tcpcli.get()))) { + MNS_LOG_ERROR("tcpclient NOT avaliable"); + + p_multimap_weight_wptcpcli_->erase(iter++); + continue; + } + + sp_tcpconn = sp_tcpcli->connection(); + if (MNS_UNLIKELY(!sp_tcpconn)) { + MNS_LOG_INFO("NOT connected yet"); + ++iter; + continue; + } + + MNS_LOG_DEBUG("Address: " << (sp_tcpconn->peerAddress()).toIpPort() << " " + "weight " << iter->first); + + try { + str_port = + boost::lexical_cast((sp_tcpconn->peerAddress()).toPort()); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "tcp connnect peer port : " + << (sp_tcpconn->peerAddress()).toPort()); + + ++iter; + continue; + } + + iter_ipport_spconninfo = map_ipport_spconninfo_.find( + (sp_tcpconn->peerAddress()).toIp() + ":" + str_port); + if (MNS_UNLIKELY( + iter_ipport_spconninfo == map_ipport_spconninfo_.end())) { + MNS_LOG_ERROR("Not find ip:" + << (sp_tcpconn->peerAddress()).toIp() << " port:" + << str_port << " in map_ipport_spconninfo_"); + + p_multimap_weight_wptcpcli_->erase(iter++); + continue; + } + + if (!(iter_ipport_spconninfo->second->CheckConnHealthy())) { + ++iter; + continue; + } + + //weight random choose algorithm + //1. sum all weight(one weight = single weight * same weight conn num) + //2. random total_weight,get a random_weight + //3. choose random_weight region from all weight. + if (!MnsSdkCommon::CheckDoubleEqual(d_last_weight, + iter->first)) { //new weight + if (MNS_LIKELY( + !MnsSdkCommon::CheckDoubleEqual(d_last_weight, -1.0))) { //NOT init + if (i8_stop_region <= CheckRegion(iter->first)) { //if already get + // conn and next region reach, stop + MNS_LOG_DEBUG("stop region " << i8_stop_region << " " + "iter->first " << iter->first); + break; + } + + d_total_weight += d_last_weight * static_cast + (map_weight_vec[d_last_weight] + .size + ()); + } else { + i8_stop_region = + static_cast(CheckRegion(iter->first) + + 1); //set stop region by the first weight + + MNS_LOG_DEBUG("i8_stop_region set to be " << i8_stop_region); + } + + vec_weight.push_back(iter->first); + d_last_weight = iter->first; + } + + map_weight_vec[iter->first].push_back(iter->second); + ++iter; + } + + if (MNS_UNLIKELY(0 == vec_weight.size())) { + MNS_LOG_INFO("Not avaliable conn can be choosed, maybe all occupied"); + return 1; + } + //将所有候选节点的权重进行求和:d_total_weight + //将权重看作一条线段,d_total_weight是线段长度 + //不同权重的节点占据这条线段的不同部分 + //产生0~d_total_weight一个随机数,落入的权重线段某个区域; 选择该区域归属的节点列表;从这个节点列表中随机选择一个节点。 + d_total_weight += + d_last_weight * static_cast(map_weight_vec[d_last_weight].size + ()); + + MNS_LOG_DEBUG("d_total_weight " << d_total_weight); + //伪随机数在小范围下不均匀(0~1),放大1000倍解决该问题 + d_total_weight *= static_cast(1000.0); + + double d_choose = 0.0; + double d_tmp = 0.0; + //产生的随机数落入权重线段某个区域,后面的while其实是在找这个“区域” + double d_random_weight = fmod(static_cast(rand()), d_total_weight); + vector::iterator it_vec = vec_weight.begin(); + while (vec_weight.end() != it_vec) { + //伪随机数在小范围下不均匀(0~1),放大1000倍进行平滑处理 + d_tmp += (*it_vec) * static_cast(map_weight_vec[*it_vec].size()) + * static_cast(1000.0); + if (d_tmp > d_random_weight) { + d_choose = *it_vec; + break; + } + + ++it_vec; + } + + boost::unordered_map >::iterator + it_map = map_weight_vec.find(d_choose); + if (MNS_UNLIKELY(it_map == map_weight_vec.end())) { + MNS_LOG_ERROR("not find weight " << d_choose); + return -1; + } + + if (1 == (it_map->second).size()) { + *p_wp_tcpcli = *((it_map->second).begin()); + } else { + MNS_LOG_DEBUG((it_map->second).size() << " conn need be choose one " + "equally"); + + *p_wp_tcpcli = (it_map->second)[rand() % ((it_map->second).size())]; + } + + return 0; +} + +void +MnsWorker::UpdateSvrList(const vector &vec_sgservice) { + vector::const_iterator it_vec; + boost::unordered_map::iterator + it_map_sgservice; + + string str_port; + string str_sgagent_default_port; + + try { + str_sgagent_default_port = + boost::lexical_cast(g_config.local_chrion_port_); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "SgagentPort " + << g_config.local_chrion_port_); + + return; + } + + vector vec_sgservice_add; + vector vec_sgservice_del; + vector vec_sgservice_chg; + + if (MNS_UNLIKELY( + 0 == map_ipport_sgservice_.size() && 0 == vec_sgservice.size())) { + MNS_LOG_WARN("Init svr list but empty srvlist"); + } else if (MNS_UNLIKELY(0 == map_ipport_sgservice_.size())) { + it_vec = vec_sgservice.begin(); + MNS_LOG_INFO("Init svr list for appkey " << it_vec->appkey); + + while (it_vec != vec_sgservice.end()) { + if (MNS_UNLIKELY(2 != it_vec->status)) { + MNS_LOG_DEBUG("svr info: " + << MnsSdkCommon::SGService2String(*it_vec) + << " IGNORED"); + ++it_vec; + continue; + } + + try { + str_port = boost::lexical_cast(it_vec->port); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "it_vec->port " + << it_vec->port); + + ++it_vec; + continue; + } + + map_ipport_sgservice_.insert(make_pair(it_vec->ip + ":" + str_port, + *it_vec)); + + vec_sgservice_add.push_back(*(it_vec++)); + } + } else if (MNS_UNLIKELY(0 == vec_sgservice.size())) { + MNS_LOG_WARN("vec_sgservice empty"); + + it_map_sgservice = map_ipport_sgservice_.begin(); + while (it_map_sgservice + != map_ipport_sgservice_.end()) { //exclude local sgagent since sentinel list NOT include it + if (g_config.str_local_ip_ + ":" + g_config.str_local_chrion_port_ + != it_map_sgservice->first) { + vec_sgservice_del.push_back(it_map_sgservice->second); + map_ipport_sgservice_.erase(it_map_sgservice++); + } else { + it_map_sgservice++; + } + } + } else { + boost::unordered_map + map_tmp_locate_del(map_ipport_sgservice_); + map_tmp_locate_del.erase(g_config.str_local_ip_ + ":" + + g_config.str_local_chrion_port_); //exclude local sgagent + + it_vec = vec_sgservice.begin(); + while (it_vec != vec_sgservice.end()) { + if (MNS_UNLIKELY(2 != it_vec->status)) { + MNS_LOG_DEBUG("svr info: " + << MnsSdkCommon::SGService2String(*it_vec) + << " IGNORED"); + ++it_vec; + continue; + } + + try { + str_port = boost::lexical_cast(it_vec->port); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_DEBUG("boost::bad_lexical_cast :" << e.what() + << "it_vec->port " + << it_vec->port); + + ++it_vec; + continue; + } + + string str_key(it_vec->ip + ":" + str_port); + it_map_sgservice = map_ipport_sgservice_.find(str_key); + if (map_ipport_sgservice_.end() == it_map_sgservice) { + MNS_LOG_DEBUG("ADD svr list info: " + << MnsSdkCommon::SGService2String(*it_vec)); + + vec_sgservice_add.push_back(*it_vec); + map_ipport_sgservice_.insert(make_pair(str_key, *it_vec)); + } else { + map_tmp_locate_del.erase(str_key); + + if (it_map_sgservice->second != *it_vec) { + MNS_LOG_DEBUG("UPDATE svr list. old info: " + << MnsSdkCommon::SGService2String(it_map_sgservice->second)); + MNS_LOG_DEBUG(" new info: " + << MnsSdkCommon::SGService2String(*it_vec)); + + it_map_sgservice->second = *it_vec; + + vec_sgservice_chg.push_back(*it_vec); + + map_tmp_locate_del.erase(str_key); + } + } + + ++it_vec; + } + + if (map_tmp_locate_del.size()) { + MNS_LOG_DEBUG("DEL svr list"); + + it_map_sgservice = map_tmp_locate_del.begin(); + while (it_map_sgservice != map_tmp_locate_del.end()) { + MNS_LOG_DEBUG("del svr info: " + << MnsSdkCommon::SGService2String(it_map_sgservice->second)); + + vec_sgservice_del.push_back(it_map_sgservice->second); + map_ipport_sgservice_.erase((it_map_sgservice++)->first); + } + } + } + + AddSrv(vec_sgservice_add); + DelSrv(vec_sgservice_del); + ChgSrv(vec_sgservice_chg); +} + +void MnsWorker::InitSentinel(void) { + //conn to sentinel + sp_tcpclient_sentinel_ = boost::make_shared( + p_event_loop_, + sentinel_url_addr_, + "sentinel tcpclient"); + + sp_tcpclient_sentinel_->setConnectionCallback(boost::bind(&MnsWorker::OnConn4Sentinel, + this, + _1)); + sp_tcpclient_sentinel_->setMessageCallback(boost::bind(&MnsWorker::OnMsg4Sentinel, + this, + _1, + _2, + _3)); + sp_tcpclient_sentinel_->enableRetry(); + sp_tcpclient_sentinel_->connect(); +} + +void MnsWorker::UnInitSentinel(void) { + + if (MNS_LIKELY(CheckLocalSgagentHealth())) { + MNS_LOG_DEBUG("sgagent rpc, local agent work, use it, remove sentinel"); + + if (sp_tcpclient_sentinel_) { + sp_tcpclient_sentinel_->disconnect(); + sp_tcpclient_sentinel_.reset(); + } + + vector vec_sgservice; + UpdateSvrList(vec_sgservice); + return; + } +} + +bool MnsWorker::CheckLocalSgagentHealth(void) { + string str_default_sgagent_port; + + try { + str_default_sgagent_port = + boost::lexical_cast(g_config.local_chrion_port_); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "SgagentPort " + << g_config.local_chrion_port_); + } + + UnorderedMapIpPort2ConnInfoSP iter_ipport_spconninfo; + + iter_ipport_spconninfo = map_ipport_spconninfo_.find + (g_config.str_local_ip_ + ":" + g_config.str_local_chrion_port_); + + if (map_ipport_spconninfo_.end() != iter_ipport_spconninfo + && iter_ipport_spconninfo->second->CheckConnHealthy()) { + MNS_LOG_DEBUG("sgagent rpc, local agent work, use it"); + + return true; + } + + return false; +} + +void MnsWorker::CheckLocalSgagent(void) { + + if (MNS_LIKELY(CheckLocalSgagentHealth())) { + MNS_LOG_DEBUG("sgagent rpc, local agent work, return"); + + if (map_ipport_spconninfo_.size() > 1) { + p_event_loop_->runAfter(kDRetryIntervalSec, + boost::bind(&MnsWorker::UnInitSentinel, this)); + } + + return; + } + + // to init InitSentinel + MNS_LOG_WARN("sgagent rpc, local agent NOT work, init sentinel"); + + if (map_ipport_spconninfo_.size() <= 1 && 0 == i8_destructor_flag_) { + InitSentinel(); + } +} + +void MnsWorker::InitWorker(void) { + p_multimap_weight_wptcpcli_ = + new multimap;//exit del, safe + + unzip_buf_ = new char[200000]; //200k for sentinel content + + meituan_mns::SGService sgservice; + MnsSdkCommon::PackDefaultSgservice(g_config.chrion_appkey_, + g_config.str_local_ip_, + static_cast(g_config + .local_chrion_port_), + &sgservice); + vector vec_sgservice; + vec_sgservice.push_back(sgservice); + + UpdateSvrList(vec_sgservice); + + if (g_config.b_use_remote_) { + if (!muduo::net::InetAddress::resolve(g_config.url_, + &sentinel_url_addr_)) { //ONLY fill + // IP address + MNS_LOG_WARN("resolve " << g_config.url_ << " failed"); + + } else { + //启动时,本地sg可用50ms后开始初始化哨兵;避免初始化哨兵占用work线程,造成第一次拉取服务列表超时. + MNS_LOG_DEBUG("CheckLocalSgagent after 0.05s"); + p_event_loop_->runAfter(0.05, + boost::bind(&MnsWorker::CheckLocalSgagent, this)); + + } + } +} + +void MnsWorker::AddSrv(const vector &vec_add_sgservice) { + string str_port; + vector vec_chg_sgservice; + MultiMapIter it_multimap; + + vector::const_iterator + it_sgservice = vec_add_sgservice + .begin(); + while (it_sgservice != vec_add_sgservice.end()) { + const meituan_mns::SGService &sgservice = *it_sgservice; + + try { + str_port = boost::lexical_cast(sgservice.port); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "sgservice.port " + << sgservice.port); + + ++it_sgservice; + continue; + } + + ConnInfoSharedPtr + &sp_conninfo = map_ipport_spconninfo_[sgservice.ip + ":" + str_port]; + + if (MNS_UNLIKELY(sp_conninfo.get())) { + MNS_LOG_WARN("svr " << MnsSdkCommon::SGService2String(sgservice) + << " already exist in map_ipport_sptcpcli, just change it"); + + vec_chg_sgservice.push_back(sgservice); + ++it_sgservice; + + continue; + } + + sp_conninfo = boost::make_shared(sgservice, + p_multimap_weight_wptcpcli_); + + boost::shared_ptr + sp_tcp_cli_tmp = boost::make_shared( + p_event_loop_, + muduo::net::InetAddress( + sgservice.ip, + static_cast(sgservice.port)), + "client worker for appkey " + + sgservice.appkey); + + sp_conninfo->setSp_tcpclient_(sp_tcp_cli_tmp);//will set weight buf inside + + TcpClientSharedPtr &sp_tcpcli = sp_conninfo->getSp_tcpclient_(); + + sp_tcpcli->setConnectionCallback(boost::bind(&MnsWorker::OnConn, + this, + _1)); + + sp_tcpcli->setMessageCallback(boost::bind(&MnsWorker::OnMsg, + this, + _1, + _2, + _3)); + + sp_tcpcli->enableRetry(); + sp_tcpcli->connect(); + + ++it_sgservice; + } + + if (vec_chg_sgservice.size()) { + MNS_LOG_ERROR("Add trans to Chg"); + ChgSrv(vec_chg_sgservice); + } +} + +void MnsWorker::DelSrv(const vector &vec_del_sgservice) { + string str_port; + + vector::const_iterator + it_sgservice = vec_del_sgservice.begin(); + while (it_sgservice != vec_del_sgservice.end()) { + const meituan_mns::SGService &sgservice = *it_sgservice; + + try { + str_port = boost::lexical_cast(sgservice.port); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "sgservice.port " + << sgservice.port); + + ++it_sgservice; + continue; + } + + //TODO grace exit?? + //tcpclient exit will close connection, conninfo exit will clear weight buf + map_ipport_spconninfo_.erase(sgservice.ip + ":" + str_port); + + ++it_sgservice; + } +} + +void MnsWorker::ChgSrv(const vector &vec_chg_sgservice) { + string str_port; + string str_key; + + vector vec_add_sgservice; + + vector::const_iterator + it_sgservice = vec_chg_sgservice.begin(); + while (it_sgservice != vec_chg_sgservice.end()) { + const meituan_mns::SGService &sgservice = *it_sgservice; + + try { + str_port = boost::lexical_cast(sgservice.port); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "sgservice.port " + << sgservice.port); + + ++it_sgservice; + continue; + } + + str_key.assign(sgservice.ip + ":" + str_port); + UnorderedMapStr2SpConnInfoIter + it_map = map_ipport_spconninfo_.find(str_key); + if (it_map == map_ipport_spconninfo_.end()) { + MNS_LOG_WARN("Not find " << str_key << " for appkey " + << sgservice.appkey + << " in map_ipport_spconninfo_, readd it"); + + vec_add_sgservice.push_back(sgservice); + } else { + it_map->second->UptSgservice(sgservice); + } + + ++it_sgservice; + } + + if (vec_add_sgservice.size()) { + MNS_LOG_ERROR("Chg trans to Add"); + AddSrv(vec_add_sgservice); + } +} + +void MnsWorker::OnConn(const muduo::net::TcpConnectionPtr &conn) { + MNS_LOG_INFO(conn->localAddress().toIpPort() << " -> " + << conn->peerAddress().toIpPort() + << " is " + << (conn->connected() ? "UP" + : "DOWN")); + + if (conn->connected()) { + + string str_port; + + try { + str_port = + boost::lexical_cast((conn->peerAddress()).toPort()); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "toPort " + << (conn->peerAddress()).toPort() + << "conn peerAddr " + << (conn->peerAddress()).toIpPort()); + + conn->shutdown(); + return; + } + + //check in map + UnorderedMapIpPort2ConnInfoSP unordered_map_iter = + map_ipport_spconninfo_.find( + (conn->peerAddress()).toIp() + ":" + str_port); + if (MNS_UNLIKELY( + unordered_map_iter == map_ipport_spconninfo_.end())) { + MNS_LOG_ERROR("conn peerAddr " << (conn->peerAddress()).toIpPort() + << " localaddr " + << (conn->localAddress()).toIpPort() + << " NOT find key in map_ipport_spconninfo_"); + + conn->shutdown(); + return; + } + + conn->setTcpNoDelay(true); + + boost::shared_ptr conn_context_ptr = + boost::make_shared(unordered_map_iter->second); + conn->setContext(conn_context_ptr); + + Context4WorkerSharedPtr tmp; + try { + tmp = boost::any_cast(conn->getContext()); + } catch (boost::bad_any_cast e) { + MNS_LOG_ERROR("bad_any_cast:" << e.what()); + return; + } + + //tmp->t_last_conn_time_ = time(0); + + if (MNS_UNLIKELY(1 == atomic_avaliable_conn_num_.incrementAndGet())) { + muduo::MutexLockGuard lock(mutexlock_avaliable_conn_ready_); + cond_avaliable_conn_ready_.notifyAll(); + } + } else { + if (MNS_UNLIKELY((conn->getContext()).empty())) { + MNS_LOG_WARN("conn context empty, maybe shutdown when conn"); + } else { + Context4WorkerSharedPtr sp_context; + try { + sp_context = + boost::any_cast(conn->getContext()); + } catch (boost::bad_any_cast e) { + MNS_LOG_ERROR("bad_any_cast:" << e.what()); + return; + } + + if (!(sp_context->b_highwater) && !(sp_context->b_occupied) + && (0 >= (atomic_avaliable_conn_num_.decrementAndGet()))) { + atomic_avaliable_conn_num_.getAndSet(0); //adjust for safe + + MNS_LOG_WARN("atomic_avaliable_conn_num_ 0"); + } + } + } + + if (g_config.b_use_remote_) { + CheckLocalSgagent(); + } +} + +void MnsWorker::OnMsg(const muduo::net::TcpConnectionPtr &conn, + muduo::net::Buffer *buffer, + muduo::Timestamp receiveTime) { + MNS_LOG_DEBUG((conn->peerAddress()).toIpPort() << " msg received " + << (buffer->toStringPiece()).data() + << " len " + << buffer->readableBytes()); + + if (MNS_UNLIKELY((conn->getContext()).empty())) { + MNS_LOG_ERROR("peer address " << conn->peerAddress().toIpPort() + << " context empty"); + conn->shutdown(); + return; + } + + Context4WorkerSharedPtr sp_context_worker; + try { + sp_context_worker = + boost::any_cast(conn->getContext()); + } catch (boost::bad_any_cast e) { + MNS_LOG_ERROR("bad_any_cast:" << e.what()); + return; + } +} + +TcpClientSharedPtr MnsWorker::GetAvailableConn() { + + TcpClientSharedPtr empty; + + TcpClientWeakPtr wp_tcpcli; + if (ChooseNextReadyConn(&wp_tcpcli)) { + MNS_LOG_ERROR("No candidate connection to send packet"); + return empty; + } + + TcpClientSharedPtr + sp_tcpcli(wp_tcpcli.lock()); //already check valid in ChooseNextReadyConn + string str_port; + + try { + str_port = + boost::lexical_cast((sp_tcpcli->connection()->peerAddress()).toPort()); + } catch (boost::bad_lexical_cast &e) { + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << " ip:" + << (sp_tcpcli->connection()->peerAddress()).toIp() + << " port:" + << (sp_tcpcli->connection()->peerAddress()).toPort()); + return empty; + } + + UnorderedMapIpPort2ConnInfoSP + iter_ipport_spconninfo = map_ipport_spconninfo_.find( + (sp_tcpcli->connection()->peerAddress()).toIp() + ":" + str_port); + if (MNS_UNLIKELY( + iter_ipport_spconninfo == map_ipport_spconninfo_.end())) { + MNS_LOG_ERROR("Not find ip:" + << (sp_tcpcli->connection()->peerAddress()).toIp() + << " port:" + << str_port << " in map_ipport_spconninfo_"); + + return empty; + } + + return sp_tcpcli; +} + +int32_t MnsWorker::GetServiceList(meituan_mns::ProtocolResponse &rsp, const +meituan_mns::ProtocolRequest &request) { + ServerListParamsPtr + params = boost::make_shared(rsp, request); + + size_t sz_queue_size = p_event_loop_->queueSize(); + + if (MNS_UNLIKELY(10 <= sz_queue_size)) { + MNS_LOG_WARN("worker queue size " << sz_queue_size); + } else { + MNS_LOG_DEBUG("worker queue size " << sz_queue_size); + } + + p_event_loop_->runInLoop(boost::bind + (&MnsWorker::OnGetServiceList, this, params)); + //NOT sp_shared_worker_transport_ itself + + bool b_timeout; + double d_wait_secs = 0.0; + const double d_timeout_secs = + static_cast(kI32DefaultTimeoutForReuestMS) / 1000; + muduo::Timestamp timestamp_start = muduo::Timestamp::now(); + + do { + muduo::MutexLockGuard lock(params->mutexlock_conn_ready_); + b_timeout = params->cond_ready_read_.waitForSeconds(d_timeout_secs); + } while (0); + + if (MnsSdkCommon::CheckOverTime(timestamp_start, d_timeout_secs, + &d_wait_secs) && + params->ret_ == -1) { + + params->timeout_ = true; + MNS_LOG_ERROR("GetServiceList time out "); + return -1; + } + + rsp = params->rsp_; + MNS_LOG_INFO("GetServiceList ret:" << params->ret_) + return params->ret_; + +} + +int32_t MnsWorker::RegistService(const meituan_mns::SGService &sgService) { + RegisterParamsPtr params = boost::make_shared(sgService); + + size_t sz_queue_size = p_event_loop_->queueSize(); + + if (MNS_UNLIKELY(10 <= sz_queue_size)) { + MNS_LOG_WARN("worker queue size " << sz_queue_size); + } else { + MNS_LOG_DEBUG("worker queue size " << sz_queue_size); + } + + p_event_loop_->runInLoop(boost::bind + (&MnsWorker::OnRegistService, this, params)); + + bool b_timeout; + double d_wait_secs = 0.0; + const double d_timeout_secs = + static_cast(kI32DefaultTimeoutForReuestMS) / 1000; + muduo::Timestamp timestamp_start = muduo::Timestamp::now(); + + do { + muduo::MutexLockGuard lock(params->mutexlock_conn_ready_); + b_timeout = params->cond_ready_read_.waitForSeconds(d_timeout_secs); + } while (0); + + if (MnsSdkCommon::CheckOverTime(timestamp_start, d_timeout_secs, + &d_wait_secs) && + params->ret_ == -1) { + + params->timeout_ = true; + MNS_LOG_ERROR("RegistService time out "); + return -1; + } + + MNS_LOG_INFO("RegistService ret:" << params->ret_); + return params->ret_; +} + +void MnsWorker::OnGetServiceList(ServerListParamsPtr params) { + MNS_LOG_DEBUG("getServiceListByProtocol begin"); + + if (params->timeout_) { + MNS_LOG_WARN("before get server list timeout just return"); + NotifyGetServiceList(params); + return; + } + + TcpClientSharedPtr conn = GetAvailableConn(); + if (!conn) { + params->ret_ = -1; + MNS_LOG_WARN("get server list No candidate connection to send packet " + "just return"); + NotifyGetServiceList(params); + return; + } + + std::string ip = (conn->connection()->peerAddress()).toIp(); + int16_t port = (conn->connection()->peerAddress()).toPort(); + + ThriftClientHandler *p_handle = InitHandler(ip, port); + if (!p_handle) { + params->ret_ = -1; + MNS_LOG_ERROR("OnGetServiceList failed, get handler fail."); + NotifyGetServiceList(params); + return; + } + + meituan_mns::ServiceAgentClient *thrift_client = + static_cast(p_handle->getClient()); + + if (thrift_client == NULL) { + MNS_LOG_WARN("static cast error"); + params->ret_ = -1; + NotifyGetServiceList(params); + return; + } + + try { + MNS_LOG_DEBUG("getServiceListByProtocol rpc begin"); + thrift_client->getServiceListByProtocol(params->rsp_, + params->resuest_); + params->ret_ = 0; + MNS_LOG_DEBUG("getServiceListByProtocol rpc end && error code=" + << params->rsp_.errcode); + } catch (apache::thrift::TException &tx) { + MNS_LOG_ERROR("getServiceListByProtocol error " << tx.what()); + //异常关闭连接 + p_handle->closeConnection(); + //释放内存 + MNS_SAFE_DELETE(p_handle); + params->ret_ = -1; + NotifyGetServiceList(params); + return; + } + //使用完成,关闭连接 + p_handle->closeConnection(); + //释放内存 + MNS_SAFE_DELETE(p_handle); + NotifyGetServiceList(params); + MNS_LOG_DEBUG("getServiceListByProtocol begin"); + return; +} + +void MnsWorker::NotifyRegistService(RegisterParamsPtr params) { + muduo::MutexLockGuard lock(params->mutexlock_conn_ready_); + params->cond_ready_read_.notifyAll(); +} + +void MnsWorker::NotifyGetServiceList(ServerListParamsPtr params) { + muduo::MutexLockGuard lock(params->mutexlock_conn_ready_); + params->cond_ready_read_.notifyAll(); +} + +void MnsWorker::OnRegistService(RegisterParamsPtr params) { + MNS_LOG_DEBUG("OnRegistService begin"); + if (params->timeout_) { + MNS_LOG_WARN("before get server list timeout just return"); + NotifyRegistService(params); + return; + } + + TcpClientSharedPtr conn = GetAvailableConn(); + + if (!conn) { + params->ret_ = -1; + MNS_LOG_WARN("OnRegistService No candidate connection to send packet " + "just return"); + NotifyRegistService(params); + return; + } + + std::string ip = (conn->connection()->peerAddress()).toIp(); + int16_t port = (conn->connection()->peerAddress()).toPort(); + + ThriftClientHandler *p_handle = InitHandler(ip, port); + if (!p_handle) { + MNS_LOG_ERROR("OnRegistService failed, get handler fail."); + params->ret_ = -1; + NotifyRegistService(params); + return; + } + + meituan_mns::ServiceAgentClient *thrift_client = + static_cast(p_handle->getClient()); + + if (thrift_client == NULL) { + MNS_LOG_WARN("static cast error"); + params->ret_ = -1; + NotifyRegistService(params); + return; + } + + try { + MNS_LOG_DEBUG("OnRegistService rpc begin"); + int ret = thrift_client->registService(params->sgService_); + params->ret_ = ret; + MNS_LOG_DEBUG("OnRegistService rpc end"); + } catch (apache::thrift::TException &tx) { + MNS_LOG_ERROR("OnRegistService error " << tx.what()); + //异常关闭连接 + p_handle->closeConnection(); + //释放内存 + MNS_SAFE_DELETE(p_handle); + params->ret_ = -1; + NotifyRegistService(params); + return; + } + //使用完成,关闭连接 + p_handle->closeConnection(); + //释放内存 + MNS_SAFE_DELETE(p_handle); + + MNS_LOG_DEBUG("OnRegistService end"); + NotifyRegistService(params); + return; +} + +ThriftClientHandler *MnsWorker::InitHandler(const std::string &ip, + const int port) { + ThriftClientHandler *p_handle = new ThriftClientHandler(); + if (p_handle != NULL) { + int ret = + p_handle->init(ip, port, SG_AEGNT_TYPE, false); + if ((ret == 0) && p_handle->m_transport->isOpen()) { + return p_handle; + } else { + MNS_LOG_ERROR("GetHandler init failed! " + << ", ip = " << ip + << ", port = " << port); + MNS_SAFE_DELETE(p_handle); + return NULL; + } + } else { + return NULL; + } +} + +void MnsWorker::Init() { + muduo::Timestamp timestamp_start = muduo::Timestamp::now(); + + muduo::Condition + &cond = getCond_avaliable_conn_ready_(); + muduo::MutexLock &mutexlock = + getMutexlock_avaliable_conn_ready_(); + + const double + d_default_timeout_secs = static_cast(kI32DefaultTimeoutMS) / + 1000; + double d_left_time_sec = 0.0; + bool b_timeout = false; + + while (0 >= getAtomic_avaliable_conn_num_()) {//while, NOT if + MNS_LOG_DEBUG("No good conn for from worker, wait"); + + if (!MnsSdkCommon::CheckOverTime(timestamp_start, + d_default_timeout_secs, + &d_left_time_sec)) { + do { + muduo::MutexLockGuard lock(mutexlock); + b_timeout = cond.waitForSeconds(d_left_time_sec); + } while (0); + + if (b_timeout) { + if (MNS_UNLIKELY(0 < getAtomic_avaliable_conn_num_())) { + MNS_LOG_DEBUG("miss notify, but already get"); + } else { + MNS_LOG_WARN("wait " << d_left_time_sec + << " secs for good conn for timeout, maybe " + "need more time"); + } + return; + } + + if (MNS_UNLIKELY(MnsSdkCommon::CheckOverTime(timestamp_start, + d_default_timeout_secs, + 0))) { + MNS_LOG_WARN(d_default_timeout_secs + << "secs countdown to 0, but no good conn ready, maybe need more time"); + return; + } + } + } + + MNS_LOG_DEBUG( + "wait done, avaliable conn num " << getAtomic_avaliable_conn_num_()); +} diff --git a/sdk/mns-sdk/src/mns_worker.h b/sdk/mns-sdk/src/mns_worker.h new file mode 100644 index 0000000..1317804 --- /dev/null +++ b/sdk/mns-sdk/src/mns_worker.h @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +#ifndef OCTO_OPEN_SOURCE_MNS_WORKER_H_ +#define OCTO_OPEN_SOURCE_MNS_WORKER_H_ + +#include "thrift_client.h" + +namespace mns_sdk { + +class ServerListParams { + public: + ServerListParams(const meituan_mns::ProtocolResponse &rsp, + const meituan_mns::ProtocolRequest &request) : + ret_(-1), + timeout_(false), + rsp_(rsp), + resuest_(request), + cond_ready_read_(mutexlock_conn_ready_) {} + + int ret_; + bool timeout_; + meituan_mns::ProtocolResponse rsp_; + meituan_mns::ProtocolRequest resuest_; + muduo::MutexLock mutexlock_conn_ready_; + muduo::Condition cond_ready_read_; +}; + +class RegisterParams { + public: + RegisterParams(const meituan_mns::SGService &sgService) : + ret_(-1), + timeout_(false), + sgService_(sgService), + cond_ready_read_(mutexlock_conn_ready_) { + } + + int ret_; + bool timeout_; + meituan_mns::SGService sgService_; + muduo::MutexLock mutexlock_conn_ready_; + muduo::Condition cond_ready_read_; +}; + +typedef boost::shared_ptr ServerListParamsPtr; +typedef boost::shared_ptr RegisterParamsPtr; + +struct WeightSort { + bool operator()(const double &a, const double &b) const { + return a > b; + } +}; + +typedef boost::shared_ptr TcpClientSharedPtr; +typedef boost::weak_ptr TcpClientWeakPtr; + +class ConnInfo { + private: + meituan_mns::SGService sgservice_; + TcpClientSharedPtr sp_tcpclient_; + + std::multimap *p_map_weight_tcpclientwp_; + +//for relate to weight index, if not be deleted, safe + std::multimap::iterator + it_map_weight_tcpclientwp_index_; + + public: + ConnInfo(const meituan_mns::SGService &sgservice_tmp, + std::multimap * + p_map_weight_tcpclientwp) : sgservice_(sgservice_tmp), + p_map_weight_tcpclientwp_( + p_map_weight_tcpclientwp) {} + + ~ConnInfo(void) { + if (MNS_UNLIKELY(!p_map_weight_tcpclientwp_)) { + MNS_LOG_ERROR("p_map_weight_tcpclientwp_ NULL"); + } else { + MNS_LOG_INFO("delete appkey " << sgservice_.appkey << " ip: " + << sgservice_.ip << " port: " + << sgservice_.port + << " from weight pool"); + p_map_weight_tcpclientwp_->erase(it_map_weight_tcpclientwp_index_); + } + } + + const meituan_mns::SGService &GetSgservice(void) const { + return sgservice_; + } + + bool CheckConnHealthy(void) const; + + void UptSgservice(const meituan_mns::SGService &sgservice); + + void setSp_tcpclient_(const TcpClientSharedPtr &sp_tcpclient); + + TcpClientSharedPtr &getSp_tcpclient_() { + return sp_tcpclient_; + } + + /*int8_t FetchTcpConnSP(muduo::net::TcpConnectionPtr *p_tcpconn_sp) { + if (sp_tcpclient_.get() && sp_tcpclient_->connection()) { + p_tcpconn_sp->reset((sp_tcpclient_->connection()).get()); + return 0; + } + + LOG_INFO << "sp_tcpclient_ NOT init"; + return -1; + }*/ +}; + +typedef boost::shared_ptr ConnInfoSharedPtr; +typedef boost::weak_ptr ConnInfoWeakPtr; + +struct ConnContext4Worker { + public: + + bool b_highwater; + bool b_occupied; + + ConnInfoWeakPtr wp_conn_info; + + ConnContext4Worker(const ConnInfoSharedPtr &sp_conn_info) + : b_highwater(false), + b_occupied(false), wp_conn_info(sp_conn_info) {} +}; + +typedef boost::shared_ptr Context4WorkerSharedPtr; + +class MnsWorker { + private: + struct CnxtEntry : public muduo::copyable { + MnsWorker *p_worker_; + + explicit CnxtEntry(MnsWorker *parent) + : p_worker_(parent) {} + + ~CnxtEntry(void) { + p_worker_ = NULL; + } + }; + + typedef boost::unordered_map::iterator + UnorderedMapStr2SpConnInfoIter; + + boost::shared_ptr sp_tcpclient_sentinel_; + + muduo::MutexLock mutexlock_avaliable_conn_ready_; + muduo::Condition cond_avaliable_conn_ready_; + + muduo::AtomicInt32 + atomic_avaliable_conn_num_; //exclude disconn/highwater/occupied + + int8_t i8_destructor_flag_; + + char *unzip_buf_; + + muduo::net::InetAddress sentinel_url_addr_; + + boost::unordered_map + map_ipport_sgservice_; //use compare and update svrlist + + boost::shared_ptr sp_sgagent_client_; + + void OnConn4Sentinel(const muduo::net::TcpConnectionPtr &conn); + void OnMsg4Sentinel(const muduo::net::TcpConnectionPtr &conn, + muduo::net::Buffer *buffer, + muduo::Timestamp receiveTime); + + //for common srvlist update + boost::unordered_map + map_ipport_spconninfo_; + + std::multimap + * //ONLY used by conninfo + p_multimap_weight_wptcpcli_; + + typedef boost::unordered_map + ::iterator + UnorderedMapIpPort2ConnInfoSP; + + typedef std::multimap::iterator + MultiMapIter; + + boost::shared_ptr sp_event_thread_; + + muduo::net::EventLoop *p_event_loop_; + + void AddSrv(const std::vector &vec_add_sgservice); + void DelSrv(const std::vector &vec_add_sgservice); + void ChgSrv(const std::vector &vec_add_sgservice); + + void OnConn(const muduo::net::TcpConnectionPtr &conn); + void OnMsg(const muduo::net::TcpConnectionPtr &conn, + muduo::net::Buffer *buffer, + muduo::Timestamp receiveTime); + + void UpdateSvrList + (const std::vector &vec_sgservice); + + void InitWorker(void); + void InitSentinel(void); + void UnInitSentinel(void); + + void CheckLocalSgagent(); + bool CheckLocalSgagentHealth(void); + + int8_t ChooseNextReadyConn(TcpClientWeakPtr *p_wp_tcpcli); + static int8_t CheckRegion(const double &d_weight); + + public: + MnsWorker(); + + void ClearTcpClient(muduo::CountDownLatch *p_clear_countdown) { + MNS_LOG_DEBUG("into worker thread clean resource"); + map_ipport_spconninfo_.clear(); //clear tcpclient, OR may core when + // multiple tcpclient quit + if (sp_tcpclient_sentinel_) { + sp_tcpclient_sentinel_->disconnect(); + sp_tcpclient_sentinel_.reset(); + } + + //p_multimap_weight_wptcpcli_ only need free memory in work thread. + delete p_multimap_weight_wptcpcli_; + p_clear_countdown->countDown(); + } + + virtual ~MnsWorker() { + //set destructor flag + i8_destructor_flag_ = 1; + + muduo::CountDownLatch clear_countdown(1); + p_event_loop_->runInLoop(boost::bind(&MnsWorker::ClearTcpClient, + this, &clear_countdown)); + //wait until end of the destructor + clear_countdown.wait(); + + if (MNS_LIKELY(unzip_buf_)) { + delete unzip_buf_; + } + } + + int32_t GetServiceList(meituan_mns::ProtocolResponse &rsp, + const meituan_mns::ProtocolRequest &request); + + int32_t RegistService(const meituan_mns::SGService &sgService); + + void NotifyRegistService(RegisterParamsPtr params); + + void NotifyGetServiceList(ServerListParamsPtr params); + + void OnGetServiceList(ServerListParamsPtr params); + + void OnRegistService(RegisterParamsPtr params); + + muduo::net::EventLoop *getP_event_loop_(void) const { + return p_event_loop_; + } + + TcpClientSharedPtr GetAvailableConn(); + + int32_t getAtomic_avaliable_conn_num_() { + return atomic_avaliable_conn_num_.get(); + } + + muduo::Condition &getCond_avaliable_conn_ready_() { + return cond_avaliable_conn_ready_; + } + + muduo::MutexLock &getMutexlock_avaliable_conn_ready_(void) { + return mutexlock_avaliable_conn_ready_; + } + + ThriftClientHandler *InitHandler(const std::string &ip, const int port); + + void Init(); +}; +} + +#endif //OCTO_OPEN_SOURCE_MNS_WORKER_H_ diff --git a/sdk/mns-sdk/src/test/CMakeLists.txt b/sdk/mns-sdk/src/test/CMakeLists.txt new file mode 100644 index 0000000..8150ede --- /dev/null +++ b/sdk/mns-sdk/src/test/CMakeLists.txt @@ -0,0 +1,45 @@ +IF (ENABLE_COVERAGE) + SET(CMAKE_CXX_FLAGS "-g -Wall -O0 -fPIC -DMUDUO_STD_STRING -DHAVE_NETINET_IN_H -DGTEST") +ELSE () + SET(CMAKE_CXX_FLAGS "-g -Wall -O2 -fPIC -DMUDUO_STD_STRING -DHAVE_NETINET_IN_H -DGTEST") +ENDIF () +SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") +MESSAGE(STATUS "CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}") + +enable_testing() + +IF (ENABLE_COVERAGE) + include(CodeCoverage) + APPEND_COVERAGE_COMPILER_FLAGS() +ENDIF () +MESSAGE(STATUS "CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}") + +option(MNS_SDK_DOWNLOAD_GTEST "Download and build a fresh copy of googletest. +Requires Internet access." ON) +set(MNS_SDK_SYSTEM_GTEST_SOURCE_DIR "" CACHE PATH "System googletest source +directory.") + +if (MNS_SDK_DOWNLOAD_GTEST) + include(SetupGtest) +elseif (MNS_SDK_SYSTEM_GTEST_SOURCE_DIR) + add_subdirectory("${MNS_SDK_SYSTEM_GTEST_SOURCE_DIR}" "${PROJECT_BINARY_DIR}/system-googletest-build") +else () + message(FATAL_ERROR "Googletest is not available") +endif () + +INCLUDE_DIRECTORIES(SYSTEM ${GTEST_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(SYSTEM ${INCLUDE_ECHO_OUTPUT_PATH}) + +SET(SYSTEM_INCLUDE_PATH /usr/include/) +INCLUDE_DIRECTORIES(SYSTEM ${SYSTEM_INCLUDE_PATH}) +INCLUDE_DIRECTORIES(SYSTEM ${SYSTEM_INCLUDE_PATH}/thrift) +INCLUDE_DIRECTORIES(SYSTEM ${Boost_INCLUDE_DIR}) + +INCLUDE_DIRECTORIES(SYSTEM ${INCLUDE_OUTPUT_PATH}) +LINK_DIRECTORIES(${LIBRARY_OUTPUT_PATH}) + +ADD_EXECUTABLE(mns_thread_test mns_thread_test.cc) +TARGET_LINK_LIBRARIES(mns_thread_test -Xlinker "-(" libmns_sdk.a + ${MUDUO_BASE_LIBRARY} ${MUDUO_NET_LIBRARY} ${MUDUO_HTTP_LIBRARY} + pthread rt uuid ${ZLIB_LIBRARY} ${LOG4CPLUS_LIBRARY} + liboctoidl.a ${THRIFT_LIBRARY} gtest -Xlinker "-)") diff --git a/sdk/mns-sdk/src/test/mns_thread_test.cc b/sdk/mns-sdk/src/test/mns_thread_test.cc new file mode 100644 index 0000000..441c088 --- /dev/null +++ b/sdk/mns-sdk/src/test/mns_thread_test.cc @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include + +#include +#include +#include +#include +#include + +#include + +using namespace std; +using namespace mns_sdk; + +using testing::Types; + +void Job(const vector &vec_add, + const vector &vec_del, + const vector &vec_chg, + const string &appkey) { + cout << "recv add.size " << vec_add.size() << endl; + for (int i = 0; i < static_cast(vec_add.size()); i++) { + cout << "[" << i << "]" << ": " + << MnsSdkCommon::SGService2String(vec_add[i]) << endl; + } + cout << "recv del.size " << vec_del.size() << endl; + for (size_t i = 0; i < vec_del.size(); i++) { + cout << "[" << i << "]" << ": " + << MnsSdkCommon::SGService2String(vec_del[i]) << endl; + } + cout << "recv chg.size " << vec_chg.size() << endl; + for (size_t i = 0; i < vec_chg.size(); i++) { + cout << "[" << i << "]" << ": " + << MnsSdkCommon::SGService2String(vec_chg[i]) << endl; + } + + cout << "appkey" << appkey << endl; +} + +void JobTEST(const vector &vec_add, + const vector &vec_del, + const vector &vec_chg, + const string &appkey) { + cout << "AddUpdateSvrListCallback appkey" << appkey << endl; +} + +TEST(MNSMULTITHREADTEST, HandleZeroReturn) { + InitMNS("/opt/octo.cfg", 10); + boost::function &vec_add, + const vector &vec_del, + const vector &vec_chg, + const string &appkey)> job(boost::bind(&Job, _1, _2, _3, _4)); + EXPECT_EQ(0, StartClient("com.sankuai.inf.newct", + "com.sankuai.inf.newct.client", + "thrift", + "", + job)); + + std::vector svr_list; + EXPECT_EQ(0, getSvrList("com.sankuai.inf.newct", + "com.sankuai.inf.newct.client", + "thrift", + "", + &svr_list)); + EXPECT_TRUE(!svr_list.empty()); + + string err_info = ""; + boost::function &vec_add, + const vector &vec_del, + const vector &vec_chg, + const string &appkey)> job1(boost::bind(&JobTEST, _1, _2, _3, _4)); + EXPECT_EQ(0, + AddUpdateSvrListCallback("com.sankuai.inf.newct", job1, &err_info)); + EXPECT_TRUE(err_info.empty()); + + EXPECT_EQ(0, StartClient("com.sankuai.inf.mnsctest", + "com.sankuai.inf.newct.client", + "thrift", + "", + job)); + + sleep(10); + DestroyMNS(); +} + +void testThreadFunc(muduo::CountDownLatch *p_countdown) { + RUN_ALL_TESTS(); + p_countdown->countDown(); +} + +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + int thread_num = 5; + muduo::CountDownLatch countdown_thread_finish(thread_num); + for (int i = 0; i < thread_num; ++i) { + muduo::net::EventLoopThread *pt = + new muduo::net::EventLoopThread; + + pt->startLoop()->runInLoop(boost::bind(testThreadFunc, + &countdown_thread_finish)); + + cout << endl; + } + countdown_thread_finish.wait(); + std::cout << "test finish" << std::endl; + return 0; +} diff --git a/sdk/mns-sdk/src/thrift_client.cc b/sdk/mns-sdk/src/thrift_client.cc new file mode 100644 index 0000000..1ac6f8f --- /dev/null +++ b/sdk/mns-sdk/src/thrift_client.cc @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include "thrift_client.h" + +namespace mns_sdk { + +ThriftClientHandler::ThriftClientHandler() + : m_client(NULL) { +} +ThriftClientHandler::~ThriftClientHandler() { + if (m_client) { + + closeConnection(); + + if (SG_AEGNT_TYPE == type) { + delete static_cast(m_client); + } else { + MNS_LOG_ERROR("Wrong Type: " << type); + } + } +} +int ThriftClientHandler::init(const std::string &host, + int port, + ProcType proc_type, + bool local) { + m_host = host; + m_port = port; + type = proc_type; + m_socket = + boost::shared_ptr(new apache::thrift::transport::TSocket( + m_host, + m_port)); + m_transport = + boost::shared_ptr(new apache::thrift::transport::TFramedTransport( + m_socket)); + m_protocol = + boost::shared_ptr(new apache::thrift::protocol::TBinaryProtocol( + m_transport)); + int ret = createConnection(); + if (ret != 0) { + MNS_LOG_ERROR("init create connection fail! ret = " << ret); + return ret; + } + //创建成功,置连接标示为未删除 + m_closed = false; + int32_t time_out = 0; + if (NULL == m_client) { + if (SG_AEGNT_TYPE == type) { + if (local) { + time_out = SG_LOCAL_SERVER_CONN_TIMEOUT; + m_socket->setConnTimeout(SG_LOCAL_SERVER_CONN_TIMEOUT); + m_socket->setSendTimeout(SG_LOCAL_SERVER_WRITE_TIMEOUT); + m_socket->setRecvTimeout(SG_LOCAL_SERVER_READ_TIMEOUT); + } else { + time_out = SG_SERVER_CONN_TIMEOUT; + m_socket->setConnTimeout(SG_SERVER_CONN_TIMEOUT); + m_socket->setSendTimeout(SG_SERVER_WRITE_TIMEOUT); + m_socket->setRecvTimeout(SG_SERVER_READ_TIMEOUT); + } + + m_client = + static_cast(new meituan_mns::ServiceAgentClient(m_protocol)); + } else { + m_client = NULL; + } + } + MNS_LOG_INFO("connect to ThriftClientHandler ip: " << m_host + << " port is : " << m_port + << " type is : " + << proc_type + << ", timeout = " + << time_out); + srand(static_cast(time(0))); + return 0; +} +//check连接 +int ThriftClientHandler::checkConnection() { + if (!m_transport->isOpen()) { + return ERR_CHECK_CONNECTION; + } + return 0; +} +//创建连接 +int ThriftClientHandler::createConnection() { + int count = 0; + bool flag = true; + //先check连接是否可用 + int ret = checkConnection(); + //如果连接不可用,则重新建立连接 + while ((ret != 0) && count < CONNECTION_RETRY_TIMES) { + count++; + try { + m_transport->open(); + flag = true; + MNS_LOG_INFO("reconnect to ok! ip: " << m_host.c_str() + << " port is : " << m_port); + } + catch (apache::thrift::TException &e) { + flag = false; + MNS_LOG_ERROR("reconnect to failed ip: " << m_host.c_str() + << " port is : " << m_port + << ", error : " << e.what()); + } + //获取连接状态 + ret = checkConnection(); + } + if (flag && ret == 0) { + return 0; + } else { + MNS_LOG_ERROR("ThriftClientHandler failed! ret = " + << ret << "flag = " << flag); + return ERR_CREATE_CONNECTION; + } +} +//关闭连接 +int ThriftClientHandler::closeConnection() { + if (!m_closed) { + //置连接关闭标示为true,防止多次close + m_closed = true; + try { + MNS_LOG_INFO("begin close connection !"); + if (NULL != m_transport) { + m_transport->close(); + } else { + MNS_LOG_ERROR("m_transport is NULL when to close"); + } + } + catch (apache::thrift::TException &e) { + MNS_LOG_ERROR("ERR, close connection fail! error : " << e.what()); + return ERR_CLOSE_CONNECTION; + } + } + return 0; +} +//check handler对应的连接是否可用 +int ThriftClientHandler::checkHandler() { + //先check连接 + int ret = checkConnection(); + if (ret != 0) { + MNS_LOG_ERROR(" connection lost, begin close! ret = " << ret); + //关闭连接 + ret = closeConnection(); + if (ret != 0) { + MNS_LOG_ERROR(" connection lost, close fail! ret = " << ret); + return ret; + } + //重新创建连接 + ret = createConnection(); + if (ret != 0) { + MNS_LOG_ERROR(" re-create connection fail! ret = " << ret); + return ret; + } + //创建成功,修改连接标示为连接未被关闭 + m_closed = false; + } + return 0; +} +} diff --git a/sdk/mns-sdk/src/thrift_client.h b/sdk/mns-sdk/src/thrift_client.h new file mode 100644 index 0000000..ec347df --- /dev/null +++ b/sdk/mns-sdk/src/thrift_client.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_THRIFT_CLIENT_H_ +#define OCTO_OPEN_SOURCE_THRIFT_CLIENT_H_ + +#include "util/mns_sdk_common.h" + +namespace mns_sdk { + +enum ProcType { + SG_AEGNT_TYPE, + UNKNOW_TYPE, +}; + +class ThriftClientHandler { + public: + ThriftClientHandler(); + ~ThriftClientHandler(); + int init(const std::string &host, int port, ProcType proc_type, bool local + = true); + int checkConnection(); + int createConnection(); + int closeConnection(); + int checkHandler(); + void *getClient() { + return m_client; + } + bool m_closed; + std::string m_host; + int m_port; + void *m_client; + boost::shared_ptr m_socket; + boost::shared_ptr m_transport; + boost::shared_ptr m_protocol; + ProcType type; +}; +}; +#endif // OCTO_OPEN_SOURCE_THRIFT_CLIENT_H_ \ No newline at end of file diff --git a/sdk/mns-sdk/src/util/mns_common.h b/sdk/mns-sdk/src/util/mns_common.h new file mode 100644 index 0000000..70e917a --- /dev/null +++ b/sdk/mns-sdk/src/util/mns_common.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_UTIL_MNS_COMMON_H_ +#define OCTO_OPEN_SOURCE_UTIL_MNS_COMMON_H_ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "mns_log.h" + +#define MNS_SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define MNS_SAFE_FREE(p) { if(p) { free(p); (p)=NULL; } } +#define MNS_SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define MNS_SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + +#define kDRetryIntervalSec 10.0 +#define kI32DefaultTimeoutMS 5000 +#define kI32DefaultTimeoutForReuestMS 100 + +typedef enum { + PROD, STAGING, DEV, PPE, TEST +} Appenv; + +#endif // OCTO_OPEN_SOURCE_UTIL_MNS_COMMON_H_ diff --git a/sdk/mns-sdk/src/util/mns_config.cc b/sdk/mns-sdk/src/util/mns_config.cc new file mode 100644 index 0000000..ae02d3d --- /dev/null +++ b/sdk/mns-sdk/src/util/mns_config.cc @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "mns_config.h" + +using namespace mns_sdk; + +MnsConfig mns_sdk::g_config; + +MnsConfig::MnsConfig() : + url_port_(80),local_chrion_port_(-1), b_use_remote_(false) { +} + +int MnsConfig::InitAppnev(const std::map + &config_map) { + string env; + std::map::const_iterator it = config_map.find + ("env"); + if (it != config_map.end()) { + env = it->second; + } else { + MNS_LOG_ERROR("have no env config."); + return -1; + } + + Appenv mAppenv; + // 优先解释env字段,无法解释时,再解释deployenv。请勿优化以下if语句 + if ("prod" == env) { + mAppenv = PROD; + } else if ("staging" == env) { + mAppenv = STAGING; + } else if ("dev" == env) { + mAppenv = DEV; + } else if ("ppe" == env) { + mAppenv = PPE; + } else if ("test" == env) { + mAppenv = TEST; + } else { + MNS_LOG_ERROR( + "str_env_ is empty, fetch from appenv file failed, Please contact with SRE to handle this problem. "); + return -1; + } + + switch (mAppenv) { + case PROD:str_env_ = "prod"; + str_octo_env_ = "prod"; + enum_onoffline_env_ = ONLINE; + MNS_LOG_INFO("success to init host env = prod (online)"); + break; + case STAGING:str_env_ = "stage"; + str_octo_env_ = "stage"; + enum_onoffline_env_ = ONLINE; + MNS_LOG_INFO("success to init host env = staging (online)"); + break; + case DEV:str_env_ = "prod"; + str_octo_env_ = "dev"; + enum_onoffline_env_ = OFFLINE; + MNS_LOG_INFO("success to init host env = dev (offline)"); + break; + case PPE:str_env_ = "stage"; + str_octo_env_ = "ppe"; + enum_onoffline_env_ = OFFLINE; + MNS_LOG_INFO("success to init host env = ppe (offline)"); + break; + case TEST:str_env_ = "test"; + str_octo_env_ = "test"; + enum_onoffline_env_ = OFFLINE; + MNS_LOG_INFO("success to init host env = test (offline)"); + break; + default: MNS_LOG_ERROR("fail to init host env."); + return -1; + } + + MNS_LOG_DEBUG("enum_onoffline_env_ " << enum_onoffline_env_); + return 0; +} + +void MnsConfig::GetHostIPInfo(void) { + char ip[INET_ADDRSTRLEN] = {0}; + + MnsSdkCommon::IntranetIp(ip); + if (MNS_UNLIKELY(0 == strlen(ip))) { + MNS_LOG_WARN("Cannot get local ip, wait 5 secs"); + muduo::CurrentThread::sleepUsec(5000 * 1000); + + MnsSdkCommon::IntranetIp(ip); + } + + if (MNS_UNLIKELY(0 == strlen(ip))) { + MNS_LOG_WARN("After wait 5 secs, still cannot get local ip, set to be 127" + ".0.0.1"); + str_local_ip_.assign("127.0.0.1"); + } else { + str_local_ip_.assign(ip); + MNS_LOG_INFO("local ip " << str_local_ip_); + } + + char hostCMD[64] = {0}; + strncpy(hostCMD, "host ", 5); + strncpy(hostCMD + 5, ip, INET_ADDRSTRLEN); + + FILE *fp = popen(hostCMD, "r"); + char hostInfo[256] = {0}; + + if (MNS_LIKELY(!fgets(hostInfo, 256, fp))) { + int iRet = ferror(fp); + if (MNS_UNLIKELY(iRet)) { + MNS_LOG_ERROR("fgets error, iRet " << iRet); + pclose(fp); + return; + } + } + hostInfo[strlen(hostInfo) - 1] = '\0'; + + str_host_.assign(hostInfo); + str_host_.assign(MnsSdkCommon::strToLower(str_host_)); + MnsSdkCommon::replace_all_distinct(" ", "%20", &str_host_); + MNS_LOG_INFO("host info: " << hostInfo); + + pclose(fp); + memset(hostCMD, 0, sizeof(hostCMD)); + + strncpy(hostCMD, "hostname ", 9); + fp = popen(hostCMD, "r"); + char hostname[256] = {0}; + if (MNS_LIKELY(!fgets(hostname, 256, fp))) { + int iRet = ferror(fp); + if (MNS_UNLIKELY(iRet)) { + MNS_LOG_ERROR("fgets error, iRet " << iRet); + pclose(fp); + return; + } + } + + hostname[strlen(hostname) - 1] = '\0'; //del line token + + str_hostname_.assign(hostname); + str_hostname_.assign(MnsSdkCommon::strToLower(str_hostname_)); + MnsSdkCommon::replace_all_distinct(" ", "%20", &str_hostname_); + MNS_LOG_INFO("host name: " << hostname); + pclose(fp); +} + +int MnsConfig::LoadConfig(const std::string &str_file_path) { + + std::map str_str_map; + string deployenv_str; + string env_str; + ifstream confg_fin; + try { + confg_fin.open(str_file_path.c_str(), std::ios::in); + if (!confg_fin.is_open()) { + MNS_LOG_ERROR("Failed to open appenv file, Maybe file is not exist" + << str_file_path); + return -1; + } else { + string buffer_str; + while (getline(confg_fin, buffer_str) + && (env_str.empty() || deployenv_str.empty())) { + size_t pos = buffer_str.find_first_of("="); + if (string::npos != pos) { + string key = buffer_str.substr(0, pos); + string value = buffer_str.substr(pos + 1); + boost::trim(key); + boost::trim(value); + str_str_map[key] = value; + } + buffer_str.clear(); + } + } + confg_fin.close(); + } catch (exception &e) { + confg_fin.close(); + MNS_LOG_ERROR("fail to load " + << str_file_path + << "OR fetch deployenv/appenv failed, reason: " + << e.what()); + return -1; + } + + if (InitAppnev(str_str_map) != 0) { + MNS_LOG_ERROR("InitAppnev failed "); + } + + if (str_str_map.find("mns_url") != str_str_map.end()) { + url_ = str_str_map["mns_url"]; + + size_t pos = url_.find("http://"); + if(pos != std::string::npos){ + url_ = url_.substr(pos + 7); + } + + pos = url_.find(":"); + if(pos != std::string::npos){ + std::string temp = url_.substr(pos +1); + size_t pos2 = temp.find("/"); + temp = temp.substr(0, pos2); + + + try { + url_port_ = boost::lexical_cast(temp); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" + << e.what() << "url_: " << temp); + url_port_ = 80; + } + + url_ = url_.substr(0, pos); + } + + MNS_LOG_INFO("url host:" << url_ << " port:" << url_port_); + } else { + MNS_LOG_ERROR("have no mns_url config."); + } + + if (str_str_map.find("sgagent_appkey") != str_str_map.end()) { + chrion_appkey_ = str_str_map["sgagent_appkey"]; + } else { + MNS_LOG_ERROR("have no chrion_appkey config."); + } + + if (str_str_map.find("sg_sentinel_appkey") != str_str_map.end()) { + chrion_sentienl_appkey_ = str_str_map["sg_sentinel_appkey"]; + } else { + MNS_LOG_ERROR("have no sentienl_appkey config."); + } + + if (str_str_map.find("idc_path") != str_str_map.end()) { + str_idc_path_ = str_str_map["idc_path"]; + } else { + MNS_LOG_ERROR("have no idc_path config."); + } + + if (str_str_map.find("port") != str_str_map.end()) { + local_chrion_port_ = atoi(str_str_map["port"].c_str()); + } else { + MNS_LOG_ERROR("have no port config."); + } + + GetHostIPInfo(); + + if (str_env_.empty() || url_.empty() || str_octo_env_.empty() || + chrion_sentienl_appkey_.empty()) { + MNS_LOG_ERROR("b_use_remote_. false"); + b_use_remote_ = false; + } else { + MNS_LOG_INFO("b_use_remote_. true"); + str_sentinel_http_request_.assign( + "GET /api/servicelist?appkey=" + g_config.chrion_sentienl_appkey_ + + "&env=" + g_config.str_env_ + + "&host=" + g_config.str_host_ + "&hostname=" + + g_config.str_hostname_ + "&ip=" + g_config.str_local_ip_ + " " + "HTTP/1.1\r\nHost: " + g_config.url_ + "\r\n\r\n"); + b_use_remote_ = true; + } + + if (local_chrion_port_ == -1) { + MNS_LOG_INFO("port is unknow. failed"); + return -1; + } + + str_local_chrion_port_ = boost::lexical_cast(local_chrion_port_); + return 0; +} diff --git a/sdk/mns-sdk/src/util/mns_config.h b/sdk/mns-sdk/src/util/mns_config.h new file mode 100644 index 0000000..b48288a --- /dev/null +++ b/sdk/mns-sdk/src/util/mns_config.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_MNS_SDK_SRC_UTIL_MNS_CONFIG_H_ +#define OCTO_OPEN_SOURCE_MNS_SDK_SRC_UTIL_MNS_CONFIG_H_ + +#include "mns_sdk_common.h" + + +namespace mns_sdk { + +enum ONOFFLINE { + ONLINE, + OFFLINE, +}; + +class MnsConfig { + public: + MnsConfig(); + int LoadConfig(const std::string &str_file_path); + + public: + int InitAppnev(const std::map &config_map); + + void GetHostIPInfo(); + + std::string str_env_; + std::string str_octo_env_; + int enum_onoffline_env_; + + std::string url_; + uint16_t url_port_; + std::string chrion_appkey_; + std::string chrion_sentienl_appkey_; + std::string str_idc_path_; + std::string str_local_chrion_port_; + int local_chrion_port_; + + bool b_use_remote_; + + std::string str_local_ip_; + std::string str_hostname_; + std::string str_host_; + + std::string str_sentinel_http_request_; +}; + +extern mns_sdk::MnsConfig g_config; +} // namespace mns_sdk + + + + +#endif // OCTO_OPEN_SOURCE_MNS_SDK_SRC_UTIL_MNS_CONFIG_H_ diff --git a/sdk/mns-sdk/src/util/mns_log.cc b/sdk/mns-sdk/src/util/mns_log.cc new file mode 100644 index 0000000..7c26e0f --- /dev/null +++ b/sdk/mns-sdk/src/util/mns_log.cc @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "mns_log.h" + +namespace mns_sdk { + +Logger debug_instance = + log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("debug")); +Logger info_instance = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("info")); +Logger warn_instance = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("warn")); +Logger error_instance = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("error")); +Logger fatal_instance = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("fatal")); + +// non root Logger +Logger stat_instance = + log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("statLogger")); + +} // namespace mns_sdk diff --git a/sdk/mns-sdk/src/util/mns_log.h b/sdk/mns-sdk/src/util/mns_log.h new file mode 100644 index 0000000..64588e5 --- /dev/null +++ b/sdk/mns-sdk/src/util/mns_log.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_MNS_SDK_SRC_UTIL_MNS_LOG_H_ +#define OCTO_OPEN_SOURCE_MNS_SDK_SRC_UTIL_MNS_LOG_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mns_sdk { + +using std::auto_ptr; +using log4cplus::Logger; +using log4cplus::ConsoleAppender; +using log4cplus::FileAppender; +using log4cplus::Appender; +using log4cplus::Layout; +using log4cplus::PatternLayout; +using log4cplus::helpers::SharedObjectPtr; + +extern Logger debug_instance; +extern Logger info_instance; +extern Logger warn_instance; +extern Logger error_instance; +extern Logger fatal_instance; +extern Logger stat_instance; + +#define MNS_LOG_DEBUG(debugContent) \ + { LOG4CPLUS_DEBUG(debug_instance, debugContent); } +#define MNS_LOG_INFO(infoContent) \ + { LOG4CPLUS_INFO(info_instance, infoContent); } +#define MNS_LOG_WARN(warnContent) \ + { LOG4CPLUS_WARN(warn_instance, warnContent); } +#define MNS_LOG_ERROR(errorContent) \ + { LOG4CPLUS_ERROR(error_instance, errorContent); } +#define MNS_LOG_FATAL(fatalContent) \ + { LOG4CPLUS_ERROR(fatal_instance, fatalContent); } +#define MNS_LOG_STAT(statContent) \ + { LOG4CPLUS_INFO(stat_instance, statContent); } + +} // namespace mns_sdk + +#endif // OCTO_OPEN_SOURCE_MNS_SDK_SRC_UTIL_MNS_LOG_H_ diff --git a/sdk/mns-sdk/src/util/mns_sdk_common.cc b/sdk/mns-sdk/src/util/mns_sdk_common.cc new file mode 100644 index 0000000..0ccf074 --- /dev/null +++ b/sdk/mns-sdk/src/util/mns_sdk_common.cc @@ -0,0 +1,751 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "mns_sdk_common.h" + +namespace mns_sdk { + +extern mns_sdk::MnsConfig g_config; + +const double MnsSdkCommon::kDFirstRegionMin = 1.0; +const double MnsSdkCommon::kDSecondRegionMin = 0.001; + +static const int hex_table[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 0, 0, 0, 0, 0, 0, + 0, 10, 11, 12, 13, 14, 15, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 10, + 11, 12, 13, 14, 15}; + +MnsSdkCommon::MnsSdkCommon(void) { +} + +string MnsSdkCommon::SGService2String(const meituan_mns::SGService &sgservice) { + string str_ret + ("appkey:" + sgservice.appkey + " version:" + sgservice.version + " ip:" + + sgservice.ip); + + string str_tmp; + + try { + str_ret.append(" port:" + boost::lexical_cast(sgservice.port)); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "sgservice.port : " + << sgservice.port); + } + + try { + str_ret.append( + " weight:" + boost::lexical_cast(sgservice.weight)); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "sgservice.weight : " + << sgservice.weight); + } + + try { + str_ret.append( + " status:" + boost::lexical_cast(sgservice.status)); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "sgservice.status : " + << sgservice.status); + } + + try { + str_ret.append(" role:" + boost::lexical_cast(sgservice.role)); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "sgservice.role : " + << sgservice.role); + } + + try { + str_ret.append( + " envir:" + boost::lexical_cast(sgservice.envir)); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "sgservice.envir : " + << sgservice.envir); + } + + try { + str_ret.append(" lastUpdateTime:" + + boost::lexical_cast(sgservice.lastUpdateTime)); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "sgservice.lastUpdateTime : " + << sgservice.lastUpdateTime); + } + + try { + str_ret.append( + " fweight:" + boost::lexical_cast(sgservice.fweight)); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "sgservice.fweight : " + << sgservice.fweight); + } + + try { + str_ret.append(" serverType:" + + boost::lexical_cast(sgservice.serverType)); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "sgservice.serverType : " + << sgservice.serverType); + } + + return str_ret; +} + +int8_t MnsSdkCommon::ParseSentineSgagentList(const string &str_req, + vector *p_vec_sgservice) { + rapidjson::Document reader; + if ((reader.Parse(str_req.c_str())).HasParseError()) { + MNS_LOG_WARN("json parse string " << str_req << " failed"); + return -1; //maybe NOT error + } + + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + reader.Accept(writer); + MNS_LOG_DEBUG("receive body " << string(buffer.GetString())); + + int i_ret; + if (FetchInt32FromJson("ret", reader, &i_ret)) { + return -1; + } + MNS_LOG_DEBUG("i_ret " << i_ret); + + if (200 != i_ret) { + MNS_LOG_ERROR("fetch santine sgagent list failed, i_ret " << i_ret); + return -1; + } + + rapidjson::Value::MemberIterator it_data; + if (FetchJsonValByKey4Doc(reader, "data", &it_data) + || !((it_data->value).IsObject())) { + MNS_LOG_ERROR("FetchJsonValByKey4Doc Wrong OR data is NOT object"); + return -1; + } + + rapidjson::Value &data_val = it_data->value; + + rapidjson::Value::MemberIterator it; + if (FetchJsonValByKey4Val(data_val, "serviceList", &it)) { + return -1; + } + + rapidjson::Value &srv_list = it->value; + if (!(srv_list.IsArray())) { + MNS_LOG_ERROR("srv_list NOT array"); + return -1; + } + + rapidjson::Document::MemberIterator itr_sing; + for (rapidjson::Value::ValueIterator itr = srv_list.Begin(); + itr != srv_list.End(); ++itr) { + meituan_mns::SGService sgservice; + const rapidjson::Value &srvlist_info = *itr; + + if (FetchJsonValByKey4Val(const_cast(srvlist_info), + "appkey", + &itr_sing) + || !((itr_sing->value).IsString())) { + MNS_LOG_ERROR("appkey NOT EXIST OR NOT string OR NOT "); + continue; + } + + //sgservice.appkey.assign((itr_sing->value).GetString()); + sgservice.appkey.assign(g_config.chrion_appkey_); //replace to be sgagent appkey!! + + if (FetchJsonValByKey4Val(const_cast(srvlist_info), + "version", + &itr_sing) + || !((itr_sing->value).IsString())) { + MNS_LOG_ERROR("version NOT EXIST OR NOT string"); + continue; + } + + sgservice.version.assign((itr_sing->value).GetString()); + + if (FetchJsonValByKey4Val(const_cast(srvlist_info), + "ip", + &itr_sing) + || !((itr_sing->value).IsString())) { + MNS_LOG_ERROR("version NOT EXIST OR NOT string"); + continue; + } + + sgservice.ip.assign((itr_sing->value).GetString()); + + if (FetchJsonValByKey4Val(const_cast(srvlist_info), + "port", + &itr_sing) + || !((itr_sing->value).IsInt())) { + MNS_LOG_ERROR("version NOT EXIST OR NOT int"); + continue; + } + + sgservice.port = (itr_sing->value).GetInt(); + + if (FetchJsonValByKey4Val(const_cast(srvlist_info), + "weight", + &itr_sing) + || !((itr_sing->value).IsInt())) { + MNS_LOG_ERROR("weight NOT EXIST OR NOT int"); + continue; + } + + sgservice.weight = (itr_sing->value).GetInt(); + + if (FetchJsonValByKey4Val(const_cast(srvlist_info), + "status", + &itr_sing) + || !((itr_sing->value).IsInt())) { + MNS_LOG_ERROR("status NOT EXIST OR NOT int"); + continue; + } + + sgservice.status = (itr_sing->value).GetInt(); + + if (FetchJsonValByKey4Val(const_cast(srvlist_info), + "role", + &itr_sing) + || !((itr_sing->value).IsInt())) { + MNS_LOG_ERROR("role NOT EXIST OR NOT int"); + continue; + } + + sgservice.role = (itr_sing->value).GetInt(); + + if (FetchJsonValByKey4Val(const_cast(srvlist_info), + "env", + &itr_sing) + || !((itr_sing->value).IsInt())) { + MNS_LOG_ERROR("envir NOT EXIST OR NOT int"); + continue; + } + + sgservice.envir = (itr_sing->value).GetInt(); + + if (FetchJsonValByKey4Val(const_cast(srvlist_info), + "lastUpdateTime", + &itr_sing) + || !((itr_sing->value).IsInt())) { + MNS_LOG_ERROR("lastUpdateTime NOT EXIST OR NOT int"); + continue; + } + + sgservice.lastUpdateTime = (itr_sing->value).GetInt(); + + if (FetchJsonValByKey4Val(const_cast(srvlist_info), + "fweight", + &itr_sing) + || !((itr_sing->value).IsDouble())) { + MNS_LOG_ERROR("fweight NOT EXIST OR NOT double"); + continue; + } + + sgservice.fweight = (itr_sing->value).GetDouble(); + + if (FetchJsonValByKey4Val(const_cast(srvlist_info), + "serverType", + &itr_sing) + || !((itr_sing->value).IsInt())) { + MNS_LOG_ERROR("serverType NOT EXIST OR NOT int"); + continue; + } + + sgservice.serverType = (itr_sing->value).GetInt(); + MNS_LOG_DEBUG("sgservice content: " << SGService2String(sgservice)); + + p_vec_sgservice->push_back(sgservice); + } + + return 0; +} + +int MnsSdkCommon::Hex2Decimal(const char *begin, const char *end) { + int iret = 0; + char *pos = const_cast(begin); + while (pos != end) { + iret = (iret << 4) | hex_table[static_cast(*pos)]; + pos++; + } + + return iret; +} + +void MnsSdkCommon::ParseHttpChunkData(muduo::net::Buffer *pBuf, + muduo::net::HttpContext *pContext) { + char kCRLF[] = "\r\n"; + const char *crlf = std::search(pBuf->peek(), + static_cast( pBuf->beginWrite()), + kCRLF, + kCRLF + 2); + if (pBuf->beginWrite() == crlf) { + MNS_LOG_DEBUG("NOT enough chunk length"); + return; + } + + uint32_t udwSizeLen = static_cast(crlf - pBuf->peek()); + MNS_LOG_DEBUG("udwSizeLen " << udwSizeLen); + + //transfer hex to int + uint32_t udwLen = static_cast(Hex2Decimal(pBuf->peek(), crlf)); + MNS_LOG_DEBUG("udwLen " << udwLen); + + if (0 == udwLen) { + char kDoubleCRLF[] = "\r\n\r\n"; + const char *doubleCrlf = std::search(crlf, + static_cast( pBuf->beginWrite()), + kDoubleCRLF, + kDoubleCRLF + 4); + if (pBuf->beginWrite() == doubleCrlf) { + MNS_LOG_DEBUG("NOT enough chunk length"); + return; + } + + MNS_LOG_DEBUG("chunk data recv completely!"); + + pBuf->retrieveUntil(doubleCrlf + 4); + pContext->receiveBody(); //END + + return; + } + + //assume NO other data but size/CRLF/data + if (pBuf->readableBytes() + < static_cast(udwSizeLen + 2 + udwLen + + 2)) { //size+CRLF+len+CRLF + MNS_LOG_DEBUG("NOT enough chunk length"); + return; + } + + muduo::net::HttpRequest &request = pContext->request(); + + if (0 < request.body().size()) { //append body + string strTmp(request.body()); + strTmp.append(crlf + 2, udwLen); + request.setBody(strTmp.c_str(), strTmp.c_str() + strTmp.size()); + } else { + request.setBody(crlf + 2, crlf + 2 + udwLen); + } + + pBuf->retrieve(udwSizeLen + 2 + udwLen + 2); + + if (pBuf->readableBytes()) { + ParseHttpChunkData(pBuf, pContext); //recursion!! + } +} + +bool MnsSdkCommon::ParseHttpRequest(uint32_t *pudwWantLen, + muduo::net::Buffer *buf, + muduo::net::HttpContext *context, + muduo::Timestamp receiveTime) { + bool ok = true; + bool hasMore = true; + uint32_t udwBodyLen = 0; + string strBodyLen; + + while (hasMore) { + if (context->expectRequestLine()) { + const char *crlf = buf->findCRLF(); + if (crlf) { + context->request().setReceiveTime(receiveTime); + buf->retrieveUntil(crlf + 2); + context->receiveRequestLine(); + } else { + hasMore = false; + } + } else if (context->expectHeaders()) { + const char *crlf = buf->findCRLF(); + if (crlf) { + const char *colon = std::find(buf->peek(), crlf, ':'); + if (colon != crlf) { + context->request().addHeader(buf->peek(), colon, crlf); + } else { + //print header + map::const_iterator + it = (context->request()).headers().begin(); + while (it != (context->request()).headers().end()) { + MNS_LOG_DEBUG("key " << it->first << " value " << it->second); + it++; + } + + strBodyLen = (context->request()).getHeader("Content-Length"); + if (0 == strBodyLen.size()) { + MNS_LOG_DEBUG("No body length"); + + // empty line, end of header + context->receiveAll(); + hasMore = false; + } else { + + try { + udwBodyLen = boost::lexical_cast(strBodyLen); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_DEBUG("boost::bad_lexical_cast :" << e.what() + << "strBodyLen : " + << strBodyLen); + + return false; + } + + MNS_LOG_DEBUG("udwBodyLen " << udwBodyLen); + context->receiveHeaders(); + } + } + + if ("\r\n\r\n" == string(crlf, 4)) { //two "/r/n" means header over + buf->retrieveUntil(crlf + 2 + 2); + + strBodyLen = (context->request()).getHeader("Content-Length"); + if (0 == strBodyLen.size()) { + string strTransEncode + ((context->request()).getHeader("Transfer-Encoding")); + if (string::npos == strTransEncode.find("chunked")) { + MNS_LOG_DEBUG("No body length and NOT chunk data"); + + // empty line, end of header + context->receiveAll(); + hasMore = false; + } else { + MNS_LOG_DEBUG("chunk data, NO body length"); + context->receiveHeaders(); + } + } else { + + try { + udwBodyLen = boost::lexical_cast(strBodyLen); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "strBodyLen : " + << strBodyLen); + + return false; + } + + MNS_LOG_DEBUG("udwBodyLen " << udwBodyLen); + context->receiveHeaders(); + } + } else { + buf->retrieveUntil(crlf + 2); + } + } else { + hasMore = false; + } + } else if (context->expectBody()) { + hasMore = false; //whatever, this is end + + strBodyLen = (context->request()).getHeader("Content-Length"); + if (0 < strBodyLen.size()) { + + try { + udwBodyLen = boost::lexical_cast(strBodyLen); + } catch (boost::bad_lexical_cast &e) { + + MNS_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "strBodyLen : " + << strBodyLen); + + return false; + } + + MNS_LOG_DEBUG("udwBodyLen " << udwBodyLen); + + if (MNS_UNLIKELY(0 == udwBodyLen)) { + MNS_LOG_WARN("Content-Length 0, maybe Bad.Request"); + context->receiveBody(); + } else { + if (buf->readableBytes() >= udwBodyLen) { //enough + //string strTmp(buf->peek() + 12, buf->peek() + udwBodyLen - 17); + //strTmp = UrlDecode(strTmp); + (context->request()).setBody(buf->peek(), + buf->peek() + udwBodyLen); + MNS_LOG_DEBUG("body is " << (context->request()).body()); + + context->receiveBody(); + buf->retrieve(udwBodyLen); + } + } + } else { + string + strTransEncode + ((context->request()).getHeader("Transfer-Encoding")); + if (string::npos == strTransEncode.find("chunked")) { + MNS_LOG_ERROR("NO content length, NOT chunk"); + return false; + } + + ParseHttpChunkData(buf, context); + } + } + } + + return ok; +} + +int MnsSdkCommon::Httpgzdecompress(Byte *zdata, uLong nzdata, + Byte *data, uLong *ndata) { + int err = 0; + z_stream d_stream = {0}; /* decompression stream */ + static char dummy_head[2] = + { + 0x8 + 0x7 * 0x10, + (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF, + }; + d_stream.zalloc = reinterpret_cast(0); + d_stream.zfree = reinterpret_cast(0); + d_stream.opaque = reinterpret_cast(0); + d_stream.next_in = zdata; + d_stream.avail_in = 0; + d_stream.next_out = data; + if (inflateInit2(&d_stream, 47) != Z_OK) return -1; + while (d_stream.total_out < *ndata && d_stream.total_in < nzdata) { + d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ + if ((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_STREAM_END) break; + if (err != Z_OK) { + if (err == Z_DATA_ERROR) { + d_stream.next_in = reinterpret_cast(dummy_head); + d_stream.avail_in = sizeof(dummy_head); + if ((inflate(&d_stream, Z_NO_FLUSH)) != Z_OK) { + return -1; + } + } else return -1; + } + } + if (inflateEnd(&d_stream) != Z_OK) return -1; + *ndata = d_stream.total_out; + return 0; +} + +string MnsSdkCommon::strToLower(const string &str_tmp) { + string str_lower(str_tmp); + transform(str_lower.begin(), str_lower.end(), str_lower.begin(), ::tolower); + + return str_lower; +} + +void MnsSdkCommon::replace_all_distinct(const string &old_value, + const string &new_value, + string *p_str) { + for (string::size_type pos(0); pos != string::npos; + pos += new_value.length()) { + if ((pos = p_str->find(old_value, pos)) != string::npos) + p_str->replace(pos, old_value.length(), new_value); + else break; + } +} + +int8_t MnsSdkCommon::FetchInt32FromJson(const string &strKey, + rapidjson::Value &data_single, + int32_t *p_i32_value) { + rapidjson::Value::MemberIterator it; + if (FetchJsonValByKey4Val(data_single, strKey, &it)) { + MNS_LOG_ERROR("NO " << strKey << " exist"); + return -1; + } + + if (!((it->value).IsInt())) { + MNS_LOG_ERROR(strKey << " NOT int32"); + return -1; + } + + *p_i32_value = (it->value).GetInt(); + MNS_LOG_DEBUG(strKey << " = " << *p_i32_value); + + return 0; +} + +int MnsSdkCommon::FetchJsonValByKey4Doc(rapidjson::Document &reader, + const string &strKey, + rapidjson::Document::MemberIterator *pitr) { + *pitr = reader.FindMember(strKey.c_str()); + if (*pitr == reader.MemberEnd()) { + MNS_LOG_WARN("No " << strKey); + /*SEND_LOG_ERROR("coral.interface.error",7338731, ("No " + strKey).c_str() + ,4, -1, ("No " + strKey).c_str() );*/ + return -1; + } + + if ("content" != strKey && CheckEmptyJsonStringVal(*pitr)) { + MNS_LOG_WARN(strKey << " has empty string value"); + return -1; + } + + return 0; +} + +int MnsSdkCommon::FetchJsonValByKey4Val(rapidjson::Value &reader, + const string &strKey, + rapidjson::Value::MemberIterator *pitr) { + *pitr = reader.FindMember(strKey.c_str()); + if (*pitr == reader.MemberEnd()) { + MNS_LOG_WARN("No " << strKey); + /*SEND_LOG_ERROR("coral.interface.error",7338731, ("No " + strKey).c_str() + ,4, -1, ("No " + strKey).c_str() );*/ + return -1; + } + + if (CheckEmptyJsonStringVal(*pitr) && "extend" != strKey) { + MNS_LOG_WARN(strKey << " has empty string value"); + return 1; + } + + return 0; +} + +int MnsSdkCommon::CheckEmptyJsonStringVal(const rapidjson::Document::MemberIterator &itr) { + if ((itr->value).IsString() + && 0 == string((itr->value).GetString()).size()) { + return 1; + } + + return 0; +} + +void MnsSdkCommon::IntranetIp(char ip[INET_ADDRSTRLEN]) { + struct ifaddrs *ifAddrStruct = NULL; + struct ifaddrs *ifa = NULL; + void *tmpAddrPtr = NULL; + int addrArrayLen = 32; + char addrArray[addrArrayLen][INET_ADDRSTRLEN]; + getifaddrs(&ifAddrStruct); + int index = 0; + for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) { + if (!ifa->ifa_addr) { + continue; + } + if (0 == strcmp(ifa->ifa_name, "vnic")) + continue; + if (ifa->ifa_addr->sa_family == AF_INET) { // check it is IP4 + //tmpAddrPtr = &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr; + tmpAddrPtr = + &(reinterpret_cast(ifa->ifa_addr))->sin_addr; + inet_ntop(AF_INET, tmpAddrPtr, addrArray[index], INET_ADDRSTRLEN); + if (0 == strcmp(addrArray[index], "127.0.0.1")) + continue; + strcpy(ip, addrArray[index]); + if (++index >= addrArrayLen - 1) + break; + } + } + if (index > 1) { + int idx = 0; + while (idx < index) { + if (NULL != strstr(addrArray[idx], "10.") + && 0 == strcmp(addrArray[idx], strstr(addrArray[idx], "10."))) { + strcpy(ip, addrArray[idx]); + } + idx++; + } + } + if (ifAddrStruct != NULL) + freeifaddrs(ifAddrStruct); + return; +} + +double MnsSdkCommon::FetchOctoWeight(const double &fweight, + const double &weight) { + return (!CheckDoubleEqual(fweight, weight) + && !CheckDoubleEqual(fweight, static_cast(0))) ? fweight : weight; +} + +bool MnsSdkCommon::CheckDoubleEqual(const double &d1, const double &d2) { + return fabs(d1 - d2) < numeric_limits::epsilon(); +} + +void MnsSdkCommon::PackDefaultSgservice(const string &str_svr_appkey, + const string &str_local_ip, + const uint16_t &u16_port, + meituan_mns::SGService *p_sgservice) { + p_sgservice->__set_appkey(str_svr_appkey); + p_sgservice->__set_version("origin"); + p_sgservice->__set_ip(str_local_ip); + p_sgservice->__set_port(u16_port); + p_sgservice->__set_weight(10); + p_sgservice->__set_status(2); + p_sgservice->__set_lastUpdateTime(static_cast(time(0))); + p_sgservice->__set_fweight(10.0); + p_sgservice->__set_serverType(0); + p_sgservice->__set_heartbeatSupport(2); +} + +bool MnsSdkCommon::CheckOverTime(const muduo::Timestamp ×tamp, const double +&d_overtime_secs, double *p_d_left_secs) { + double + d_time_diff_secs = + muduo::timeDifference(muduo::Timestamp::now(), timestamp); + + MNS_LOG_DEBUG("d_time_diff_secs " << d_time_diff_secs); + + if (p_d_left_secs) { + *p_d_left_secs = + d_overtime_secs > d_time_diff_secs ? d_overtime_secs - d_time_diff_secs + : 0; + } + + if (d_overtime_secs < d_time_diff_secs + || (CheckDoubleEqual( + d_overtime_secs, + d_time_diff_secs))) { + MNS_LOG_WARN("overtime " << d_overtime_secs << "secs, timediff " + << d_time_diff_secs << " secs"); + + return true; + } + + return false; +} + +} diff --git a/sdk/mns-sdk/src/util/mns_sdk_common.h b/sdk/mns-sdk/src/util/mns_sdk_common.h new file mode 100644 index 0000000..734cb91 --- /dev/null +++ b/sdk/mns-sdk/src/util/mns_sdk_common.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_MNS_SDK_COMMON_H_ +#define OCTO_OPEN_SOURCE_MNS_SDK_COMMON_H_ + +#include "mns_common.h" +#include "mns_config.h" + +namespace mns_sdk { +using namespace std; + +#define MNS_LIKELY(x) (__builtin_expect(!!(x), 1)) +#define MNS_UNLIKELY(x) (__builtin_expect(!!(x), 0)) + +#define ERR_CHECK_CONNECTION -300001 +#define ERR_CREATE_CONNECTION -300002 +#define ERR_CLOSE_CONNECTION -300003 + +#define CONNECTION_RETRY_TIMES 1 +#define SG_SERVER_READ_TIMEOUT 100 +#define SG_SERVER_CONN_TIMEOUT 50 +#define SG_SERVER_WRITE_TIMEOUT 50 +#define SG_LOCAL_SERVER_READ_TIMEOUT 30 +#define SG_LOCAL_SERVER_CONN_TIMEOUT 10 +#define SG_LOCAL_SERVER_WRITE_TIMEOUT 10 + +struct HttpContext { + muduo::net::HttpContext http_context; + uint32_t u32_want_len; +}; +typedef boost::shared_ptr HttpContextSharedPtr; + +class MnsSdkCommon { + public: + MnsSdkCommon(void); + + static std::string SGService2String(const meituan_mns::SGService &sgservice); + + static int8_t ParseSentineSgagentList + (const std::string &str_req, + std::vector *p_vec_sgservice); + + static int Hex2Decimal(const char *begin, const char *end); + static void ParseHttpChunkData(muduo::net::Buffer *pBuf, + muduo::net::HttpContext *pContext); + static bool ParseHttpRequest(uint32_t *pudwWantLen, + muduo::net::Buffer *buf, + muduo::net::HttpContext *context, + muduo::Timestamp receiveTime); + + static int FetchJsonValByKey4Doc(rapidjson::Document &reader, + const std::string &strKey, + rapidjson::Document::MemberIterator *pitr); + + static int FetchJsonValByKey4Val(rapidjson::Value &reader, + const std::string &strKey, + rapidjson::Value::MemberIterator *pitr); + + static void IntranetIp(char ip[INET_ADDRSTRLEN]); + + static int8_t FetchInt32FromJson + (const std::string &strKey, + rapidjson::Value &data_single, + int32_t *p_i32_value); + + static void replace_all_distinct + (const std::string &old_value, + const std::string &new_value, + std::string *p_str); + + static int CheckEmptyJsonStringVal(const + rapidjson::Document::MemberIterator &itr); + static int Httpgzdecompress(Byte *zdata, uLong nzdata, + Byte *data, uLong *ndata); + + static string strToLower(const string &str_tmp); + + static double + FetchOctoWeight(const double &fweight, const double &weight); + + static bool CheckDoubleEqual(const double &d1, const double &d2); + + static void PackDefaultSgservice(const string &str_svr_appkey, + const string &str_local_ip, + const uint16_t &u16_port, + meituan_mns::SGService *p_sgservice); + + static bool CheckOverTime(const muduo::Timestamp ×tamp, + const double &d_overtime_secs, + double *p_d_left_secs); + + const static double kDFirstRegionMin; + const static double kDSecondRegionMin; +}; + +} + +#endif //OCTO_OPEN_SOURCE_MNS_SDK_COMMON_H_ diff --git a/sdk/mns-sdk/thrid/octoidl/CMakeLists.txt b/sdk/mns-sdk/thrid/octoidl/CMakeLists.txt new file mode 100644 index 0000000..698f61b --- /dev/null +++ b/sdk/mns-sdk/thrid/octoidl/CMakeLists.txt @@ -0,0 +1,33 @@ + +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/octoidl) + +SET(THRIFT_GEN_CPP_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../../common/gen-cpp) + +SET(OCTOIDL_SRC + ${THRIFT_GEN_CPP_PATH}/MNSCacheService.cpp + ${THRIFT_GEN_CPP_PATH}/mnsc_data_constants.cpp + ${THRIFT_GEN_CPP_PATH}/mnsc_data_types.cpp + ${THRIFT_GEN_CPP_PATH}/mnsc_service_constants.cpp + ${THRIFT_GEN_CPP_PATH}/mnsc_service_types.cpp + ${THRIFT_GEN_CPP_PATH}/naming_common_constants.cpp + ${THRIFT_GEN_CPP_PATH}/naming_common_types.cpp + ${THRIFT_GEN_CPP_PATH}/naming_service_constants.cpp + ${THRIFT_GEN_CPP_PATH}/naming_service_types.cpp + ${THRIFT_GEN_CPP_PATH}/unified_protocol_constants.cpp + ${THRIFT_GEN_CPP_PATH}/unified_protocol_types.cpp + ${THRIFT_GEN_CPP_PATH}/ServiceAgent.cpp + ${THRIFT_GEN_CPP_PATH}/naming_common_types.cpp + ${THRIFT_GEN_CPP_PATH}/naming_data_types.cpp + ) + +MESSAGE("OCTOIDL_SRC ${OCTOIDL_SRC}") + +ADD_LIBRARY(octoidl STATIC ${OCTOIDL_SRC}) +ADD_LIBRARY(octoidl_dynamic SHARED ${OCTOIDL_SRC}) + +SET_TARGET_PROPERTIES(octoidl_dynamic PROPERTIES OUTPUT_NAME "octoidl") + +#DO NOT add ' OR " to the path +EXECUTE_PROCESS(COMMAND find ${THRIFT_GEN_CPP_PATH} -name *.h -print -exec cp -t ${INCLUDE_OCTOIDL_OUTPUT_PATH} {} \;) + + diff --git a/sdk/mns-sdk/tool/clear4git.sh b/sdk/mns-sdk/tool/clear4git.sh new file mode 100644 index 0000000..08706bd --- /dev/null +++ b/sdk/mns-sdk/tool/clear4git.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +rm -rf ../cmake_install.cmake ../CMakeCache.txt ../CMakeFiles ../Makefile ../build/ ../install_manifest.txt +rm -rf ../src/cmake_install.cmake ../src/CMakeCache.txt ../src/CMakeFiles ../src/Makefile ../src/gen-cpp +rm -rf ../src/tests/cmake_install.cmake ../src/tests/CMakeCache.txt ../src/tests/CMakeFiles ../src/tests/Makefile +rm -rf ../example/cmake_install.cmake ../example/CMakeCache.txt ../example/CMakeFiles ../example/Makefile + +find ../ -name .*.sw* -exec rm -rf {} \; diff --git a/sg_agent/CMakeLists.txt b/sg_agent/CMakeLists.txt new file mode 100644 index 0000000..ac00e95 --- /dev/null +++ b/sg_agent/CMakeLists.txt @@ -0,0 +1,144 @@ +cmake_minimum_required(VERSION 2.8) + +project(sg_agent C CXX) +SET(CMAKE_CXX_FLAGS "-g -fPIC -Wno-deprecated -DHAVE_NETINET_IN_H -DMUDUO_STD_STRING") + +SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +#for filter absolute path of compiler machine +SET(CMAKE_USE_RELATIVE_PATHS ON) + +SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") +MESSAGE(STATUS "CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}") + +IF(ENABLE_COVERAGE) + include(CodeCoverage) + APPEND_COVERAGE_COMPILER_FLAGS() +ENDIF() + +#use clog +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_CLOG_SUPPORT") + +SET(AGENT_SRC_PATH ${CMAKE_SOURCE_DIR}/src) +MESSAGE(STATUS "AGENT_SRC_PATH ${AGENT_SRC_PATH}") + +SET(SGAGENT_MODULE_PATH ${CMAKE_SOURCE_DIR}/thrid_party) +MESSAGE(STATUS "SGAGENT_MODULE_PATH ${SGAGENT_MODULE_PATH}") + +SET(THIRD_MODULE_PATH ${CMAKE_SOURCE_DIR}/thrid_party) +MESSAGE(STATUS "THIRD_MODULE_PATH ${THIRD_MODULE_PATH}") + +SET(COMMON_PATH ${AGENT_SRC_PATH}/comm) +MESSAGE(STATUS "COMMON_PATH ${COMMON_PATH}") + +SET(COMMONLOG_PATH ${AGENT_SRC_PATH}/commonlog) +MESSAGE(STATUS "COMMONLOG_PATH ${COMMONLOG_PATH}") + +SET(UTIL_PATH ${AGENT_SRC_PATH}/util) +MESSAGE(STATUS "UTIL_PATH ${UTIL_PATH}") + +SET(RULE_PATH ${AGENT_SRC_PATH}/rule) +MESSAGE(STATUS "RULE_PATH ${RULE_PATH}") + +SET(MCC_PATH ${AGENT_SRC_PATH}/mcc) +MESSAGE(STATUS "MCC_PATH ${MCC_PATH}") + +SET(MNS_PATH ${AGENT_SRC_PATH}/mns) +MESSAGE(STATUS "MNS_PATH ${MNS_PATH}") + +SET(MAFKA_PATH ${AGENT_SRC_PATH}/remote/mafka) +MESSAGE(STATUS "MAFKA_PATH ${MAFKA_PATH}") + + +SET(FALCON_PATH ${AGENT_SRC_PATH}/remote/falcon) +MESSAGE(STATUS "FALCON_PATH ${FALCON_PATH}") + +SET(LOG4CPLUS_PATH ${CMAKE_SOURCE_DIR}/thrid_party/logs/log4cplus) +MESSAGE(STATUS "LOG4CPLUS_PATH ${LOG4CPLUS_PATH}") + +SET(MONITOR_COLLECTOR_PATH ${AGENT_SRC_PATH}/remote/monitor) +MESSAGE(STATUS "MONITOR_COLLECTOR_PATH ${MONITOR_COLLECTOR_PATH}") + +INCLUDE(ExternalProject) + +#for output +EXECUTE_PROCESS(COMMAND mkdir ${CMAKE_SOURCE_DIR}/build) +SET(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/build) +MESSAGE(STATUS "CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}") + +#default binary and lib path +SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_INSTALL_PREFIX}/bin) +EXECUTE_PROCESS(COMMAND mkdir ${EXECUTABLE_OUTPUT_PATH}) +MESSAGE(STATUS "EXECUTABLE_OUTPUT_PATH ${EXECUTABLE_OUTPUT_PATH}") + +# find muduo libraries +if (CMAKE_BUILD_INIT) + FIND_PACKAGE(Muduo REQUIRED) + MESSAGE(STATUS "MUDUO_INCLUDE_DIR ${MUDUO_INCLUDE_DIR}") + MESSAGE(STATUS "MUDUO_BASE_LIBRARIES ${MUDUO_BASE_LIBRARY}") +else() + find_library(MUDUO_BASE_LIBRARY libmuduo_base.a) + find_library(MUDUO_NET_LIBRARY libmuduo_net.a) + find_library(MUDUO_HTTP_LIBRARY libmuduo_http.a) + MESSAGE(STATUS,"MUDUO_BASE_LIBRARY ${MUDUO_BASE_LIBRARY}") + MESSAGE(STATUS,"MUDUO_NET_LIBRARY ${MUDUO_NET_LIBRARY}") + MESSAGE(STATUS,"MUDUO_HTTP_LIBRARY ${MUDUO_HTTP_LIBRARY}") + # find zookeeper libraries + FIND_PACKAGE(Zookeeper REQUIRED) + MESSAGE(STATUS "ZOOKEEPER_LIBRARY ${ZOOKEEPER_LIBRARY}") + MESSAGE(STATUS "ZOOKEEPER_INCLUDE_DIR ${ZOOKEEPER_INCLUDE_DIR}") + + # find boost libraries + FIND_PACKAGE(Boost REQUIRED) + MESSAGE(STATUS "BOOST_INCLUDE_DIR ${BOOST_INCLUDE_DIR}") + + #find cthrift libraries + FIND_PACKAGE(Cthrift REQUIRED) + MESSAGE(STATUS "CTHRIFT_INCLUDE_DIR ${CTHRIFT_INCLUDE_DIR}") + MESSAGE(STATUS "CTHRIFT_LIBRARY ${CTHRIFT_LIBRARY}") + + #find cthrift libraries + FIND_PACKAGE(Sdk REQUIRED) + #MESSAGE(STATUS "CTHRIFT_INCLUDE_DIR ${CTHRIFT_INCLUDE_DIR}") + MESSAGE(STATUS "MNS_SDK_LIBRARY ${MNS_SDK_LIBRARY}") + + FIND_PACKAGE(Log4cplus REQUIRED) + MESSAGE(STATUS "LOG4CPLUS_INCLUDE_DIR ${LOG4CPLUS_INCLUDE_DIR}") + MESSAGE(STATUS "LOG4CPLUS_LIBRARY ${LOG4CPLUS_LIBRARY}") + + # find thrift libraries + FIND_PACKAGE(Thrift REQUIRED) + SET(THRIFT_COMPILER ${THIRD_MODULE_PATH}/thrift-0.8.0_build/bin/thrift) + SET(THRIFT_INCLUDE_DIR ${SGAGENT_MODULE_PATH}/thrift/include) + SET(THRIFT_STATIC_LIB ${SGAGENT_MODULE_PATH}/thrift/lib/libthrift.a) + SET(THRIFTNB_STATIC_LIB ${SGAGENT_MODULE_PATH}/thrift/lib/libthriftnb.a) + MESSAGE(STATUS "THRIFT_INCLUDE_DIR ${THRIFT_INCLUDE_DIR}") + MESSAGE(STATUS "THRIFT_LIBS ${THRIFT_LIBS}") + MESSAGE(STATUS "THRIFT_STATIC_LIB ${THRIFT_STATIC_LIB}") + MESSAGE(STATUS "THRIFTNB_STATIC_LIB ${THRIFTNB_STATIC_LIB}") + + SET(OCTO_IDL_PATH ../common/idl-mns) + MESSAGE(STATUS "OCTO_IDL_PATH ${OCTO_IDL_PATH}") + + SET(CURRENT_CMAKE_PATH ) + SET(THRIFT_GEN_CPP_PATH ../../../octo-open_source/common/gen-cpp) + MESSAGE(STATUS "THRIFT_GEN_CPP_PATH ${THRIFT_GEN_CPP_PATH}") + + INCLUDE_DIRECTORIES(system ${CTHRIFT_INCLUDE_DIR}) + INCLUDE_DIRECTORIES(system ${SDK_INCLUDE_DIR}) + + MESSAGE(STATUS "CTHRIFT_INCLUDE_DIR ${CTHRIFT_INCLUDE_DIR}") + MESSAGE(STATUS "SDK_INCLUDE_DIR ${SDK_INCLUDE_DIR}") + + if(${CMAKE_BUILD_TYPE} MATCHES "debug") + ADD_DEFINITIONS(-DSG_AGENT_TEST) + ADD_SUBDIRECTORY(test) + else() + ADD_SUBDIRECTORY(src/mns) + endif() + +INSTALL(CODE "execute_process(COMMAND find ${CMAKE_SOURCE_DIR}/tool/ -type f -exec cp -rt ${EXECUTABLE_OUTPUT_PATH} {} \;)") +INSTALL(CODE "execute_process(COMMAND find ${CMAKE_SOURCE_DIR}/conf/ -type f -exec cp -rt ${EXECUTABLE_OUTPUT_PATH} {} \;)") + +endif() diff --git a/sg_agent/README.md b/sg_agent/README.md new file mode 100644 index 0000000..c3f89e5 --- /dev/null +++ b/sg_agent/README.md @@ -0,0 +1,23 @@ +## SGAgent简介 + + * SGAgent是基于C++开发的服务治理代理,为美团点评OCTO服务治理体系提供支持水平扩展的RPC/HTTP服务治理接入. + * SGAgent作为服务端项目基础组件,提供了通过RPC/HTTP进行服务注册、服务发现等功能. + * SGAgent组件的引入简化了SDK和通信框架的设计,可进行基于标签、服务分组等功能辅助通信框架完成软负载及流量走向定义. + +## 功能简介 + + 服务治理完成服务注册、服务发现的两个主要流程,注册支持按增量和非增量方式,增量方式是指一个服务实例可以包含多种ServiceName接口类型,通过在注册中心建立ServiceName和服务实例的双向映射,可满足按ServiceName和服务实例两种方式进行服务发现. + + (1)**服务分组**:服务分组本质影响服务节点权重(权重的调整可按照用户进行自定义),服务分组只有在注册中心配置了路由策略且生效才会最终影响到权重过滤,目前支持的几种策略如下 + + a.自定义路由分组:在服务端配置该策略后,可定向指定上游打入该服务的服务范围; + + b.同机房优先分组:是默认分组,自动开启,流量优先在同机房进行调用. + + c.同中心优先分组: 默认不开启,流量在同中心进行调用. + + d.同城市路由分组: 在同域进行流量的调用. + + (2)**标签过滤**: 对于服务提供者自定义了标签属性的服务发现流程,可按照传入标签返回对应感兴趣服务提供者信息. + + (3)**HTTP接口**: 支持HTTP接口进行服务发现. \ No newline at end of file diff --git a/sg_agent/build.sh b/sg_agent/build.sh new file mode 100755 index 0000000..c00fcbd --- /dev/null +++ b/sg_agent/build.sh @@ -0,0 +1,49 @@ +#!/bin/sh + +set -x + +if [ $# -ne 1 ] || [ "$1" != "only_lib" -a "$1" != "with_example" -a "$1" != "with_bin" -a "$1" != "clean" -a "$1" != "init" ] +then +echo "build.sh + , no argument means all" +exit +fi + +BUILD_NO_EXAMPLES=${BUILD_NO_EXAMPLES:-0} +BUILD_NO_TESTS=${BUILD_NO_TESTS:-0} + +SOURCE_DIR=`pwd` +CPU_CORE_NUM=`cat /proc/cpuinfo | grep processor | wc -l` + + + if [ "$1" == "clean" ] + then + cd tool + sh -x clear4git.sh + cd - + exit + fi + + BUILD_NO_EXAMPLES=1 + BUILD_NO_TESTS=1 + + if [ "$1" == "with_example" ] + then + BUILD_NO_EXAMPLES=0 + elif [ "$1" == "with_bin" ] + then + BUILD_NO_TESTS=0 + elif [ "$1" == "init" ] + then + cmake -DCMAKE_BUILD_INIT=1 $SOURCE_DIR && make -j"$CPU_CORE_NUM" + cd tool + sh -x clear4git.sh + cd - + exit + fi + + + cmake \ + -DCMAKE_BUILD_NO_EXAMPLES=$BUILD_NO_EXAMPLES \ + -DCMAKE_BUILD_NO_TESTS=$BUILD_NO_TESTS \ + $SOURCE_DIR \ + && make -j"$CPU_CORE_NUM" diff --git a/sg_agent/cmake/CMakeLists.download_gtest.in b/sg_agent/cmake/CMakeLists.download_gtest.in new file mode 100644 index 0000000..da9f6f5 --- /dev/null +++ b/sg_agent/cmake/CMakeLists.download_gtest.in @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.8.10) + +project(googletest-download NONE) + +include(ExternalProject) +ExternalProject_Add(googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.8.0 + SOURCE_DIR "${PROJECT_BINARY_DIR}/googletest-src" + BINARY_DIR "${PROJECT_BINARY_DIR}/googletest-build" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" +) diff --git a/sg_agent/cmake/CodeCoverage.cmake b/sg_agent/cmake/CodeCoverage.cmake new file mode 100644 index 0000000..1629bd4 --- /dev/null +++ b/sg_agent/cmake/CodeCoverage.cmake @@ -0,0 +1,235 @@ +# Copyright (c) 2012 - 2017, Lars Bilke +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# CHANGES: +# +# 2012-01-31, Lars Bilke +# - Enable Code Coverage +# +# 2013-09-17, Joakim Söderberg +# - Added support for Clang. +# - Some additional usage instructions. +# +# 2016-02-03, Lars Bilke +# - Refactored functions to use named parameters +# +# 2017-06-02, Lars Bilke +# - Merged with modified version from github.com/ufz/ogs +# +# +# USAGE: +# +# 1. Copy this file into your cmake modules path. +# +# 2. Add the following line to your CMakeLists.txt: +# include(CodeCoverage) +# +# 3. Append necessary compiler flags: +# APPEND_COVERAGE_COMPILER_FLAGS() +# +# 4. If you need to exclude additional directories from the report, specify them +# using the COVERAGE_EXCLUDES variable before calling SETUP_TARGET_FOR_COVERAGE. +# Example: +# set(COVERAGE_EXCLUDES 'dir1/*' 'dir2/*') +# +# 5. Use the functions described below to create a custom make target which +# runs your test executable and produces a code coverage report. +# +# 6. Build a Debug build: +# cmake -DCMAKE_BUILD_TYPE=Debug .. +# make +# make my_coverage_target +# + +include(CMakeParseArguments) + +# Check prereqs +find_program( GCOV_PATH gcov ) +find_program( LCOV_PATH lcov ) +find_program( GENHTML_PATH genhtml ) +find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test) +find_program( SIMPLE_PYTHON_EXECUTABLE python ) + +if(NOT GCOV_PATH) + message(FATAL_ERROR "gcov not found! Aborting...") +endif() # NOT GCOV_PATH + +if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") + if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3) + message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...") + endif() +elseif(NOT CMAKE_COMPILER_IS_GNUCXX) + message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...") +endif() + +set(COVERAGE_COMPILER_FLAGS "-g -O0 --coverage -fprofile-arcs -ftest-coverage" + CACHE INTERNAL "") + +set(CMAKE_CXX_FLAGS_COVERAGE + ${COVERAGE_COMPILER_FLAGS} + CACHE STRING "Flags used by the C++ compiler during coverage builds." + FORCE ) +set(CMAKE_C_FLAGS_COVERAGE + ${COVERAGE_COMPILER_FLAGS} + CACHE STRING "Flags used by the C compiler during coverage builds." + FORCE ) +set(CMAKE_EXE_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used for linking binaries during coverage builds." + FORCE ) +set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used by the shared libraries linker during coverage builds." + FORCE ) +mark_as_advanced( + CMAKE_CXX_FLAGS_COVERAGE + CMAKE_C_FLAGS_COVERAGE + CMAKE_EXE_LINKER_FLAGS_COVERAGE + CMAKE_SHARED_LINKER_FLAGS_COVERAGE ) + +if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") + message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading") +endif() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug" + +if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + link_libraries(gcov) +else() + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") +endif() + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# SETUP_TARGET_FOR_COVERAGE( +# NAME testrunner_coverage # New target name +# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES testrunner # Dependencies to build first +# ) +function(SETUP_TARGET_FOR_COVERAGE) + + set(options NONE) + set(oneValueArgs NAME) + set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT LCOV_PATH) + message(FATAL_ERROR "lcov not found! Aborting...") + endif() # NOT LCOV_PATH + + if(NOT GENHTML_PATH) + message(FATAL_ERROR "genhtml not found! Aborting...") + endif() # NOT GENHTML_PATH + + # Setup target + add_custom_target(${Coverage_NAME} + + # Cleanup lcov + COMMAND ${LCOV_PATH} --directory . --zerocounters + + # Run tests + COMMAND ${Coverage_EXECUTABLE} + + # Capturing lcov counters and generating report + COMMAND ${LCOV_PATH} --directory . --capture --output-file ${Coverage_NAME}.info + COMMAND ${LCOV_PATH} --remove ${Coverage_NAME}.info ${COVERAGE_EXCLUDES} --output-file ${Coverage_NAME}.info.cleaned + COMMAND ${GENHTML_PATH} -o ${Coverage_NAME} ${Coverage_NAME}.info.cleaned + COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.info ${Coverage_NAME}.info.cleaned + + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." + ) + + # Show info where to find the report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." + ) + +endfunction() # SETUP_TARGET_FOR_COVERAGE + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# SETUP_TARGET_FOR_COVERAGE_COBERTURA( +# NAME ctest_coverage # New target name +# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES executable_target # Dependencies to build first +# ) +function(SETUP_TARGET_FOR_COVERAGE_COBERTURA) + + set(options NONE) + set(oneValueArgs NAME) + set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT SIMPLE_PYTHON_EXECUTABLE) + message(FATAL_ERROR "python not found! Aborting...") + endif() # NOT SIMPLE_PYTHON_EXECUTABLE + + if(NOT GCOVR_PATH) + message(FATAL_ERROR "gcovr not found! Aborting...") + endif() # NOT GCOVR_PATH + + # Combine excludes to several -e arguments + set(COBERTURA_EXCLUDES "") + foreach(EXCLUDE ${COVERAGE_EXCLUDES}) + set(COBERTURA_EXCLUDES "-e ${EXCLUDE} ${COBERTURA_EXCLUDES}") + endforeach() + + add_custom_target(${Coverage_NAME} + + # Run tests + ${Coverage_EXECUTABLE} + + # Running gcovr + COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} ${COBERTURA_EXCLUDES} + -o ${Coverage_NAME}.xml + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + COMMENT "Running gcovr to produce Cobertura code coverage report." + ) + + # Show info where to find the report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml." + ) + +endfunction() # SETUP_TARGET_FOR_COVERAGE_COBERTURA + +function(APPEND_COVERAGE_COMPILER_FLAGS) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) + message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}") +endfunction() # APPEND_COVERAGE_COMPILER_FLAGS + diff --git a/sg_agent/cmake/DonwloadMuduo.cmake b/sg_agent/cmake/DonwloadMuduo.cmake new file mode 100644 index 0000000..371af81 --- /dev/null +++ b/sg_agent/cmake/DonwloadMuduo.cmake @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 2.8.10) + +project(muduo-download NONE) + +include(ExternalProject) +ExternalProject_Add(muduo + GIT_REPOSITORY https://github.com/chenshuo/muduo.git + GIT_TAG v1.1.0 + SOURCE_DIR "${PROJECT_BINARY_DIR}/muduo" + PATCH_COMMAND patch -p1 < ${CMAKE_SOURCE_DIR}/patch/0001-add-patch-for-http.patch + CMAKE_COMMAND cmake + CMAKE_ARGS "-DCMAKE_BUILD_NO_EXAMPLES=1 -DCMAKE_CXX_FLAGS=-fPIC" + ) diff --git a/sg_agent/cmake/FindBoost.cmake b/sg_agent/cmake/FindBoost.cmake new file mode 100644 index 0000000..8b5cf4c --- /dev/null +++ b/sg_agent/cmake/FindBoost.cmake @@ -0,0 +1,26 @@ +# FindBoost +# -------- +# +# Find boost +# +# Find the boost includes and library. Once done this will define +# +# BOOST_INCLUDE_DIRS - where to find boost include, etc. +# BOOST_FOUND - True if boost found. +# +set(BOOST_INCLUDE_DIR ${THIRD_MODULE_PATH}/boost_1_59_0/) + +#message(${BOOST_INCLUDE_DIRS}) +find_path(BOOST_INCLUDE_DIR NAMES boost) + +mark_as_advanced(BOOST_INCLUDE_DIR) + +# handle the QUIETLY and REQUIRED arguments and set BOOST_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Boost REQUIRED_VARS BOOST_INCLUDE_DIR) + +if(BOOST_FOUND) + set(BOOST_INCLUDE_DIRS ${BOOST_INCLUDE_DIR}) +endif() + diff --git a/sg_agent/cmake/FindCthrift.cmake b/sg_agent/cmake/FindCthrift.cmake new file mode 100644 index 0000000..7b637f5 --- /dev/null +++ b/sg_agent/cmake/FindCthrift.cmake @@ -0,0 +1,27 @@ +# FindCthrift +# -------- +# +# Find Cthrift +# +# Find the Cthrift includes and library. Once done this will define +# +# CTHRIFT_INCLUDE_DIRS - where to find cthrift include, etc. +# CTHRIFT_FOUND - True if cthrift found. +# +set(CTHRIFT_INCLUDE_DIR ${SGAGENT_MODULE_PATH}/cthrift/include) + +#message(${CTHRIFT_INCLUDE_DIR}) +find_path(CTHRIFT_INCLUDE_DIR NAMES cthrift) + +mark_as_advanced(cthrift_INCLUDE_DIR) + +# handle the QUIETLY and REQUIRED arguments and set CTHRIFT_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Cthrift REQUIRED_VARS CTHRIFT_INCLUDE_DIR) + +if(CTHRIFT_FOUND) + set(CTHRIFT_INCLUDE_DIRS ${CTHRIFT_INCLUDE_DIR}) +endif() + +set(CTHRIFT_LIBRARY ${SGAGENT_MODULE_PATH}/cthrift/lib/libcthrift.a) diff --git a/sg_agent/cmake/FindLog4cplus.cmake b/sg_agent/cmake/FindLog4cplus.cmake new file mode 100644 index 0000000..7cabb56 --- /dev/null +++ b/sg_agent/cmake/FindLog4cplus.cmake @@ -0,0 +1,33 @@ +# FindLog4cplus +# -------- +# +# Find log4cplus +# +# Find the log4cplus includes and library. Once done this will define +# +# LOG4CPLUS_INCLUDE_DIRS - where to find log4cplus include, etc. +# LOG4CPLUS_FOUND - True if log4cplus found. +# + +set(LOG4CPLUS_INCLUDE_DIR ${SGAGENT_MODULE_PATH}/logs/log4cplus/include) +set(LOG4CPLUS_LIBRARY ${SGAGENT_MODULE_PATH}/logs/lib/liblog4cplus.a) + + +#message(${CURL_INCLUDE_DIRS}) +find_path(LOG4CPLUS_INCLUDE_DIR NAMES log4cplus) +find_library(LOG4CPLUS_LIBRARY NAMES log4cplus) + +mark_as_advanced(LOG4CPLUS_LIBRARY LOG4CPLUS_INCLUDE_DIR) + + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Log4cplus REQUIRED_VARS LOG4CPLUS_LIBRARY + LOG4CPLUS_INCLUDE_DIR) + +set(LOG4CPLUS_FOUND TRUE) +if(LOG4CPLUS_FOUND) + set(LOG4CPLUS_INCLUDE_DIR ${LOG4CPLUS_INCLUDE_DIR}) + set(LOG4CPLUS_LIBRARY ${LOG4CPLUS_LIBRARY}) + message(STATUS "${LOG4CPLUS_INCLUDE_DIR}") + message(STATUS "${LOG4CPLUS_LIBRARY}") +endif() diff --git a/sg_agent/cmake/FindMuduo.cmake b/sg_agent/cmake/FindMuduo.cmake new file mode 100644 index 0000000..02856f2 --- /dev/null +++ b/sg_agent/cmake/FindMuduo.cmake @@ -0,0 +1,38 @@ +# Find the muduo includes and library. Once done this will define +# +# MUDUO_INCLUDE_DIRS - where to find muduo include, etc. +# MUDUO_BASE_LIBRARIES - List of libraries when using muduo_base. +# MUDUO_NET_LIBRARIES - List of libraries when using muduo_net. +# MUDUO_HTTP_LIBRARIES - List of libraries when using muduo_http. +# MUDUO_FOUND - True if muduo found. +# +set(MUDUO_INCLUDE_DIR /usr/local/include/) +set(MUDUO_BASE_LIBRARY /usr/local/lib) + + +find_path(MUDUO_INCLUDE_DIR NAMES muduo PATHS ${MUDUO_INCLUDE_DIR}) +find_library(MUDUO_BASE_LIBRARY NAMES muduo_base PATHS ${MUDUO_BASE_LIBRARY}) + + +mark_as_advanced(MUDUO_BASE_LIBRARY MUDUO_INCLUDE_DIR) + +# handle the QUIETLY and REQUIRED arguments and set MUDUO_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(MUDUO REQUIRED_VARS MUDUO_BASE_LIBRARY + MUDUO_INCLUDE_DIR) + +MESSAGE("MUDUO_INCLUDE_DIR ${MUDUO_INCLUDE_DIR}") +MESSAGE("MUDUO_BASE_LIBRARY ${MUDUO_BASE_LIBRARY}") + +include(DonwloadMuduo) + +if(MUDUO_FOUND) + set(MUDUO_INCLUDE_DIRS ${MUDUO_INCLUDE_DIR}) + set(MUDUO_BASE_LIBRARIES ${MUDUO_BASE_LIBRARY} pthread rt) + MESSAGE("MUDUO_FOUND") +else() + MESSAGE("MUDUO_FOUND NO FOUND Download and compile") + include(DonwloadMuduo) +endif() + diff --git a/sg_agent/cmake/FindSdk.cmake b/sg_agent/cmake/FindSdk.cmake new file mode 100644 index 0000000..e8b4899 --- /dev/null +++ b/sg_agent/cmake/FindSdk.cmake @@ -0,0 +1,17 @@ +# FindSdk +# -------- +# +# Find SDK +# +set(MNS_SDK_LIBRARY ${THIRD_MODULE_PATH}/thrid/lib/libmns_sdk.a) + +find_library(MNS_SDK_LIBRARY NAMES libmns_sdk.a) +set(SDK_INCLUDE_DIR ${THIRD_MODULE_PATH}/thrid/include/) +mark_as_advanced(MNS_SDK_LIBRARY MNS_SDK_INCLUDE_DIR) + +# handle the QUIETLY and REQUIRED arguments and set ZOOKEEPER_FOUND to TRUE if +# all listed variables are TRUE + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(sdk REQUIRED_VARS MNS_SDK_LIBRARY) + diff --git a/sg_agent/cmake/FindThrift.cmake b/sg_agent/cmake/FindThrift.cmake new file mode 100644 index 0000000..109a938 --- /dev/null +++ b/sg_agent/cmake/FindThrift.cmake @@ -0,0 +1,54 @@ +# - Find Thrift (a cross platform RPC lib/tool) +# This module defines +# THRIFT_VERSION, version string of ant if found +# THRIFT_INCLUDE_DIR, where to find THRIFT headers +# THRIFT_CONTRIB_DIR, where contrib thrift files (e.g. fb303.thrift) are installed +# THRIFT_LIBS, THRIFT libraries +# THRIFT_FOUND, If false, do not try to use ant + +# prefer the thrift version supplied in THRIFT_HOME +set(THRIFT_INCLUDE_DIR ${THIRD_MODULE_PATH}/thrift-0.8.0_build/include) +find_path(THRIFT_INCLUDE_DIR thrift/Thrift.h) + +set(THRIFT_CONTRIB_DIR ${THIRD_MODULE_PATH}/thrift-0.8.0_build/contrib) +find_path(THRIFT_CONTRIB_DIR fb303/if/fb303.thrift) + +set (THRIFT_LIB_PATHS ${THIRD_MODULE_PATH}/thrift-0.8.0_build/lib) +find_path(THRIFT_LIB_PATH libthrift.a PATHS ${THRIFT_LIB_PATHS}) + +set (THRIFT_STATIC_LIB_PATH ${THIRD_MODULE_PATH}/thrift-0.8.0_build/lib) +find_path(THRIFT_STATIC_LIB_PATH libthrift.a PATHS ${THRIFT_LIB_PATHS}) + +# prefer the thrift version supplied in THRIFT_HOME +find_library(THRIFT_LIB NAMES thrift HINTS ${THRIFT_LIB_PATHS}) +find_library(THRIFTNB_LIB NAMES thriftnb HINTS ${THRIFT_LIB_PATHS}) + +set(THRIFT_COMPILER ${THIRD_MODULE_PATH}/thrift-0.8.0_build/bin/thrift) +find_program(THRIFT_COMPILER thrift) + +if (THRIFT_LIB) + set(THRIFT_FOUND TRUE) + set(THRIFT_LIBS ${THIRD_MODULE_PATH}/thrift-0.8.0_build/lib/libthrift.so) + set(THRIFT_STATIC_LIB ${THRIFT_STATIC_LIB_PATH}/libthrift.a) + set(THRIFTNB_STATIC_LIB ${THRIFT_STATIC_LIB_PATH}/libthriftnb.a) + exec_program(${THRIFT_COMPILER} + ARGS -version OUTPUT_VARIABLE THRIFT_VERSION RETURN_VALUE THRIFT_RETURN) +else () + set(THRIFT_FOUND FALSE) +endif () + +if (THRIFT_FOUND) + if (NOT THRIFT_FIND_QUIETLY) + message(STATUS "${THRIFT_VERSION}") + endif () +else () + message(STATUS "Thrift compiler/libraries NOT found. " + "Thrift support will be disabled (${THRIFT_RETURN}, " + "${THRIFT_INCLUDE_DIR}, ${THRIFT_LIB})") +endif () + +mark_as_advanced( + THRIFT_LIB + THRIFT_COMPILER + THRIFT_INCLUDE_DIR +) diff --git a/sg_agent/cmake/FindZookeeper.cmake b/sg_agent/cmake/FindZookeeper.cmake new file mode 100644 index 0000000..8338185 --- /dev/null +++ b/sg_agent/cmake/FindZookeeper.cmake @@ -0,0 +1,27 @@ +# FindZookeeper +# -------- +# +# Find zookeeper +# +# Find the zookeeper includes and library. Once done this will define +# +# ZOOKEEPER_LIBRARIES - List of libraries when using zookeeper_base. +# ZOOKEEPER_FOUND - True if zookeeper found. +# +set(ZOOKEEPER_LIBRARY ${THIRD_MODULE_PATH}/zookeeper/libzookeeper_mt.a) + +find_library(ZOOKEEPER_LIBRARY NAMES zookeeper_mt) + +set(ZOOKEEPER_INCLUDE_DIR ${THIRD_MODULE_PATH}/zookeeper/include) + +mark_as_advanced(ZOOKEEPER_LIBRARY ZOOKEEPER_INCLUDE_DIR) + +# handle the QUIETLY and REQUIRED arguments and set ZOOKEEPER_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Zookeeper REQUIRED_VARS ZOOKEEPER_LIBRARY) + +if(ZOOKEEPER_FOUND) + set(ZOOKEEPER_LIBRARIES ${ZOOKEEPER_LIBRARY}) +endif() + diff --git a/sg_agent/cmake/SetupGtest.cmake b/sg_agent/cmake/SetupGtest.cmake new file mode 100644 index 0000000..869becd --- /dev/null +++ b/sg_agent/cmake/SetupGtest.cmake @@ -0,0 +1,24 @@ +# Setup googletest +configure_file("${PROJECT_SOURCE_DIR}/cmake/CMakeLists.download_gtest.in" ${PROJECT_BINARY_DIR}/googletest-download/CMakeLists.txt) + +execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/googletest-download + ) +if(result) + message(FATAL_ERROR "CMake step for googletest failed: ${result}") +endif() + +execute_process(COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/googletest-download + ) +if(result) + message(FATAL_ERROR "Build step for googletest failed: ${result}") +endif() + +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +add_subdirectory(${PROJECT_BINARY_DIR}/googletest-src + ${PROJECT_BINARY_DIR}/googletest-build + EXCLUDE_FROM_ALL) diff --git a/sg_agent/conf/README.md b/sg_agent/conf/README.md new file mode 100644 index 0000000..45244df --- /dev/null +++ b/sg_agent/conf/README.md @@ -0,0 +1,46 @@ +## 配置项简介 + +#### conf.json + + * SG_Agent使用Cthrift作为rpc server,该配置型定义了使用Cthrift Server时的配置. + * 参数介绍 + + 参数名 | 参数类型 | 描述 +------------- | ------------- | ------------ +MnsHost | string | 忽略 +server.Version | string | 忽略 +server.ListenPort | int | 监听端口 +server.Appkey | int | 忽略 +server.register | int | 忽略 +server.WorkThreadNum | int | 工作线程数 +server.MaxConnNum | int | 最大连接数 +server.ServerTimeOut | int | 超时 +server.ConnGCTime | int | +server.ConnThreadNum | int | 连接线程数 + + +#### sg\_agent\_mutable.xml + + * 配置代理通用参数 + * 参数介绍 + + 参数名 | 参数类型 | 描述 +------------- | ------------- | ------------ +AgentAppKey | string | 服务实例Appkey +AgentVersion | string | 版本信息 +ClientPort | int | 监听端口 +AgentLogPath | string | 日志目录 +MNSCacheAppkey | string | Mns-Cache Appkey +MnsHost | string | 标识ZooKeeper的地址信息 + +#### sg\_agent\_whitelist.xml + + * 配置服务注册、服务发现过程中的白名单信息. + + +#### idc.xml + + * 配置用于服务分组的参数 + + 该配置项定义服务部署归属的机房、idc及地域信息,用于做路由计算及权重调整使用. + diff --git a/sg_agent/conf/conf.json b/sg_agent/conf/conf.json new file mode 100644 index 0000000..3e681ed --- /dev/null +++ b/sg_agent/conf/conf.json @@ -0,0 +1,12 @@ +{ + "MnsHost":"10.20.127.164:2181", + "server.Version":"3.0.0", + "server.ListenPort":5266, + "server.Appkey":"octo.nameing.mt.newct", + "server.register":0, + "server.WorkThreadNum":40, + "server.MaxConnNum":10000, + "server.ServerTimeOut":100, + "server.ConnGCTime":600, + "server.ConnThreadNum":4 +} diff --git a/sg_agent/conf/idc.xml b/sg_agent/conf/idc.xml new file mode 100644 index 0000000..ca99fcd --- /dev/null +++ b/sg_agent/conf/idc.xml @@ -0,0 +1,97 @@ + + + + beijing + + DX + BJ1 + + 10.32.0.0 + 255.255.0.0 + + + 10.33.0.0 + 255.255.0.0 + + + + YF + BJ2 + + 10.4.0.0 + 255.255.0.0 + + + 10.5.0.0 + 255.255.0.0 + + + + RZ + NOCENTER + + 10.16.0.0 + 255.255.0.0 + + + 10.17.0.0 + 255.255.0.0 + + + + GH + BJ1 + + 10.20.0.0 + 255.255.0.0 + + + 10.21.0.0 + 255.255.0.0 + + + + TXBJ + BJ1 + + 10.61.0.0 + 255.255.0.0 + + + + + shanghai + + DP + SH + + 10.100.0.0 + 255.255.0.0 + + + + GQ + SH + + 10.3.0.0 + 255.255.0.0 + + + 10.67.0.0 + 255.255.0.0 + + + + NH + SH + + 10.1.0.0 + 255.255.0.0 + + + 10.101.0.0 + 255.255.0.0 + + + + diff --git a/sg_agent/conf/log4cplus.conf b/sg_agent/conf/log4cplus.conf new file mode 100644 index 0000000..ab2d633 --- /dev/null +++ b/sg_agent/conf/log4cplus.conf @@ -0,0 +1,67 @@ +log4cplus.rootLogger=fatal, error, warn, info, debug +log4cplus.logger.debug=debug +log4cplus.appender.debug=log4cplus::RollingFileAppender +log4cplus.appender.debug.MaxFileSize=50MB +log4cplus.appender.debug.MaxBackupIndex=10 +log4cplus.appender.debug.Append=true +log4cplus.appender.debug.layout=log4cplus::PatternLayout +log4cplus.appender.debug.layout.ConversionPattern=[%D{%Y-%m-%d %H:%M:%S:%Q}] [%F:%L] %-5p - %m%n +log4cplus.appender.debug.Threshold=fatal +log4cplus.appender.debug.append=true +log4cplus.appender.debug.File=/octo/ns/sg_agent/logs/sg_agent.debug + +log4cplus.logger.info=info +log4cplus.appender.info=log4cplus::RollingFileAppender +log4cplus.appender.info.MaxFileSize=50MB +log4cplus.appender.info.MaxBackupIndex=10 +log4cplus.appender.info.Append=true +log4cplus.appender.info.layout=log4cplus::PatternLayout +log4cplus.appender.info.layout.ConversionPattern=[%D{%Y-%m-%d %H:%M:%S:%Q}] [%F:%L] %-5p - %m%n +log4cplus.appender.info.Threshold=info +log4cplus.appender.info.append=true +log4cplus.appender.info.File=/octo/ns/sg_agent/logs/sg_agent.info + +log4cplus.logger.warn=warn +log4cplus.appender.warn=log4cplus::RollingFileAppender +log4cplus.appender.warn.MaxFileSize=10MB +log4cplus.appender.warn.MaxBackupIndex=10 +log4cplus.appender.warn.Append=true +log4cplus.appender.warn.layout=log4cplus::PatternLayout +log4cplus.appender.warn.layout.ConversionPattern=[%D{%Y-%m-%d %H:%M:%S:%Q}] [%F:%L] %-5p - %m%n +log4cplus.appender.warn.Threshold=warn +log4cplus.appender.warn.append=true +log4cplus.appender.warn.File=/octo/ns/sg_agent/logs/sg_agent.warn + +log4cplus.logger.error=error +log4cplus.appender.error=log4cplus::RollingFileAppender +log4cplus.appender.error.MaxFileSize=10MB +log4cplus.appender.error.MaxBackupIndex=10 +log4cplus.appender.error.Append=true +log4cplus.appender.error.layout=log4cplus::PatternLayout +log4cplus.appender.error.layout.ConversionPattern=[%D{%Y-%m-%d %H:%M:%S:%Q}] [%F:%L] %-5p - %m%n +log4cplus.appender.error.Threshold=error +log4cplus.appender.error.append=true +log4cplus.appender.error.File=/octo/ns/sg_agent/logs/sg_agent.error + +log4cplus.logger.fatal=fatal +log4cplus.appender.fatal=log4cplus::RollingFileAppender +log4cplus.appender.fatal.MaxFileSize=10MB +log4cplus.appender.fatal.MaxBackupIndex=10 +log4cplus.appender.fatal.Append=true +log4cplus.appender.fatal.layout=log4cplus::PatternLayout +log4cplus.appender.fatal.layout.ConversionPattern=[%D{%Y-%m-%d %H:%M:%S:%Q}] [%F:%L] %-5p - %m%n +log4cplus.appender.fatal.Threshold=fatal +log4cplus.appender.fatal.append=true +log4cplus.appender.fatal.File=/octo/ns/sg_agent/logs/sg_agent.fatal + +log4cplus.logger.statLogger=warn, stat + +log4cplus.appender.stat=log4cplus::RollingFileAppender +log4cplus.appender.stat.MaxFileSize=10MB +log4cplus.appender.stat.MaxBackupIndex=10 +log4cplus.appender.stat.Append=true +log4cplus.appender.stat.layout=log4cplus::PatternLayout +log4cplus.appender.stat.layout.ConversionPattern=[%D{%Y-%m-%d %H:%M:%S:%Q}] [%F:%L] %-5p - %m%n +log4cplus.appender.stat.Threshold=warn +log4cplus.appender.stat.append=true +log4cplus.appender.stat.File=/octo/ns/sg_agent/logs/sg_agent.stat diff --git a/sg_agent/conf/sg_agent_mutable.xml b/sg_agent/conf/sg_agent_mutable.xml new file mode 100644 index 0000000..e8529aa --- /dev/null +++ b/sg_agent/conf/sg_agent_mutable.xml @@ -0,0 +1,68 @@ + + + + com.octo.mns.sg_agent + /octo/ns/sg_agent/log4cplus.conf + + sg_agent-open + + 5266 + + /mns/sankuai/prod + + 4 + + 4 + + 1 + + 4 + + 4 + + 4 + + 30000 + + 3 + + 2 + + 0 + com.meituan.octo.mnsc + 0 + + 600000 + + + + + + 127.0.0.1:2181 + + + 127.0.0.1:2181 + + + + + 127.0.0.1:2181 + + + 127.0.0.1:2181 + + + + + com.meituan.octo.mnsc + + open + + open + + open + + 0 + + 1 + diff --git a/sg_agent/conf/sg_agent_whitelist.xml b/sg_agent/conf/sg_agent_whitelist.xml new file mode 100644 index 0000000..b8d070c --- /dev/null +++ b/sg_agent/conf/sg_agent_whitelist.xml @@ -0,0 +1,35 @@ + + + + octo.naming.dorado + octo.naming.cthrift + + + + octo.naming.server.testa + octo.naming.server.testb + octo.naming.server.testc + octo.naming.user + octo.naming.tair. + + + octo.naming.testa + octo.naming.testb + octo.naming.mnsc + + + octo.naming.testa + octo.naming.agent + + + + octo.naming.testa + octo.naming.testb + + + + 10.0.0.0 + 255.0.0.0 + + + \ No newline at end of file diff --git a/sg_agent/docs/README.md b/sg_agent/docs/README.md new file mode 100644 index 0000000..c3f89e5 --- /dev/null +++ b/sg_agent/docs/README.md @@ -0,0 +1,23 @@ +## SGAgent简介 + + * SGAgent是基于C++开发的服务治理代理,为美团点评OCTO服务治理体系提供支持水平扩展的RPC/HTTP服务治理接入. + * SGAgent作为服务端项目基础组件,提供了通过RPC/HTTP进行服务注册、服务发现等功能. + * SGAgent组件的引入简化了SDK和通信框架的设计,可进行基于标签、服务分组等功能辅助通信框架完成软负载及流量走向定义. + +## 功能简介 + + 服务治理完成服务注册、服务发现的两个主要流程,注册支持按增量和非增量方式,增量方式是指一个服务实例可以包含多种ServiceName接口类型,通过在注册中心建立ServiceName和服务实例的双向映射,可满足按ServiceName和服务实例两种方式进行服务发现. + + (1)**服务分组**:服务分组本质影响服务节点权重(权重的调整可按照用户进行自定义),服务分组只有在注册中心配置了路由策略且生效才会最终影响到权重过滤,目前支持的几种策略如下 + + a.自定义路由分组:在服务端配置该策略后,可定向指定上游打入该服务的服务范围; + + b.同机房优先分组:是默认分组,自动开启,流量优先在同机房进行调用. + + c.同中心优先分组: 默认不开启,流量在同中心进行调用. + + d.同城市路由分组: 在同域进行流量的调用. + + (2)**标签过滤**: 对于服务提供者自定义了标签属性的服务发现流程,可按照传入标签返回对应感兴趣服务提供者信息. + + (3)**HTTP接口**: 支持HTTP接口进行服务发现. \ No newline at end of file diff --git a/sg_agent/patch/0001-add-patch-for-http.patch b/sg_agent/patch/0001-add-patch-for-http.patch new file mode 100644 index 0000000..7206124 --- /dev/null +++ b/sg_agent/patch/0001-add-patch-for-http.patch @@ -0,0 +1,97 @@ +From 8a663a187142a030d762f111540bf3e2472ae17b Mon Sep 17 00:00:00 2001 +From: huixiangbo +Date: Sun, 16 Dec 2018 01:35:28 +0800 +Subject: [PATCH] add patch for http + +--- + CMakeLists.txt | 2 +- + muduo/net/http/HttpContext.h | 21 +++++++++++++++++++++ + muduo/net/http/HttpRequest.h | 10 ++++++++++ + 3 files changed, 32 insertions(+), 1 deletion(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index fcb8103..b525072 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -11,7 +11,7 @@ endif() + set(CXX_FLAGS + -g + # -DVALGRIND +- # -DMUDUO_STD_STRING ++ -DMUDUO_STD_STRING + -DCHECK_PTHREAD_RETURN_VALUE + -D_FILE_OFFSET_BITS=64 + -Wall +diff --git a/muduo/net/http/HttpContext.h b/muduo/net/http/HttpContext.h +index b550b7f..861c6bd 100644 +--- a/muduo/net/http/HttpContext.h ++++ b/muduo/net/http/HttpContext.h +@@ -43,9 +43,30 @@ class HttpContext : public muduo::copyable + // return false if any error + bool parseRequest(Buffer* buf, Timestamp receiveTime); + ++ bool expectRequestLine() const ++ { return state_ == kExpectRequestLine; } ++ ++ bool expectHeaders() const ++ { return state_ == kExpectHeaders; } ++ ++ bool expectBody() const ++ { return state_ == kExpectBody; } ++ + bool gotAll() const + { return state_ == kGotAll; } + ++ void receiveRequestLine() ++ { state_ = kExpectHeaders; } ++ ++ void receiveHeaders() ++ { state_ = kExpectBody;} // chaoshu ++ ++ void receiveBody() ++ { state_ = kGotAll; } //chaoshu ++ ++ void receiveAll() ++ { state_ = kGotAll; } //chaoshu, use for ONLY head, NO body ++ + void reset() + { + state_ = kExpectRequestLine; +diff --git a/muduo/net/http/HttpRequest.h b/muduo/net/http/HttpRequest.h +index 7ecad6d..d957ef5 100644 +--- a/muduo/net/http/HttpRequest.h ++++ b/muduo/net/http/HttpRequest.h +@@ -162,6 +162,14 @@ class HttpRequest : public muduo::copyable + const std::map& headers() const + { return headers_; } + ++ void setBody(const char* start, const char* end) //chaoshu ++ { ++ body_.assign(start, end); ++ } ++ ++ const string& body() const //chaoshu ++ { return body_; } ++ + void swap(HttpRequest& that) + { + std::swap(method_, that.method_); +@@ -170,6 +178,7 @@ class HttpRequest : public muduo::copyable + query_.swap(that.query_); + receiveTime_.swap(that.receiveTime_); + headers_.swap(that.headers_); ++ body_.assign(that.body_); //chaoshu + } + + private: +@@ -179,6 +188,7 @@ class HttpRequest : public muduo::copyable + string query_; + Timestamp receiveTime_; + std::map headers_; ++ string body_; //chaoshu + }; + + } +-- +1.7.12.4 + diff --git a/sg_agent/src/cmake/CMakeLists.download_gtest.in b/sg_agent/src/cmake/CMakeLists.download_gtest.in new file mode 100644 index 0000000..da9f6f5 --- /dev/null +++ b/sg_agent/src/cmake/CMakeLists.download_gtest.in @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.8.10) + +project(googletest-download NONE) + +include(ExternalProject) +ExternalProject_Add(googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.8.0 + SOURCE_DIR "${PROJECT_BINARY_DIR}/googletest-src" + BINARY_DIR "${PROJECT_BINARY_DIR}/googletest-build" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" +) diff --git a/sg_agent/src/cmake/CodeCoverage.cmake b/sg_agent/src/cmake/CodeCoverage.cmake new file mode 100644 index 0000000..1629bd4 --- /dev/null +++ b/sg_agent/src/cmake/CodeCoverage.cmake @@ -0,0 +1,235 @@ +# Copyright (c) 2012 - 2017, Lars Bilke +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# CHANGES: +# +# 2012-01-31, Lars Bilke +# - Enable Code Coverage +# +# 2013-09-17, Joakim Söderberg +# - Added support for Clang. +# - Some additional usage instructions. +# +# 2016-02-03, Lars Bilke +# - Refactored functions to use named parameters +# +# 2017-06-02, Lars Bilke +# - Merged with modified version from github.com/ufz/ogs +# +# +# USAGE: +# +# 1. Copy this file into your cmake modules path. +# +# 2. Add the following line to your CMakeLists.txt: +# include(CodeCoverage) +# +# 3. Append necessary compiler flags: +# APPEND_COVERAGE_COMPILER_FLAGS() +# +# 4. If you need to exclude additional directories from the report, specify them +# using the COVERAGE_EXCLUDES variable before calling SETUP_TARGET_FOR_COVERAGE. +# Example: +# set(COVERAGE_EXCLUDES 'dir1/*' 'dir2/*') +# +# 5. Use the functions described below to create a custom make target which +# runs your test executable and produces a code coverage report. +# +# 6. Build a Debug build: +# cmake -DCMAKE_BUILD_TYPE=Debug .. +# make +# make my_coverage_target +# + +include(CMakeParseArguments) + +# Check prereqs +find_program( GCOV_PATH gcov ) +find_program( LCOV_PATH lcov ) +find_program( GENHTML_PATH genhtml ) +find_program( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/scripts/test) +find_program( SIMPLE_PYTHON_EXECUTABLE python ) + +if(NOT GCOV_PATH) + message(FATAL_ERROR "gcov not found! Aborting...") +endif() # NOT GCOV_PATH + +if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") + if("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3) + message(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...") + endif() +elseif(NOT CMAKE_COMPILER_IS_GNUCXX) + message(FATAL_ERROR "Compiler is not GNU gcc! Aborting...") +endif() + +set(COVERAGE_COMPILER_FLAGS "-g -O0 --coverage -fprofile-arcs -ftest-coverage" + CACHE INTERNAL "") + +set(CMAKE_CXX_FLAGS_COVERAGE + ${COVERAGE_COMPILER_FLAGS} + CACHE STRING "Flags used by the C++ compiler during coverage builds." + FORCE ) +set(CMAKE_C_FLAGS_COVERAGE + ${COVERAGE_COMPILER_FLAGS} + CACHE STRING "Flags used by the C compiler during coverage builds." + FORCE ) +set(CMAKE_EXE_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used for linking binaries during coverage builds." + FORCE ) +set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used by the shared libraries linker during coverage builds." + FORCE ) +mark_as_advanced( + CMAKE_CXX_FLAGS_COVERAGE + CMAKE_C_FLAGS_COVERAGE + CMAKE_EXE_LINKER_FLAGS_COVERAGE + CMAKE_SHARED_LINKER_FLAGS_COVERAGE ) + +if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug") + message(WARNING "Code coverage results with an optimised (non-Debug) build may be misleading") +endif() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug" + +if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + link_libraries(gcov) +else() + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") +endif() + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# SETUP_TARGET_FOR_COVERAGE( +# NAME testrunner_coverage # New target name +# EXECUTABLE testrunner -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES testrunner # Dependencies to build first +# ) +function(SETUP_TARGET_FOR_COVERAGE) + + set(options NONE) + set(oneValueArgs NAME) + set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT LCOV_PATH) + message(FATAL_ERROR "lcov not found! Aborting...") + endif() # NOT LCOV_PATH + + if(NOT GENHTML_PATH) + message(FATAL_ERROR "genhtml not found! Aborting...") + endif() # NOT GENHTML_PATH + + # Setup target + add_custom_target(${Coverage_NAME} + + # Cleanup lcov + COMMAND ${LCOV_PATH} --directory . --zerocounters + + # Run tests + COMMAND ${Coverage_EXECUTABLE} + + # Capturing lcov counters and generating report + COMMAND ${LCOV_PATH} --directory . --capture --output-file ${Coverage_NAME}.info + COMMAND ${LCOV_PATH} --remove ${Coverage_NAME}.info ${COVERAGE_EXCLUDES} --output-file ${Coverage_NAME}.info.cleaned + COMMAND ${GENHTML_PATH} -o ${Coverage_NAME} ${Coverage_NAME}.info.cleaned + COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.info ${Coverage_NAME}.info.cleaned + + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." + ) + + # Show info where to find the report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Open ./${Coverage_NAME}/index.html in your browser to view the coverage report." + ) + +endfunction() # SETUP_TARGET_FOR_COVERAGE + +# Defines a target for running and collection code coverage information +# Builds dependencies, runs the given executable and outputs reports. +# NOTE! The executable should always have a ZERO as exit code otherwise +# the coverage generation will not complete. +# +# SETUP_TARGET_FOR_COVERAGE_COBERTURA( +# NAME ctest_coverage # New target name +# EXECUTABLE ctest -j ${PROCESSOR_COUNT} # Executable in PROJECT_BINARY_DIR +# DEPENDENCIES executable_target # Dependencies to build first +# ) +function(SETUP_TARGET_FOR_COVERAGE_COBERTURA) + + set(options NONE) + set(oneValueArgs NAME) + set(multiValueArgs EXECUTABLE EXECUTABLE_ARGS DEPENDENCIES) + cmake_parse_arguments(Coverage "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT SIMPLE_PYTHON_EXECUTABLE) + message(FATAL_ERROR "python not found! Aborting...") + endif() # NOT SIMPLE_PYTHON_EXECUTABLE + + if(NOT GCOVR_PATH) + message(FATAL_ERROR "gcovr not found! Aborting...") + endif() # NOT GCOVR_PATH + + # Combine excludes to several -e arguments + set(COBERTURA_EXCLUDES "") + foreach(EXCLUDE ${COVERAGE_EXCLUDES}) + set(COBERTURA_EXCLUDES "-e ${EXCLUDE} ${COBERTURA_EXCLUDES}") + endforeach() + + add_custom_target(${Coverage_NAME} + + # Run tests + ${Coverage_EXECUTABLE} + + # Running gcovr + COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} ${COBERTURA_EXCLUDES} + -o ${Coverage_NAME}.xml + WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + DEPENDS ${Coverage_DEPENDENCIES} + COMMENT "Running gcovr to produce Cobertura code coverage report." + ) + + # Show info where to find the report + add_custom_command(TARGET ${Coverage_NAME} POST_BUILD + COMMAND ; + COMMENT "Cobertura code coverage report saved in ${Coverage_NAME}.xml." + ) + +endfunction() # SETUP_TARGET_FOR_COVERAGE_COBERTURA + +function(APPEND_COVERAGE_COMPILER_FLAGS) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COVERAGE_COMPILER_FLAGS}" PARENT_SCOPE) + message(STATUS "Appending code coverage compiler flags: ${COVERAGE_COMPILER_FLAGS}") +endfunction() # APPEND_COVERAGE_COMPILER_FLAGS + diff --git a/sg_agent/src/cmake/FindBoost.cmake b/sg_agent/src/cmake/FindBoost.cmake new file mode 100644 index 0000000..8b5cf4c --- /dev/null +++ b/sg_agent/src/cmake/FindBoost.cmake @@ -0,0 +1,26 @@ +# FindBoost +# -------- +# +# Find boost +# +# Find the boost includes and library. Once done this will define +# +# BOOST_INCLUDE_DIRS - where to find boost include, etc. +# BOOST_FOUND - True if boost found. +# +set(BOOST_INCLUDE_DIR ${THIRD_MODULE_PATH}/boost_1_59_0/) + +#message(${BOOST_INCLUDE_DIRS}) +find_path(BOOST_INCLUDE_DIR NAMES boost) + +mark_as_advanced(BOOST_INCLUDE_DIR) + +# handle the QUIETLY and REQUIRED arguments and set BOOST_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Boost REQUIRED_VARS BOOST_INCLUDE_DIR) + +if(BOOST_FOUND) + set(BOOST_INCLUDE_DIRS ${BOOST_INCLUDE_DIR}) +endif() + diff --git a/sg_agent/src/cmake/FindCthrift.cmake b/sg_agent/src/cmake/FindCthrift.cmake new file mode 100644 index 0000000..7b637f5 --- /dev/null +++ b/sg_agent/src/cmake/FindCthrift.cmake @@ -0,0 +1,27 @@ +# FindCthrift +# -------- +# +# Find Cthrift +# +# Find the Cthrift includes and library. Once done this will define +# +# CTHRIFT_INCLUDE_DIRS - where to find cthrift include, etc. +# CTHRIFT_FOUND - True if cthrift found. +# +set(CTHRIFT_INCLUDE_DIR ${SGAGENT_MODULE_PATH}/cthrift/include) + +#message(${CTHRIFT_INCLUDE_DIR}) +find_path(CTHRIFT_INCLUDE_DIR NAMES cthrift) + +mark_as_advanced(cthrift_INCLUDE_DIR) + +# handle the QUIETLY and REQUIRED arguments and set CTHRIFT_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Cthrift REQUIRED_VARS CTHRIFT_INCLUDE_DIR) + +if(CTHRIFT_FOUND) + set(CTHRIFT_INCLUDE_DIRS ${CTHRIFT_INCLUDE_DIR}) +endif() + +set(CTHRIFT_LIBRARY ${SGAGENT_MODULE_PATH}/cthrift/lib/libcthrift.a) diff --git a/sg_agent/src/cmake/FindCurl.cmake b/sg_agent/src/cmake/FindCurl.cmake new file mode 100644 index 0000000..8709248 --- /dev/null +++ b/sg_agent/src/cmake/FindCurl.cmake @@ -0,0 +1,20 @@ +set(CURL_INCLUDE_DIR ${SGAGENT_MODULE_PATH}/curl/include/) +set(CURL_LIBRARY ${SGAGENT_MODULE_PATH}/curl/lib/libcurl.a) + + +#message(${CURL_INCLUDE_DIRS}) +find_path(CURL_INCLUDE_DIR NAMES curl) +find_library(CURL_LIBRARY NAMES curl) + +mark_as_advanced(CURL_LIBRARY CURL_INCLUDE_DIR) + + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Curl REQUIRED_VARS CURL_LIBRARY CURL_INCLUDE_DIR) + +set(CURL_FOUND TRUE) +if(CURL_FOUND) + set(CURL_INCLUDE_DIR ${CURL_INCLUDE_DIR}) + set(CURL_LIBRARY ${CURL_LIBRARY}) +endif() + diff --git a/sg_agent/src/cmake/FindLog4cplus.cmake b/sg_agent/src/cmake/FindLog4cplus.cmake new file mode 100644 index 0000000..925be2d --- /dev/null +++ b/sg_agent/src/cmake/FindLog4cplus.cmake @@ -0,0 +1,33 @@ +# FindLog4cplus +# -------- +# +# Find log4cplus +# +# Find the log4cplus includes and library. Once done this will define +# +# LOG4CPLUS_INCLUDE_DIRS - where to find log4cplus include, etc. +# LOG4CPLUS_FOUND - True if log4cplus found. +# + +set(LOG4CPLUS_INCLUDE_DIR ${SGAGENT_MODULE_PATH}/logs/include/) +set(LOG4CPLUS_LIBRARY ${SGAGENT_MODULE_PATH}/logs/lib/liblog4cplus.a) + + +#message(${CURL_INCLUDE_DIRS}) +find_path(LOG4CPLUS_INCLUDE_DIR NAMES log4cplus) +find_library(LOG4CPLUS_LIBRARY NAMES log4cplus) + +mark_as_advanced(LOG4CPLUS_LIBRARY LOG4CPLUS_INCLUDE_DIR) + + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Log4cplus REQUIRED_VARS LOG4CPLUS_LIBRARY + LOG4CPLUS_INCLUDE_DIR) + +set(LOG4CPLUS_FOUND TRUE) +if(LOG4CPLUS_FOUND) + set(LOG4CPLUS_INCLUDE_DIR ${LOG4CPLUS_INCLUDE_DIR}) + set(LOG4CPLUS_LIBRARY ${LOG4CPLUS_LIBRARY}) + message(STATUS "${LOG4CPLUS_INCLUDE_DIR}") + message(STATUS "${LOG4CPLUS_LIBRARY}") +endif() \ No newline at end of file diff --git a/sg_agent/src/cmake/FindMuduo.cmake b/sg_agent/src/cmake/FindMuduo.cmake new file mode 100644 index 0000000..ae6affe --- /dev/null +++ b/sg_agent/src/cmake/FindMuduo.cmake @@ -0,0 +1,42 @@ +# FindMuduo +# -------- +# +# Find muduo +# +# Find the muduo includes and library. Once done this will define +# +# MUDUO_INCLUDE_DIRS - where to find muduo include, etc. +# MUDUO_BASE_LIBRARIES - List of libraries when using muduo_base. +# MUDUO_NET_LIBRARIES - List of libraries when using muduo_net. +# MUDUO_HTTP_LIBRARIES - List of libraries when using muduo_http. +# MUDUO_FOUND - True if muduo found. +# +set(MUDUO_INCLUDE_DIR /usr/include/) +set(MUDUO_INCLUDE_BASE_DIR /usr/include/muduo/base) +set(MUDUO_INCLUDE_NET_DIR /usr/include/muduo/muduo/net) +set(MUDUO_BASE_LIBRARY /usr/lib64/libmuduo_base.a) +set(MUDUO_NET_LIBRARY /usr/lib64/libmuduo_net.a) +set(MUDUO_HTTP_LIBRARY /usr/lib64/libmuduo_http.a) + +#message(${MUDUO_INCLUDE_DIRS}) +find_path(MUDUO_INCLUDE_DIR NAMES muduo) +find_library(MUDUO_BASE_LIBRARY NAMES muduo_base) +find_library(MUDUO_NET_LIBRARY NAMES muduo_net) +find_library(MUDUO_HTTP_LIBRARY NAMES muduo_http) + +mark_as_advanced(MUDUO_BASE_LIBRARY MUDUO_NET_LIBRARY + MUDUO_HTTP_LIBRARY MUDUO_INCLUDE_DIR) + +# handle the QUIETLY and REQUIRED arguments and set MUDUO_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Muduo REQUIRED_VARS MUDUO_BASE_LIBRARY MUDUO_NET_LIBRARY + MUDUO_HTTP_LIBRARY MUDUO_INCLUDE_DIR) + +if(MUDUO_FOUND) + set(MUDUO_INCLUDE_DIRS ${MUDUO_INCLUDE_DIR}) + set(MUDUO_BASE_LIBRARIES ${MUDUO_BASE_LIBRARY} pthread rt) + set(MUDUO_NET_LIBRARIES ${MUDUO_NET_LIBRARY} ${MUDUO_BASE_LIBRARIES}) + set(MUDUO_HTTP_LIBRARIES ${MUDUO_HTTP_LIBRARY} ${MUDUO_NET_LIBRARIES}) +endif() + diff --git a/sg_agent/src/cmake/FindThrift.cmake b/sg_agent/src/cmake/FindThrift.cmake new file mode 100644 index 0000000..28805d4 --- /dev/null +++ b/sg_agent/src/cmake/FindThrift.cmake @@ -0,0 +1,55 @@ +# - Find Thrift (a cross platform RPC lib/tool) +# This module defines +# THRIFT_VERSION, version string of ant if found +# THRIFT_INCLUDE_DIR, where to find THRIFT headers +# THRIFT_CONTRIB_DIR, where contrib thrift files (e.g. fb303.thrift) are installed +# THRIFT_LIBS, THRIFT libraries +# THRIFT_FOUND, If false, do not try to use ant + +# prefer the thrift version supplied in THRIFT_HOME +set(THRIFT_INCLUDE_DIR ${THIRD_MODULE_PATH}/thrift-0.8.0_build/include) +find_path(THRIFT_INCLUDE_DIR thrift/Thrift.h) + +set(THRIFT_CONTRIB_DIR ${THIRD_MODULE_PATH}/thrift-0.8.0_build/contrib) +find_path(THRIFT_CONTRIB_DIR fb303/if/fb303.thrift) + +set (THRIFT_LIB_PATHS ${THIRD_MODULE_PATH}/thrift-0.8.0_build/lib) +find_path(THRIFT_LIB_PATH libthrift.a PATHS ${THRIFT_LIB_PATHS}) + +set (THRIFT_STATIC_LIB_PATH ${THIRD_MODULE_PATH}/thrift-0.8.0_build/lib) +find_path(THRIFT_STATIC_LIB_PATH libthrift.a PATHS ${THRIFT_LIB_PATHS}) + +# prefer the thrift version supplied in THRIFT_HOME +find_library(THRIFT_LIB NAMES thrift HINTS ${THRIFT_LIB_PATHS}) +find_library(THRIFTNB_LIB NAMES thriftnb HINTS ${THRIFT_LIB_PATHS}) + +set(THRIFT_COMPILER ${THIRD_MODULE_PATH}/thrift-0.8.0_build/bin/thrift) +find_program(THRIFT_COMPILER thrift) + +if (THRIFT_LIB) + set(THRIFT_FOUND TRUE) + set(THRIFT_LIBS ${THIRD_MODULE_PATH}/thrift-0.8.0_build/lib/libthrift.so) + set(THRIFT_STATIC_LIB ${THRIFT_STATIC_LIB_PATH}/libthrift.a) + set(THRIFTNB_STATIC_LIB ${THRIFT_STATIC_LIB_PATH}/libthriftnb.a) + exec_program(${THRIFT_COMPILER} + ARGS -version OUTPUT_VARIABLE THRIFT_VERSION RETURN_VALUE THRIFT_RETURN) +else () + set(THRIFT_FOUND FALSE) +endif () + +if (THRIFT_FOUND) + if (NOT THRIFT_FIND_QUIETLY) + message(STATUS "${THRIFT_VERSION}") + endif () +else () + message(STATUS "Thrift compiler/libraries NOT found. " + "Thrift support will be disabled (${THRIFT_RETURN}, " + "${THRIFT_INCLUDE_DIR}, ${THRIFT_LIB})") +endif () + + +mark_as_advanced( + THRIFT_LIB + THRIFT_COMPILER + THRIFT_INCLUDE_DIR +) diff --git a/sg_agent/src/cmake/FindZookeeper.cmake b/sg_agent/src/cmake/FindZookeeper.cmake new file mode 100644 index 0000000..8338185 --- /dev/null +++ b/sg_agent/src/cmake/FindZookeeper.cmake @@ -0,0 +1,27 @@ +# FindZookeeper +# -------- +# +# Find zookeeper +# +# Find the zookeeper includes and library. Once done this will define +# +# ZOOKEEPER_LIBRARIES - List of libraries when using zookeeper_base. +# ZOOKEEPER_FOUND - True if zookeeper found. +# +set(ZOOKEEPER_LIBRARY ${THIRD_MODULE_PATH}/zookeeper/libzookeeper_mt.a) + +find_library(ZOOKEEPER_LIBRARY NAMES zookeeper_mt) + +set(ZOOKEEPER_INCLUDE_DIR ${THIRD_MODULE_PATH}/zookeeper/include) + +mark_as_advanced(ZOOKEEPER_LIBRARY ZOOKEEPER_INCLUDE_DIR) + +# handle the QUIETLY and REQUIRED arguments and set ZOOKEEPER_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Zookeeper REQUIRED_VARS ZOOKEEPER_LIBRARY) + +if(ZOOKEEPER_FOUND) + set(ZOOKEEPER_LIBRARIES ${ZOOKEEPER_LIBRARY}) +endif() + diff --git a/sg_agent/src/cmake/SetupGtest.cmake b/sg_agent/src/cmake/SetupGtest.cmake new file mode 100644 index 0000000..869becd --- /dev/null +++ b/sg_agent/src/cmake/SetupGtest.cmake @@ -0,0 +1,24 @@ +# Setup googletest +configure_file("${PROJECT_SOURCE_DIR}/cmake/CMakeLists.download_gtest.in" ${PROJECT_BINARY_DIR}/googletest-download/CMakeLists.txt) + +execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/googletest-download + ) +if(result) + message(FATAL_ERROR "CMake step for googletest failed: ${result}") +endif() + +execute_process(COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/googletest-download + ) +if(result) + message(FATAL_ERROR "Build step for googletest failed: ${result}") +endif() + +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +add_subdirectory(${PROJECT_BINARY_DIR}/googletest-src + ${PROJECT_BINARY_DIR}/googletest-build + EXCLUDE_FROM_ALL) diff --git a/sg_agent/src/comm/buffer_mgr.h b/sg_agent/src/comm/buffer_mgr.h new file mode 100644 index 0000000..24f1aba --- /dev/null +++ b/sg_agent/src/comm/buffer_mgr.h @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef __BUFFER_MGR_H__ +#define __BUFFER_MGR_H__ + +#include +#include "inc_comm.h" +#include "../util/base_errors_consts.h" + +namespace meituan_mns { + +#define STAT_STOPPED 0 +#define STAT_RUNNING 1 +#define RETRYTIMES 2 +#define CYCLE_TIME 10 + +template +class BufferMgr { + public: + + BufferMgr(); + + /* + * 获取缓存信息 + * key:缓存对应的键值 + */ + int get(const std::string key, type &val); + + /* + * 获取缓存信息 + **/ + int get(const std::string key, boost::shared_ptr ptr); + + /* + * 为更新列表插入新的key + */ + int insert(const std::string key, const type &val); + + /* + * 从更新列表删除key,及对应的value + * 线程不安全,慎用 + */ + int del(const std::string key); + + /* + * 获取size + */ + int size(); + int GetKeyList(std::vector &keys); + + ~BufferMgr(); + + private: + + void _clear(); + + std::map *m_data_map; + + pthread_rwlock_t rwlock; +}; + +template +BufferMgr::BufferMgr() { + + m_data_map = new std::map(); + pthread_rwlock_init(&rwlock, NULL); +} + +/* + * 获取key对应的val + * ret:0表示取得数值, -1表示没有对应key + */ +template +int BufferMgr::get(const std::string key, type &val) { + + if (key.empty()) { + return ERR_BUFFERMGR_EMPTYKEY; + } + + if(NULL==m_data_map){ + return ERR_BUFFERMGR_EMPTYKEY; + } + int ret = 0; + // 防止多线程不安全, iter置空的情况 + + pthread_rwlock_rdlock(&rwlock); + typename std::map::iterator iter; + if(key.empty()){ + pthread_rwlock_unlock(&rwlock); + return -1; + } + iter = m_data_map->find(key); + if (m_data_map->end() != iter) { + if(NULL==m_data_map){ + pthread_rwlock_unlock(&rwlock); + return -1; + } + val = m_data_map->at(key); + ret = 0; + } else { + ret = -1; + } + pthread_rwlock_unlock(&rwlock); + return ret; +} + +template +int BufferMgr::insert(const std::string key, const type &val) { + if (NULL == m_data_map) { + return ERR_BUFFERMGR_BUFHEAD_NULL; + } + pthread_rwlock_wrlock(&rwlock); + typename std::map::iterator iter; + iter = m_data_map->find(key); + if (m_data_map->end() != iter) { + //如果map中已经存在,则只替换val + iter->second = val; + } else { + //如果map中不存在,则insert pair + m_data_map->insert(std::pair(key, val)); + } + pthread_rwlock_unlock(&rwlock); + return 0; +} + +template +int BufferMgr::size() { + if (NULL == m_data_map) { + return 0; + } + int size = 0; + pthread_rwlock_rdlock(&rwlock); + size = m_data_map->size(); + pthread_rwlock_unlock(&rwlock); + return size; +} + +/** + * return 0: succeed to delete or map don't has this key + * other: error + */ +template +int BufferMgr::del(std::string key) { + if (NULL == m_data_map) { + return ERR_BUFFERMGR_BUFHEAD_NULL; + } + pthread_rwlock_wrlock(&rwlock); + typename std::map::iterator iter; + iter = m_data_map->find(key); + if (m_data_map->end() != iter) { + m_data_map->erase(iter); + } + pthread_rwlock_unlock(&rwlock); + return 0; +} + +/* + * 析构函数 + * 清理map数据 + * + */ +template +BufferMgr::~BufferMgr() { + SAFE_DELETE(m_data_map); + pthread_rwlock_destroy(&rwlock); +} + +/* + * clear map + */ +template +void BufferMgr::_clear() { + m_data_map->clear(); +} +/* + * get keylist + * */ +template +int BufferMgr::GetKeyList(std::vector &keys) { + if (NULL == m_data_map) { + return ERR_BUFFERMGR_BUFHEAD_NULL; + } + pthread_rwlock_rdlock(&rwlock); + typename std::map::iterator iter; + for (iter = m_data_map->begin(); iter != m_data_map->end(); iter++) { + keys.push_back(iter->first); + } + pthread_rwlock_unlock(&rwlock); + + return keys.size(); +} + +} //namespace sg_buffermgr +#endif diff --git a/sg_agent/src/comm/cJSON.c b/sg_agent/src/comm/cJSON.c new file mode 100644 index 0000000..31c43dd --- /dev/null +++ b/sg_agent/src/comm/cJSON.c @@ -0,0 +1,596 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +#include +#include +#include +#include +#include +#include +#include +#include "cJSON.h" + +static const char *ep; + +const char *cJSON_GetErrorPtr(void) {return ep;} + +static int cJSON_strcasecmp(const char *s1,const char *s2) +{ + if (!s1) return (s1==s2)?0:1;if (!s2) return 1; + for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; + return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); +} + +static void *(*cJSON_malloc)(size_t sz) = malloc; +static void (*cJSON_free)(void *ptr) = free; + +static char* cJSON_strdup(const char* str) +{ + size_t len; + char* copy; + + len = strlen(str) + 1; + if (!(copy = (char*)cJSON_malloc(len))) return 0; + memcpy(copy,str,len); + return copy; +} + +void cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (!hooks) { /* Reset hooks */ + cJSON_malloc = malloc; + cJSON_free = free; + return; + } + + cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc; + cJSON_free = (hooks->free_fn)?hooks->free_fn:free; +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(void) +{ + cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); + if (node) memset(node,0,sizeof(cJSON)); + return node; +} + +/* Delete a cJSON structure. */ +void cJSON_Delete(cJSON *c) +{ + cJSON *next; + while (c) + { + next=c->next; + if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); + if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); + if (c->string) cJSON_free(c->string); + cJSON_free(c); + c=next; + } +} + +/* Parse the input text to generate a number, and populate the result into item. */ +static const char *parse_number(cJSON *item,const char *num) +{ + double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; + + if (*num=='-') sign=-1,num++; /* Has sign? */ + if (*num=='0') num++; /* is zero */ + if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ + if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ + if (*num=='e' || *num=='E') /* Exponent? */ + { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ + while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ + } + + n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ + + item->valuedouble=n; + item->valueint=(int)n; + item->type=cJSON_Number; + return num; +} + +/* Render the number nicely from the given item into a string. */ +static char *print_number(cJSON *item) +{ + char *str; + double d=item->valuedouble; + if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) + { + str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ + if (str) sprintf(str,"%d",item->valueint); + } + else + { + str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ + if (str) + { + if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d); + else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); + else sprintf(str,"%f",d); + } + } + return str; +} + +static unsigned parse_hex4(const char *str) +{ + unsigned h=0; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + h=h<<4;str++; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + h=h<<4;str++; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + h=h<<4;str++; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + return h; +} + +/* Parse the input text into an unescaped cstring, and populate item. */ +static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; +static const char *parse_string(cJSON *item,const char *str) +{ + const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; + if (*str!='\"') {ep=str;return 0;} /* not a string! */ + + while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ + + out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ + if (!out) return 0; + + ptr=str+1;ptr2=out; + while (*ptr!='\"' && *ptr) + { + if (*ptr!='\\') *ptr2++=*ptr++; + else + { + ptr++; + switch (*ptr) + { + case 'b': *ptr2++='\b'; break; + case 'f': *ptr2++='\f'; break; + case 'n': *ptr2++='\n'; break; + case 'r': *ptr2++='\r'; break; + case 't': *ptr2++='\t'; break; + case 'u': /* transcode utf16 to utf8. */ + uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */ + + if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */ + + if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */ + { + if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */ + uc2=parse_hex4(ptr+3);ptr+=6; + if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */ + uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); + } + + len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; + + switch (len) { + case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 1: *--ptr2 =(uc | firstByteMark[len]); + } + ptr2+=len; + break; + default: *ptr2++=*ptr; break; + } + ptr++; + } + } + *ptr2=0; + if (*ptr=='\"') ptr++; + item->valuestring=out; + item->type=cJSON_String; + return ptr; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static char *print_string_ptr(const char *str) +{ + const char *ptr;char *ptr2,*out;int len=0;unsigned char token; + + if (!str) return cJSON_strdup(""); + ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;} + + out=(char*)cJSON_malloc(len+3); + if (!out) return 0; + + ptr2=out;ptr=str; + *ptr2++='\"'; + while (*ptr) + { + if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; + else + { + *ptr2++='\\'; + switch (token=*ptr++) + { + case '\\': *ptr2++='\\'; break; + case '\"': *ptr2++='\"'; break; + case '\b': *ptr2++='b'; break; + case '\f': *ptr2++='f'; break; + case '\n': *ptr2++='n'; break; + case '\r': *ptr2++='r'; break; + case '\t': *ptr2++='t'; break; + default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ + } + } + } + *ptr2++='\"';*ptr2++=0; + return out; +} +/* Invote print_string_ptr (which is useful) on an item. */ +static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);} + +/* Predeclare these prototypes. */ +static const char *parse_value(cJSON *item,const char *value); +static char *print_value(cJSON *item,int depth,int fmt); +static const char *parse_array(cJSON *item,const char *value); +static char *print_array(cJSON *item,int depth,int fmt); +static const char *parse_object(cJSON *item,const char *value); +static char *print_object(cJSON *item,int depth,int fmt); + +/* Utility to jump whitespace and cr/lf */ +static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} + +/* Parse an object - create a new root, and populate. */ +cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated) +{ + const char *end=0; + cJSON *c=cJSON_New_Item(); + ep=0; + if (!c) return 0; /* memory fail */ + + end=parse_value(c,skip(value)); + if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */ + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}} + if (return_parse_end) *return_parse_end=end; + return c; +} +/* Default options for cJSON_Parse */ +cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);} + +/* Render a cJSON item/entity/structure to text. */ +char *cJSON_Print(cJSON *item) {return print_value(item,0,1);} +char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);} + +/* Parser core - when encountering text, process appropriately. */ +static const char *parse_value(cJSON *item,const char *value) +{ + if (!value) return 0; /* Fail on null. */ + if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } + if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } + if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } + if (*value=='\"') { return parse_string(item,value); } + if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } + if (*value=='[') { return parse_array(item,value); } + if (*value=='{') { return parse_object(item,value); } + + ep=value;return 0; /* failure. */ +} + +/* Render a value to text. */ +static char *print_value(cJSON *item,int depth,int fmt) +{ + char *out=0; + if (!item) return 0; + switch ((item->type)&255) + { + case cJSON_NULL: out=cJSON_strdup("null"); break; + case cJSON_False: out=cJSON_strdup("false");break; + case cJSON_True: out=cJSON_strdup("true"); break; + case cJSON_Number: out=print_number(item);break; + case cJSON_String: out=print_string(item);break; + case cJSON_Array: out=print_array(item,depth,fmt);break; + case cJSON_Object: out=print_object(item,depth,fmt);break; + } + return out; +} + +/* Build an array from input text. */ +static const char *parse_array(cJSON *item,const char *value) +{ + cJSON *child; + if (*value!='[') {ep=value;return 0;} /* not an array! */ + + item->type=cJSON_Array; + value=skip(value+1); + if (*value==']') return value+1; /* empty array. */ + + item->child=child=cJSON_New_Item(); + if (!item->child) return 0; /* memory fail */ + value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ + if (!value) return 0; + + while (*value==',') + { + cJSON *new_item; + if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ + child->next=new_item;new_item->prev=child;child=new_item; + value=skip(parse_value(child,skip(value+1))); + if (!value) return 0; /* memory fail */ + } + + if (*value==']') return value+1; /* end of array */ + ep=value;return 0; /* malformed. */ +} + +/* Render an array to text */ +static char *print_array(cJSON *item,int depth,int fmt) +{ + char **entries; + char *out=0,*ptr,*ret;int len=5; + cJSON *child=item->child; + int numentries=0,i=0,fail=0; + + /* How many entries in the array? */ + while (child) numentries++,child=child->next; + /* Explicitly handle numentries==0 */ + if (!numentries) + { + out=(char*)cJSON_malloc(3); + if (out) strcpy(out,"[]"); + return out; + } + /* Allocate an array to hold the values for each */ + entries=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!entries) return 0; + memset(entries,0,numentries*sizeof(char*)); + /* Retrieve all the results: */ + child=item->child; + while (child && !fail) + { + ret=print_value(child,depth+1,fmt); + entries[i++]=ret; + if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1; + child=child->next; + } + + /* If we didn't fail, try to malloc the output string */ + if (!fail) out=(char*)cJSON_malloc(len); + /* If that fails, we fail. */ + if (!out) fail=1; + + /* Handle failure. */ + if (fail) + { + for (i=0;itype=cJSON_Object; + value=skip(value+1); + if (*value=='}') return value+1; /* empty array. */ + + item->child=child=cJSON_New_Item(); + if (!item->child) return 0; + value=skip(parse_string(child,skip(value))); + if (!value) return 0; + child->string=child->valuestring;child->valuestring=0; + if (*value!=':') {ep=value;return 0;} /* fail! */ + value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ + if (!value) return 0; + + while (*value==',') + { + cJSON *new_item; + if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ + child->next=new_item;new_item->prev=child;child=new_item; + value=skip(parse_string(child,skip(value+1))); + if (!value) return 0; + child->string=child->valuestring;child->valuestring=0; + if (*value!=':') {ep=value;return 0;} /* fail! */ + value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ + if (!value) return 0; + } + + if (*value=='}') return value+1; /* end of array */ + ep=value;return 0; /* malformed. */ +} + +/* Render an object to text. */ +static char *print_object(cJSON *item,int depth,int fmt) +{ + char **entries=0,**names=0; + char *out=0,*ptr,*ret,*str;int len=7,i=0,j; + cJSON *child=item->child; + int numentries=0,fail=0; + /* Count the number of entries. */ + while (child) numentries++,child=child->next; + /* Explicitly handle empty object case */ + if (!numentries) + { + out=(char*)cJSON_malloc(fmt?depth+4:3); + if (!out) return 0; + ptr=out;*ptr++='{'; + if (fmt) {*ptr++='\n';for (i=0;ichild;depth++;if (fmt) len+=depth; + while (child) + { + names[i]=str=print_string_ptr(child->string); + entries[i++]=ret=print_value(child,depth,fmt); + if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1; + child=child->next; + } + + /* Try to allocate the output string */ + if (!fail) out=(char*)cJSON_malloc(len); + if (!out) fail=1; + + /* Handle failure */ + if (fail) + { + for (i=0;ichild;int i=0;while(c)i++,c=c->next;return i;} +cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} +cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} +/* Utility for handling references. */ +static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} + +/* Add item to array/object. */ +void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} +void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} +void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} +void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} + +cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; + if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} +void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} +cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} +void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} + +/* Replace array/object items with new ones. */ +void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; + newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; + if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} +void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} + +/* Create basic types: */ +cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} +cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} +cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} +cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} +cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} +cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} +cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} +cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} + +/* Create Arrays: */ +cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} + +/* Duplication */ +cJSON *cJSON_Duplicate(cJSON *item,int recurse) +{ + cJSON *newitem,*cptr,*nptr=0,*newchild; + /* Bail on bad ptr */ + if (!item) return 0; + /* Create new item */ + newitem=cJSON_New_Item(); + if (!newitem) return 0; + /* Copy over all vars */ + newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; + if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}} + if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}} + /* If non-recursive, then we're done! */ + if (!recurse) return newitem; + /* Walk the ->next chain for the child. */ + cptr=item->child; + while (cptr) + { + newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) {cJSON_Delete(newitem);return 0;} + if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */ + cptr=cptr->next; + } + return newitem; +} + +void cJSON_Minify(char *json) +{ + char *into=json; + while (*json) + { + if (*json==' ') json++; + else if (*json=='\t') json++; // Whitespace characters. + else if (*json=='\r') json++; + else if (*json=='\n') json++; + else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; // double-slash comments, to end of line. + else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} // multiline comments. + else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are \" sensitive. + else *into++=*json++; // All other characters. + } + *into=0; // and null-terminate. +} \ No newline at end of file diff --git a/sg_agent/src/comm/cJSON.h b/sg_agent/src/comm/cJSON.h new file mode 100644 index 0000000..867b7c3 --- /dev/null +++ b/sg_agent/src/comm/cJSON.h @@ -0,0 +1,143 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef cJSON__h +#define cJSON__h + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* cJSON Types: */ +#define cJSON_False 0 +#define cJSON_True 1 +#define cJSON_NULL 2 +#define cJSON_Number 3 +#define cJSON_String 4 +#define cJSON_Array 5 +#define cJSON_Object 6 + +#define cJSON_IsReference 256 + +/* The cJSON structure: */ +typedef struct cJSON { + struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + + int type; /* The type of the item, as above. */ + + char *valuestring; /* The item's string, if type==cJSON_String */ + int valueint; /* The item's number, if type==cJSON_Number */ + double valuedouble; /* The item's number, if type==cJSON_Number */ + + char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ +} cJSON; + +typedef struct cJSON_Hooks { + void *(*malloc_fn)(size_t sz); + void (*free_fn)(void *ptr); +} cJSON_Hooks; + +/* Supply malloc, realloc and free functions to cJSON */ +extern void cJSON_InitHooks(cJSON_Hooks* hooks); + + +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ +extern cJSON *cJSON_Parse(const char *value); +/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ +extern char *cJSON_Print(cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ +extern char *cJSON_PrintUnformatted(cJSON *item); +/* Delete a cJSON entity and all subentities. */ +extern void cJSON_Delete(cJSON *c); + +/* Returns the number of items in an array (or object). */ +extern int cJSON_GetArraySize(cJSON *array); +/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ +extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); +/* Get item "string" from object. Case insensitive. */ +extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); + +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +extern const char *cJSON_GetErrorPtr(void); + +/* These calls create a cJSON item of the appropriate type. */ +extern cJSON *cJSON_CreateNull(void); +extern cJSON *cJSON_CreateTrue(void); +extern cJSON *cJSON_CreateFalse(void); +extern cJSON *cJSON_CreateBool(int b); +extern cJSON *cJSON_CreateNumber(double num); +extern cJSON *cJSON_CreateString(const char *string); +extern cJSON *cJSON_CreateArray(void); +extern cJSON *cJSON_CreateObject(void); + +/* These utilities create an Array of count items. */ +extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); +extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); +extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); +extern cJSON *cJSON_CreateStringArray(const char **strings,int count); + +/* Append item to the specified array/object. */ +extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); + +/* Remove/Detatch items from Arrays/Objects. */ +extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); +extern void cJSON_DeleteItemFromArray(cJSON *array,int which); +extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); +extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); + +/* Update array items. */ +extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); +extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will +need to be released. With recurse!=0, it will duplicate any children connected to the item. +The item->next and ->prev pointers are always zero on return from Duplicate. */ + +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); + +extern void cJSON_Minify(char *json); + +/* Macros for creating things quickly. */ +#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) +#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) +#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) +#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) +#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) +#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) + +/* When assigning an integer value, it needs to be propagated to valuedouble too. */ +#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sg_agent/src/comm/inc_comm.h b/sg_agent/src/comm/inc_comm.h new file mode 100644 index 0000000..b82bf37 --- /dev/null +++ b/sg_agent/src/comm/inc_comm.h @@ -0,0 +1,835 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _INC_COMM_H_ +#define _INC_COMM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "thrift/protocol/TBinaryProtocol.h" +#include "thrift/transport/TSocket.h" +#include "thrift/transport/TTransportUtils.h" + +#include "tinyxml2.h" +#include "log4cplus.h" +#include "md5.h" +#include "../util/base_errors_consts.h" +using namespace ::apache::thrift; +using namespace ::apache::thrift::protocol; +using namespace ::apache::thrift::transport; +using namespace boost; + +namespace meituan_mns { +#define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define SAFE_FREE(p) { if(p) { free(p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + +#ifdef __GNUC__ +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#else +#define likely(x) (x) +#define unlikely(x) (x) +#endif + +const int MAX_INTERFACE_NUM = 32; + +//公用方法 +inline int SplitStringIntoVector(const char *sContent, + const char *sDivider, + std::vector &vecStr) { + char *sNewContent = new char[strlen(sContent) + 1]; + snprintf(sNewContent, strlen(sContent) + 1, "%s", sContent); + char *pStart = sNewContent; + + std::string strContent; + char *pEnd = strstr(sNewContent, sDivider); + if (pEnd == NULL && strlen(sNewContent) > 0) { + strContent = pStart; //get the last one; + vecStr.push_back(strContent); + } + + while (pEnd) { + *pEnd = '\0'; + strContent = pStart; + vecStr.push_back(strContent); + + pStart = pEnd + strlen(sDivider); + if ((*pStart) == '\0') { + break; + } + + pEnd = strstr(pStart, sDivider); + + if (pEnd == NULL) { + strContent = pStart; //get the last one; + vecStr.push_back(strContent); + } + } + + SAFE_DELETE_ARRAY(sNewContent); + return vecStr.size(); +} +//从version中反解mtime +inline int64_t GetMtimeFromVersion(const std::string &version) { + + std::vector version_vec; + int64_t m_time = 0; + + if (!version.empty()) { + SplitStringIntoVector(version.c_str(), "|", version_vec); + if (3 != version_vec.size()) { + NS_LOG_ERROR("the wrong version concludes" << version_vec.size()); + return 0; + } + try { + m_time = boost::lexical_cast(version_vec[0]); + } catch (bad_lexical_cast &ex) { + NS_LOG_ERROR("convert the mtime from version failed,m_time: " << m_time); + } + } + return m_time; +} + +inline std::string Convert(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + + const size_t SIZE = 512; + char buffer[SIZE] = {0}; + vsnprintf(buffer, SIZE, fmt, ap); + + va_end(ap); + + return std::string(buffer); +} + +//根据mtime ,cversion, version拼接版本信息 +inline std::string GetVersion(const int64_t &mtime, const int64_t &cversion, const int64_t &version) { + const size_t SIZE = 512; + char buffer[SIZE] = {0}; + snprintf(buffer, sizeof(buffer), "%lu|%lu|%lu", mtime, cversion, version); + + return std::string(buffer); +} + +/** + * 获取本机IP + * @return 0: success; -1:error + */ +inline int getLocalIp(std::string &ip) { + struct ifaddrs *ifAddrStruct = NULL; + void *tmpAddrPtr = NULL; + + getifaddrs(&ifAddrStruct); + + std::string eth0 = "eth0"; + std::string en0 = "en0"; + std::string em1 = "em1"; + std::string ifa_name; + char addressBufferIPv4[INET_ADDRSTRLEN]; + + while (ifAddrStruct != NULL) { + // To check is it an IPv4 + if (ifAddrStruct->ifa_addr->sa_family == AF_INET) { + // It is a valid IPv4 Address + tmpAddrPtr = &((struct sockaddr_in *) ifAddrStruct->ifa_addr)->sin_addr; + inet_ntop(AF_INET, tmpAddrPtr, addressBufferIPv4, INET_ADDRSTRLEN); + ifa_name = std::string(ifAddrStruct->ifa_name); + if (0 == eth0.compare(ifa_name) || 0 == en0.compare(ifa_name) + || 0 == em1.compare(ifa_name)) { + ip = std::string(addressBufferIPv4); + return 0; + } + } + ifAddrStruct = ifAddrStruct->ifa_next; + } + return -1; +} + +inline int getIntranet(char ip[INET_ADDRSTRLEN], char mask[INET_ADDRSTRLEN]) { + int ret = 0; + + struct ifaddrs *ifAddrStruct = NULL; + struct ifaddrs *ifa = NULL; + void *tmpAddrPtr = NULL; + void *tmpMaskPtr = NULL; + char addrArray[MAX_INTERFACE_NUM][INET_ADDRSTRLEN]; + char maskArray[MAX_INTERFACE_NUM][INET_ADDRSTRLEN]; + getifaddrs(&ifAddrStruct); + int index = 0; + for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) { + if ((NULL == ifa->ifa_addr) || (0 == strcmp(ifa->ifa_name, "vnic"))) { + continue; + } + if (ifa->ifa_addr->sa_family == AF_INET) { // check it is IP4 + tmpAddrPtr = &((struct sockaddr_in *) ifa->ifa_addr)->sin_addr; + inet_ntop(AF_INET, tmpAddrPtr, addrArray[index], INET_ADDRSTRLEN); + if (0 == strcmp(addrArray[index], "127.0.0.1")) { + continue; + } + + tmpMaskPtr = &((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr; + inet_ntop(AF_INET, tmpMaskPtr, maskArray[index], INET_ADDRSTRLEN); + + strcpy(ip, addrArray[index]); + strcpy(mask, maskArray[index]); + if (++index > MAX_INTERFACE_NUM - 1) { + break; + } + + } + } + + if (index > 1) { + int idx = 0; + while (idx < index) { + if (NULL != strstr(addrArray[idx], "10.") + && 0 == strcmp(addrArray[idx], + strstr(addrArray[idx], "10."))) { + strcpy(ip, addrArray[idx]); + strcpy(mask, maskArray[idx]); + } + idx++; + } + } else if (0 >= index) { + NS_LOG_ERROR("not get IP with getIntranet, index = " << index); + ret = -1; + } + + if (ifAddrStruct != NULL) { + freeifaddrs(ifAddrStruct); + } + return ret; +} + +inline int getHost(std::string &ip) { + char hname[1024] = {0}; + gethostname(hname, sizeof(hname)); + struct hostent *hent; + hent = gethostbyname(hname); + if (NULL != hent) { + ip = inet_ntoa(*(struct in_addr *) (hent->h_addr_list[0])); + } else { + ip = ""; + NS_LOG_ERROR("not get IP with getIntranet"); + return -1; + } + return 0; +} + +/** + * 获取本机IP, 因为在连接数超过1024时, 会获取失败, 与getLocalIP一起使用 + * @return 0: success; -1:error + */ +inline int getip(std::string &ip) { + int ret = 0; + char hname[1024] = {0}; + gethostname(hname, sizeof(hname)); + struct hostent *hent; + hent = gethostbyname(hname); + if (NULL != hent) { + ip = inet_ntoa(*(struct in_addr *) (hent->h_addr_list[0])); + } else { + ip = ""; + // 使用另一种方式来获取ip + ret = getLocalIp(ip); + } + return ret; +} + +/** + * 获取本机IP, 因为在连接数超过1024时, 会获取失败, 与getLocalIP一起使用 + * @return 0: success; -1:error + */ +inline int getip2(std::string &ip) { + int ret = 0; + ret = getLocalIp(ip); + if (0 != ret || ip.empty()) { + return getHost(ip); + } + return ret; +} + +//check appkey是否为字母,数字,下划线,减号,点组成 +inline bool IsAppkeyLegal(const std::string &appkey) { + char ch; + for (int i = 0; i < appkey.length(); i++) { + ch = appkey[i]; + if ((ch >= '0') && (ch <= '9')) { + continue; + } else if (((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z'))) { + continue; + } else if ((ch == '-') || (ch == '_') || (ch == '.')) { + continue; + } else { + return false; + } + } + return true; +} + +//check appkey是否为字母,数字,下划线,减号,点组成 +inline bool IsIpAndPortLegal(const std::string &ip, const int port) { + //IP格式*.*.*.*, *为1~3字符 + if ((7 > ip.size()) || (15 < ip.size())) { + return false; + } + + if (0 >= port) { + return false; + } + return true; +} + +const int MAX_PATHLEN = 512; +inline int mkCommonDirs(const char *muldir) { + if (NULL == muldir) { + return -1; + } + int len = strlen(muldir); + if (MAX_PATHLEN <= strlen(muldir)) { + return -1; + } + + NS_LOG_DEBUG("path = " << muldir); + + char path[MAX_PATHLEN]; + strncpy(path, muldir, len); + path[len] = '\0'; + int ret = 0; + for (int i = 0; i < len; i++) { + if ('/' == muldir[i] && 0 != i) { + path[i] = '\0'; + if (access(path, 0) != 0) { + ret = mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + } + path[i] = '/'; + } + } + if (len > 0 && access(path, 0) != 0) { + ret = mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + mkdir(path, S_IREAD | S_IWRITE); + } + return 0; +} + +inline int loadFile(std::string &filecontent, const std::string &filename, const std::string &filepath) { + int ret = -1; + const std::string fullname = filepath + "/" + filename; + std::ifstream in(fullname.c_str()); + if (in.is_open()) { + in.seekg(0, std::ios::end); + filecontent.resize(in.tellg()); + in.seekg(0, std::ios::beg); + in.read(&filecontent[0], filecontent.size()); + in.close(); + ret = 0; + } + + return ret; +} + +//将内容写入临时文件,若写失败返回错误码 +inline int writeToTmp(const std::string &fileContent, const std::string &filename, const std::string &filepath) { + + int ret = mkCommonDirs(filepath.c_str()); + if (SUCCESS == ret) { + + const std::string tmp_file = filepath + "/" + filename + ".tmp"; + std::ofstream fout(tmp_file.c_str()); + if (!fout.is_open()) { + NS_LOG_ERROR("fwrite fail filename = " << filename << "; filepath = " << filepath); + return FAILURE; + } + fout << fileContent; + fout.close(); + std::string tmpFileContent = ""; + std::string tmpMd5 = ""; + std::string loadName = filename + ".tmp"; + ret = loadFile(tmpFileContent, loadName, filepath); + + if (SUCCESS == ret) { + MD5 md5fileContent(fileContent); + MD5 md5fileContentTmp(tmpFileContent); + if (md5fileContent.md5() != md5fileContentTmp.md5()) { + NS_LOG_ERROR("write the tmp file failed, tmp_file filename = " << filename); + return ERR_DISK_WRITE; + } else { + NS_LOG_INFO("write the tmp file success" << filepath); + } + } else { + NS_LOG_INFO("load the has write file failed" << filepath); + } + } + + return ret; +} + +inline int moveForWork(const std::string &filename, const std::string &filepath) { + const std::string tmp_file = filepath + "/" + filename + ".tmp"; + const std::string work_file = filepath + "/" + filename; + std::string cmd = "mv " + tmp_file + " " + work_file; + int status = std::system(cmd.c_str()); + return status; +} + + +//将内容写入临时文件,若写失败返回错误码 +inline int WriteToDisk(const std::string &fileContent, const std::string &filename, const std::string &filepath) { + + int ret = mkCommonDirs(filepath.c_str()); + if (0 == ret) { + + const std::string tmp_file = filepath + "/" + filename + ".tmp"; + std::ofstream fout(tmp_file.c_str()); + if (!fout.is_open()) { + NS_LOG_ERROR("fwrite fail filename = " << filename << "; filepath = " << filepath); + return -1; + } + fout << fileContent; + fout.close(); + std::string tmpFileContent = ""; + std::string tmpMd5 = ""; + std::string loadName = filename + ".tmp"; + ret = loadFile(tmpFileContent, loadName, filepath); + + if (0 == ret) { + MD5 md5fileContent(fileContent); + MD5 md5fileContentTmp(tmpFileContent); + if (md5fileContent.md5() != md5fileContentTmp.md5()) { + NS_LOG_ERROR("write the tmp file failed, tmp_file filename = " << filename); + return -1; + } else { + NS_LOG_INFO("write the tmp file success" << filepath); + const std::string work_file = filepath + "/" + filename; + std::string cmd = "mv " + tmp_file + " " + work_file; + ret = std::system(cmd.c_str()); + } + } else { + NS_LOG_INFO("load the has write file failed" << filepath); + } + } + return ret; +} + +inline void getHostInfo(char hostInfo[256], char ip[INET_ADDRSTRLEN]) { + FILE *fp; + char hostCMD[64] = {0}; + strncpy(hostCMD, "host ", 5); + strncpy(hostCMD + 5, ip, INET_ADDRSTRLEN); + fp = popen(hostCMD, "r"); + fgets(hostInfo, 256, fp); + pclose(fp); + fp = NULL; +} + +inline bool isOnlineHost(char ip[INET_ADDRSTRLEN], std::string &hostType) { + char host[256] = {0}; + getHostInfo(host, ip); + int isOnline = 0; + if (strstr(host, ".office.mos") > 0) { + isOnline = false; + hostType = ".office.mos"; + } else if (strstr(host, "not found") > 0) { + isOnline = false; + hostType = "not found"; + } else if (strstr(host, ".corp.octo.com") > 0) { + isOnline = false; + hostType = ".corp.octo.com"; + } else if (strstr(host, ".octo.com") > 0) { + isOnline = true; + hostType = ".octo.com"; + } + return isOnline; +} + +inline static bool isPortOpen(const std::string &address, int port) { + bool isOpen = false; + + boost::shared_ptr m_socket + = boost::shared_ptr(new TSocket(address, port)); + boost::shared_ptr m_transport + = boost::shared_ptr(new TFramedTransport(m_socket)); + + try { + //设置超时30ms + m_socket->setConnTimeout(30); + m_socket->setLinger(0, 0); + m_transport->open(); + if (m_transport->isOpen()) { + isOpen = true; + } + } catch (TException &tx) { + NS_LOG_ERROR("TException Error: " << tx.what()); + } + if (NULL != m_transport) { + m_transport->close(); + } + return isOpen; +} +inline void unixTime2Str(int time, char str_time[], int buf_len) { + time_t last_time = time; + tm *last_time_tmp = localtime(&last_time); + strftime(str_time, buf_len - 1, "%Y-%m-%d %H:%M:%S", last_time_tmp); + int real_len = strlen(str_time); + str_time[real_len + 1] = '\0'; + NS_LOG_INFO("unixTime2Str:lastupdatedtime = " << str_time); +} +inline int ConvertInt2String(const int &value, std::string &toString) { + int ret = 0; + try { + toString = boost::lexical_cast(value); + } catch (bad_lexical_cast &ex) { + NS_LOG_ERROR("convert the string to int failed,value: " << toString); + ret = -1; + } + return ret; +} +inline long GetProcMemUtil(const int pid) { + + const int INDEX_SPLIT = 1; + long value = 0; + bool find = false; + std::string pid_value = ""; + std::string tmp = "", tmp_value = ""; + std::string vmrss = "", vmrss_value = ""; + std::vector vec_seg_tag; + if (0 != ConvertInt2String(pid, pid_value)) { + return FAILURE; + } + NS_LOG_INFO("the pid is " << pid << "std is: " << pid_value); + std::string name = "/proc/" + pid_value + "/status"; + std::ifstream ifile(name.c_str()); + if (!ifile.is_open()) { + NS_LOG_INFO("faild to open file name: " << name); + ifile.close(); + return -1; + } + while (getline(ifile, tmp)) { + if (std::string::npos != tmp.find("VmRSS")) { + tmp_value = tmp; + find = true; + ifile.close(); + break; + } + } + + if (find) { + boost::split(vec_seg_tag, tmp_value, boost::is_any_of(("\t"))); + if (vec_seg_tag.size() >= INDEX_SPLIT) { + boost::trim(vec_seg_tag[INDEX_SPLIT]); + vmrss = vec_seg_tag[INDEX_SPLIT]; + size_t pos_vmrss = tmp_value.find(" "); + if (std::string::npos != pos_vmrss) { + vmrss_value.assign(vmrss.c_str(), pos_vmrss - 2); + try { + value = boost::lexical_cast(vmrss_value.c_str()); + } catch (bad_lexical_cast &ex) { + NS_LOG_ERROR("convert the string to int failed"); + return -1; + } + } + } + } + if (value < 0) { + NS_LOG_ERROR("value is invalid"); + return -1; + } + return value; +} +inline unsigned int GetProcCpuTime(const int pid) { + + unsigned int proc_util = 0; + const int BEGIN_INDEX = 13, END_INDEX = 16; + std::string pid_value = ""; + std::vector vec_seg_tag; + if (0 != ConvertInt2String(pid, pid_value)) { + return -1; + } + std::string tmpFileContent = ""; + std::string filepath = "/proc/" + pid_value + "/stat"; + std::string tmp = ""; + std::ifstream ifile(filepath.c_str()); + if (!ifile.is_open()) { + NS_LOG_INFO("faild to open file path" << filepath); + ifile.close(); + return -1; + } + while (getline(ifile, tmp)) { + tmpFileContent.append(tmp); + } + boost::split(vec_seg_tag, tmpFileContent, boost::is_any_of((" "))); + for (int pos = BEGIN_INDEX; pos <= END_INDEX; ++pos) { + unsigned int value = 0; + try { + value = boost::lexical_cast(vec_seg_tag[pos].c_str()); + } catch (bad_lexical_cast &ex) { + NS_LOG_ERROR("convert the string to int failed"); + ifile.close(); + return -1; + } + proc_util += value; + } + ifile.close(); + return proc_util; +} +inline unsigned int GetTotalCpuTime() { + + const int NAME_LEN = 16; + unsigned int user = 0, nice = 0, system = 0, idle = 0; + char name[NAME_LEN] = {'0'}; + std::string filepath = "/proc/stat"; + std::string tmp = ""; + std::ifstream ifile(filepath.c_str()); + getline(ifile, tmp); + if (!tmp.empty()) { + sscanf(tmp.c_str(), "%s %u %u %u %u", name, &user, &nice, &system, &idle); + } + return (user + nice + system + idle); +} +inline float Round(float value, unsigned int num) { + + float round_float_num = 0.0; + std::ostringstream f_out; + f_out << std::setiosflags(std::ios::fixed) << std::setprecision(num) << value; + try { + round_float_num = boost::lexical_cast(f_out.str()); + } catch (bad_lexical_cast &ex) { + NS_LOG_ERROR("convert the f_out to float failed,round_float_num: " << round_float_num); + return -1; + } + return round_float_num; +} + +inline int gzCompress(const char *src, int srcLen, char *dest, int destLen) { + z_stream c_stream; + int err = 0; + int windowBits = 15; + int GZIP_ENCODING = 16; + + if (src && srcLen > 0) { + c_stream.zalloc = (alloc_func) 0; + c_stream.zfree = (free_func) 0; + c_stream.opaque = (voidpf) 0; + if (deflateInit2(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, + windowBits | GZIP_ENCODING, 8, Z_DEFAULT_STRATEGY) != Z_OK) + return FAILURE; + c_stream.next_in = (Bytef *) src; + c_stream.avail_in = srcLen; + c_stream.next_out = (Bytef *) dest; + c_stream.avail_out = destLen; + while (c_stream.avail_in != 0 && c_stream.total_out < destLen) { + if (deflate(&c_stream, Z_NO_FLUSH) != Z_OK) { + NS_LOG_ERROR("Failed to deflate."); + return -1; + } + } + if (c_stream.avail_in != 0) return c_stream.avail_in; + for (;;) { + if ((err = deflate(&c_stream, Z_FINISH)) == Z_STREAM_END) break; + if (err != Z_OK) { + NS_LOG_ERROR("Failed to deflate, err = " << err); + return -1; + } + } + if (deflateEnd(&c_stream) != Z_OK) { + NS_LOG_ERROR("Failed to deflateEnd."); + return -1; + } + return c_stream.total_out; + } + return -1; +} + +inline int32_t Ip2Int(const char *ip) { + if (NULL == ip) { + NS_LOG_ERROR("ip is null"); + return 0; + } + std::vector ips; + SplitStringIntoVector(ip, ".", ips); + if (4 != ips.size()) { + NS_LOG_ERROR("ip form is wrroy, ip = " << ip); + return 0; + } + int32_t res = + (atoi(ips[0].c_str()) << 24) + (atoi(ips[1].c_str()) << 16) + (atoi(ips[2].c_str()) << 8) + atoi(ips[3].c_str()); + return res; +} + +inline long DeltaTime(timeval end, timeval start) { + return (end.tv_sec - start.tv_sec) * 1000000L + + (end.tv_usec - start.tv_usec); +} +/* + * Function name : GetUInt32 + * Creating Time : 2018-3-29 12:04:36 + * Description : 从网络字节顺序的源buf中获得一个UInt32数据,转换成机器字节顺序, + 源buf后移4字节 + * Return type : + * Argument : char const* &pchInSour +*/ +inline unsigned int GetUInt32(const unsigned char *pchInSour) { + unsigned int nRtn; + memcpy(&nRtn, pchInSour, sizeof(nRtn)); + nRtn = ntohl(nRtn); + return nRtn; +} +/* + * Function name : GetUInt16 + * Creating Time : 2018-3-29 12:04:36 + * Description : 从网络字节顺序的源buf中获得一个UInt16数据,转换成机器字节顺序, + 源buf后移2字节 + * Return type : + * Argument : char const* &pchInSour +*/ +inline unsigned short GetUInt16(const unsigned char *pchInSour) { + unsigned short nRtn; + memcpy(&nRtn, pchInSour, 2); + pchInSour += 2; + nRtn = ntohs(nRtn); + return nRtn; +} +inline void SetUInt16(char *&pchIODes, unsigned short u16In) { + u16In = htons(u16In); + memcpy(pchIODes, &u16In, 2); + pchIODes += 2; +} + +inline void SetChars(char *&pDes, const char *pSour, int nSetNum) { + if (NULL == pSour || 0 == nSetNum) { + NS_LOG_INFO("the pSouur is null,or nSetNum is less 0"); + return; + } + memcpy(pDes, pSour, nSetNum); + pDes += nSetNum; +} + +inline void SetUInt32(char *&pchIODes, int u32In) { + u32In = htonl(u32In); + memcpy(pchIODes, &u32In, 4); + pchIODes += 4; +} +inline unsigned int GetBit(unsigned int value, unsigned int index) { + if (index < 0 || index > 31) { + return FAILURE; //如果传入参数有问题,则返回0xff,表示异常 + } + return (value >> index) & 1UL; +} +inline void SetBit(unsigned int &value, unsigned int index, unsigned int set_value) { + + if (index < 0 || index > 31) { + return; + } + if (set_value == 1) { + value |= (1UL << index); // 将index的bit位设置为1,其他位不变 + } else if (set_value == 0) { + value &= ~(1UL << index); // 将index的bit位设置为0,其他位不变 + } else { + NS_LOG_ERROR("the set value is invalid"); + } +} +inline void printfBufferSec(unsigned char *buffer_msg, unsigned int msgLen) { + for (int iter = 0; iter < msgLen; iter++) { + if (iter % 16 == 0) { + NS_LOG_INFO("\n"); + } + NS_LOG_INFO(" %02x " << *(buffer_msg + iter)); + } + NS_LOG_INFO("\n"); +} + +inline void GetString(char const *&pchInSour, char *pOut, int nNum) { + memcpy(pOut, pchInSour, nNum); + pchInSour += nNum; +} + +inline int64_t GetCurrentTime() { + struct timeval tv; + gettimeofday(&tv, NULL); + return (int64_t) tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + +inline std::string CalculateMd5(const std::string &file_name, + const std::string &file_path) { + std::string context = ""; + int32_t ret = loadFile(context, file_name, file_path); + if (SUCCESS != ret) { + NS_LOG_ERROR("failed to load " << file_name); + return ""; + } + MD5 md5_string(context); + return md5_string.md5(); +} + + +} +#endif + diff --git a/sg_agent/src/comm/md5.cc b/sg_agent/src/comm/md5.cc new file mode 100644 index 0000000..aae2673 --- /dev/null +++ b/sg_agent/src/comm/md5.cc @@ -0,0 +1,358 @@ +/* MD5 + converted to C++ class by Frank Thilo (thilo@unix-ag.org) + for bzflag (http://www.bzflag.org) + + based on: + md5.h and md5.c + reference implemantion of RFC 1321 + + Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + +*/ + +/* interface header */ +#include "md5.h" + +/* system implementation headers */ +#include +#include + + +// Constants for MD5Transform routine. +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +/////////////////////////////////////////////// +// F, G, H and I are basic MD5 functions. +inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) { + return (x & y) | ((~x) & z); +} + +inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) { + return (x&z) | (y&~z); +} + +inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) { + return x^y^z; +} + +inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) { + return y ^ (x | ~z); +} + +// rotate_left rotates x left n bits. +inline MD5::uint4 MD5::rotate_left(uint4 x, int n) { + return (x << n) | (x >> (32-n)); +} + +// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +// Rotation is separate from addition to prevent recomputation. +inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a+ F(b,c,d) + x + ac, s) + b; +} + +inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + G(b,c,d) + x + ac, s) + b; +} + +inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + H(b,c,d) + x + ac, s) + b; +} + +inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + I(b,c,d) + x + ac, s) + b; +} + +////////////////////////////////////////////// + +// default ctor, just initailize +MD5::MD5() +{ + init(); +} + +////////////////////////////////////////////// + +// nifty shortcut ctor, compute MD5 for string and finalize it right away +MD5::MD5(const std::string &text) +{ + init(); + update(text.c_str(), text.length()); + finalize(); +} + +////////////////////////////// + +void MD5::init() +{ + finalized=false; + + count[0] = 0; + count[1] = 0; + + // load magic initialization constants. + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; +} + +////////////////////////////// + +// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4. +void MD5::decode(uint4 output[], const uint1 input[], size_type len) +{ + for (unsigned int i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) | + (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24); +} + +////////////////////////////// + +// encodes input (uint4) into output (unsigned char). Assumes len is +// a multiple of 4. +void MD5::encode(uint1 output[], const uint4 input[], size_type len) +{ + for (size_type i = 0, j = 0; j < len; i++, j += 4) { + output[j] = input[i] & 0xff; + output[j+1] = (input[i] >> 8) & 0xff; + output[j+2] = (input[i] >> 16) & 0xff; + output[j+3] = (input[i] >> 24) & 0xff; + } +} + +////////////////////////////// + +// apply MD5 algo on a block +void MD5::transform(const uint1 block[blocksize]) +{ + uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + decode (x, block, blocksize); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + // Zeroize sensitive information. + memset(x, 0, sizeof x); +} + +////////////////////////////// + +// MD5 block update operation. Continues an MD5 message-digest +// operation, processing another message block +void MD5::update(const unsigned char input[], size_type length) +{ + // compute number of bytes mod 64 + size_type index = count[0] / 8 % blocksize; + + // Update number of bits + if ((count[0] += (length << 3)) < (length << 3)) + count[1]++; + count[1] += (length >> 29); + + // number of bytes we need to fill in buffer + size_type firstpart = 64 - index; + + size_type i; + + // transform as many times as possible. + if (length >= firstpart) + { + // fill buffer first, transform + memcpy(&buffer[index], input, firstpart); + transform(buffer); + + // transform chunks of blocksize (64 bytes) + for (i = firstpart; i + blocksize <= length; i += blocksize) + transform(&input[i]); + + index = 0; + } + else + i = 0; + + // buffer remaining input + memcpy(&buffer[index], &input[i], length-i); +} + +////////////////////////////// + +// for convenience provide a verson with signed char +void MD5::update(const char input[], size_type length) +{ + update((const unsigned char*)input, length); +} + +////////////////////////////// + +// MD5 finalization. Ends an MD5 message-digest operation, writing the +// the message digest and zeroizing the context. +MD5& MD5::finalize() +{ + static unsigned char padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + if (!finalized) { + // Save number of bits + unsigned char bits[8]; + encode(bits, count, 8); + + // pad out to 56 mod 64. + size_type index = count[0] / 8 % 64; + size_type padLen = (index < 56) ? (56 - index) : (120 - index); + update(padding, padLen); + + // Append length (before padding) + update(bits, 8); + + // Store state in digest + encode(digest, state, 16); + + // Zeroize sensitive information. + memset(buffer, 0, sizeof buffer); + memset(count, 0, sizeof count); + + finalized=true; + } + + return *this; +} + +////////////////////////////// + +// return hex representation of digest as string +std::string MD5::hexdigest() const +{ + if (!finalized) + return ""; + + char buf[33]; + for (int i=0; i<16; i++) + sprintf(buf+i*2, "%02x", digest[i]); + buf[32]=0; + + return std::string(buf); +} +std::string MD5::md5() const +{ + return hexdigest(); +} + + +////////////////////////////// + +std::ostream& operator<<(std::ostream& out, MD5 md5) +{ + return out << md5.hexdigest(); +} +////////////////////////////// diff --git a/sg_agent/src/comm/md5.h b/sg_agent/src/comm/md5.h new file mode 100644 index 0000000..0a208ef --- /dev/null +++ b/sg_agent/src/comm/md5.h @@ -0,0 +1,92 @@ +/* MD5 + converted to C++ class by Frank Thilo (thilo@unix-ag.org) + for bzflag (http://www.bzflag.org) + + based on: + + md5.h and md5.c + reference implementation of RFC 1321 + + Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All +rights reserved. + +License to copy and use this software is granted provided that it +is identified as the "RSA Data Security, Inc. MD5 Message-Digest +Algorithm" in all material mentioning or referencing this software +or this function. + +License is also granted to make and use derivative works provided +that such works are identified as "derived from the RSA Data +Security, Inc. MD5 Message-Digest Algorithm" in all material +mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either +the merchantability of this software or the suitability of this +software for any particular purpose. It is provided "as is" +without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this +documentation and/or software. + +*/ + +#ifndef BZF_MD5_H +#define BZF_MD5_H + +#include +#include + + +// a small class for calculating MD5 hashes of strings or byte arrays +// it is not meant to be fast or secure +// +// usage: 1) feed it blocks of uchars with update() +// 2) finalize() +// 3) get hexdigest() string +// or +// MD5(std::string).hexdigest() +// +// assumes that char is 8 bit and int is 32 bit +class MD5 +{ +public: + typedef unsigned int size_type; // must be 32bit + + MD5(); + MD5(const std::string& text); + void update(const unsigned char *buf, size_type length); + void update(const char *buf, size_type length); + MD5& finalize(); + std::string hexdigest() const; + std::string md5() const; + friend std::ostream& operator<<(std::ostream&, MD5 md5); + +private: + void init(); + typedef unsigned char uint1; // 8bit + typedef unsigned int uint4; // 32bit + enum {blocksize = 64}; // VC6 won't eat a const static int here + + void transform(const uint1 block[blocksize]); + static void decode(uint4 output[], const uint1 input[], size_type len); + static void encode(uint1 output[], const uint4 input[], size_type len); + + bool finalized; + uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk + uint4 count[2]; // 64bit counter for number of bits (lo, hi) + uint4 state[4]; // digest so far + uint1 digest[16]; // the result + + // low level logic operations + static inline uint4 F(uint4 x, uint4 y, uint4 z); + static inline uint4 G(uint4 x, uint4 y, uint4 z); + static inline uint4 H(uint4 x, uint4 y, uint4 z); + static inline uint4 I(uint4 x, uint4 y, uint4 z); + static inline uint4 rotate_left(uint4 x, int n); + static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); +}; + +#endif diff --git a/sg_agent/src/comm/tinyxml2.cc b/sg_agent/src/comm/tinyxml2.cc new file mode 100755 index 0000000..6a7ca07 --- /dev/null +++ b/sg_agent/src/comm/tinyxml2.cc @@ -0,0 +1,2348 @@ +/* +Original code by Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#include "tinyxml2.h" + +#include // yes, this one new style header, is in the Android SDK. +#if defined(ANDROID_NDK) || defined(__QNXNTO__) +# include +#else +# include +#endif + +static const char LINE_FEED = (char)0x0a; // all line endings are normalized to LF +static const char LF = LINE_FEED; +static const char CARRIAGE_RETURN = (char)0x0d; // CR gets filtered out +static const char CR = CARRIAGE_RETURN; +static const char SINGLE_QUOTE = '\''; +static const char DOUBLE_QUOTE = '\"'; + +// Bunch of unicode info at: +// http://www.unicode.org/faq/utf_bom.html +// ef bb bf (Microsoft "lead bytes") - designates UTF-8 + +static const unsigned char TIXML_UTF_LEAD_0 = 0xefU; +static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; +static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; + +namespace tinyxml2 +{ + +struct Entity { + const char* pattern; + int length; + char value; +}; + +static const int NUM_ENTITIES = 5; +static const Entity entities[NUM_ENTITIES] = { + { "quot", 4, DOUBLE_QUOTE }, + { "amp", 3, '&' }, + { "apos", 4, SINGLE_QUOTE }, + { "lt", 2, '<' }, + { "gt", 2, '>' } +}; + + +StrPair::~StrPair() +{ + Reset(); +} + + +void StrPair::TransferTo( StrPair* other ) +{ + if ( this == other ) { + return; + } + // This in effect implements the assignment operator by "moving" + // ownership (as in auto_ptr). + + TIXMLASSERT( other->_flags == 0 ); + TIXMLASSERT( other->_start == 0 ); + TIXMLASSERT( other->_end == 0 ); + + other->Reset(); + + other->_flags = _flags; + other->_start = _start; + other->_end = _end; + + _flags = 0; + _start = 0; + _end = 0; +} + +void StrPair::Reset() +{ + if ( _flags & NEEDS_DELETE ) { + delete [] _start; + } + _flags = 0; + _start = 0; + _end = 0; +} + + +void StrPair::SetStr( const char* str, int flags ) +{ + Reset(); + size_t len = strlen( str ); + _start = new char[ len+1 ]; + memcpy( _start, str, len+1 ); + _end = _start + len; + _flags = flags | NEEDS_DELETE; +} + + +char* StrPair::ParseText( char* p, const char* endTag, int strFlags ) +{ + TIXMLASSERT( endTag && *endTag ); + + char* start = p; + char endChar = *endTag; + size_t length = strlen( endTag ); + + // Inner loop of text parsing. + while ( *p ) { + if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) { + Set( start, p, strFlags ); + return p + length; + } + ++p; + } + return 0; +} + + +char* StrPair::ParseName( char* p ) +{ + if ( !p || !(*p) ) { + return 0; + } + if ( !XMLUtil::IsNameStartChar( *p ) ) { + return 0; + } + + char* const start = p; + ++p; + while ( *p && XMLUtil::IsNameChar( *p ) ) { + ++p; + } + + Set( start, p, 0 ); + return p; +} + + +void StrPair::CollapseWhitespace() +{ + // Adjusting _start would cause undefined behavior on delete[] + TIXMLASSERT( ( _flags & NEEDS_DELETE ) == 0 ); + // Trim leading space. + _start = XMLUtil::SkipWhiteSpace( _start ); + + if ( *_start ) { + char* p = _start; // the read pointer + char* q = _start; // the write pointer + + while( *p ) { + if ( XMLUtil::IsWhiteSpace( *p )) { + p = XMLUtil::SkipWhiteSpace( p ); + if ( *p == 0 ) { + break; // don't write to q; this trims the trailing space. + } + *q = ' '; + ++q; + } + *q = *p; + ++q; + ++p; + } + *q = 0; + } +} + + +const char* StrPair::GetStr() +{ + TIXMLASSERT( _start ); + TIXMLASSERT( _end ); + if ( _flags & NEEDS_FLUSH ) { + *_end = 0; + _flags ^= NEEDS_FLUSH; + + if ( _flags ) { + char* p = _start; // the read pointer + char* q = _start; // the write pointer + + while( p < _end ) { + if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) { + // CR-LF pair becomes LF + // CR alone becomes LF + // LF-CR becomes LF + if ( *(p+1) == LF ) { + p += 2; + } + else { + ++p; + } + *q++ = LF; + } + else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) { + if ( *(p+1) == CR ) { + p += 2; + } + else { + ++p; + } + *q++ = LF; + } + else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) { + // Entities handled by tinyXML2: + // - special entities in the entity table [in/out] + // - numeric character reference [in] + // 中 or 中 + + if ( *(p+1) == '#' ) { + const int buflen = 10; + char buf[buflen] = { 0 }; + int len = 0; + char* adjusted = const_cast( XMLUtil::GetCharacterRef( p, buf, &len ) ); + if ( adjusted == 0 ) { + *q = *p; + ++p; + ++q; + } + else { + TIXMLASSERT( 0 <= len && len <= buflen ); + TIXMLASSERT( q + len <= adjusted ); + p = adjusted; + memcpy( q, buf, len ); + q += len; + } + } + else { + int i=0; + for(; i(p); + // Check for BOM: + if ( *(pu+0) == TIXML_UTF_LEAD_0 + && *(pu+1) == TIXML_UTF_LEAD_1 + && *(pu+2) == TIXML_UTF_LEAD_2 ) { + *bom = true; + p += 3; + } + TIXMLASSERT( p ); + return p; +} + + +void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) +{ + const unsigned long BYTE_MASK = 0xBF; + const unsigned long BYTE_MARK = 0x80; + const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; + + if (input < 0x80) { + *length = 1; + } + else if ( input < 0x800 ) { + *length = 2; + } + else if ( input < 0x10000 ) { + *length = 3; + } + else if ( input < 0x200000 ) { + *length = 4; + } + else { + *length = 0; // This code won't convert this correctly anyway. + return; + } + + output += *length; + + // Scary scary fall throughs. + switch (*length) { + case 4: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 3: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 2: + --output; + *output = (char)((input | BYTE_MARK) & BYTE_MASK); + input >>= 6; + case 1: + --output; + *output = (char)(input | FIRST_BYTE_MARK[*length]); + break; + default: + TIXMLASSERT( false ); + } +} + + +const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length ) +{ + // Presume an entity, and pull it out. + *length = 0; + + if ( *(p+1) == '#' && *(p+2) ) { + unsigned long ucs = 0; + TIXMLASSERT( sizeof( ucs ) >= 4 ); + ptrdiff_t delta = 0; + unsigned mult = 1; + static const char SEMICOLON = ';'; + + if ( *(p+2) == 'x' ) { + // Hexadecimal. + const char* q = p+3; + if ( !(*q) ) { + return 0; + } + + q = strchr( q, SEMICOLON ); + + if ( !q ) { + return 0; + } + TIXMLASSERT( *q == SEMICOLON ); + + delta = q-p; + --q; + + while ( *q != 'x' ) { + unsigned int digit = 0; + + if ( *q >= '0' && *q <= '9' ) { + digit = *q - '0'; + } + else if ( *q >= 'a' && *q <= 'f' ) { + digit = *q - 'a' + 10; + } + else if ( *q >= 'A' && *q <= 'F' ) { + digit = *q - 'A' + 10; + } + else { + return 0; + } + TIXMLASSERT( digit >= 0 && digit < 16); + TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); + const unsigned int digitScaled = mult * digit; + TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); + ucs += digitScaled; + TIXMLASSERT( mult <= UINT_MAX / 16 ); + mult *= 16; + --q; + } + } + else { + // Decimal. + const char* q = p+2; + if ( !(*q) ) { + return 0; + } + + q = strchr( q, SEMICOLON ); + + if ( !q ) { + return 0; + } + TIXMLASSERT( *q == SEMICOLON ); + + delta = q-p; + --q; + + while ( *q != '#' ) { + if ( *q >= '0' && *q <= '9' ) { + const unsigned int digit = *q - '0'; + TIXMLASSERT( digit >= 0 && digit < 10); + TIXMLASSERT( digit == 0 || mult <= UINT_MAX / digit ); + const unsigned int digitScaled = mult * digit; + TIXMLASSERT( ucs <= ULONG_MAX - digitScaled ); + ucs += digitScaled; + } + else { + return 0; + } + TIXMLASSERT( mult <= UINT_MAX / 10 ); + mult *= 10; + --q; + } + } + // convert the UCS to UTF-8 + ConvertUTF32ToUTF8( ucs, value, length ); + return p + delta + 1; + } + return p+1; +} + + +void XMLUtil::ToStr( int v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%d", v ); +} + + +void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%u", v ); +} + + +void XMLUtil::ToStr( bool v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%d", v ? 1 : 0 ); +} + +/* + ToStr() of a number is a very tricky topic. + https://github.com/leethomason/tinyxml2/issues/106 +*/ +void XMLUtil::ToStr( float v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%.8g", v ); +} + + +void XMLUtil::ToStr( double v, char* buffer, int bufferSize ) +{ + TIXML_SNPRINTF( buffer, bufferSize, "%.17g", v ); +} + + +bool XMLUtil::ToInt( const char* str, int* value ) +{ + if ( TIXML_SSCANF( str, "%d", value ) == 1 ) { + return true; + } + return false; +} + +bool XMLUtil::ToUnsigned( const char* str, unsigned *value ) +{ + if ( TIXML_SSCANF( str, "%u", value ) == 1 ) { + return true; + } + return false; +} + +bool XMLUtil::ToBool( const char* str, bool* value ) +{ + int ival = 0; + if ( ToInt( str, &ival )) { + *value = (ival==0) ? false : true; + return true; + } + if ( StringEqual( str, "true" ) ) { + *value = true; + return true; + } + else if ( StringEqual( str, "false" ) ) { + *value = false; + return true; + } + return false; +} + + +bool XMLUtil::ToFloat( const char* str, float* value ) +{ + if ( TIXML_SSCANF( str, "%f", value ) == 1 ) { + return true; + } + return false; +} + +bool XMLUtil::ToDouble( const char* str, double* value ) +{ + if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) { + return true; + } + return false; +} + + +char* XMLDocument::Identify( char* p, XMLNode** node ) +{ + TIXMLASSERT( node ); + TIXMLASSERT( p ); + char* const start = p; + p = XMLUtil::SkipWhiteSpace( p ); + if( !*p ) { + *node = 0; + TIXMLASSERT( p ); + return p; + } + + // What is this thing? + // These strings define the matching patters: + static const char* xmlHeader = { "_memPool = &_commentPool; + p += xmlHeaderLen; + } + else if ( XMLUtil::StringEqual( p, commentHeader, commentHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() ); + returnNode = new (_commentPool.Alloc()) XMLComment( this ); + returnNode->_memPool = &_commentPool; + p += commentHeaderLen; + } + else if ( XMLUtil::StringEqual( p, cdataHeader, cdataHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); + XMLText* text = new (_textPool.Alloc()) XMLText( this ); + returnNode = text; + returnNode->_memPool = &_textPool; + p += cdataHeaderLen; + text->SetCData( true ); + } + else if ( XMLUtil::StringEqual( p, dtdHeader, dtdHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() ); + returnNode = new (_commentPool.Alloc()) XMLUnknown( this ); + returnNode->_memPool = &_commentPool; + p += dtdHeaderLen; + } + else if ( XMLUtil::StringEqual( p, elementHeader, elementHeaderLen ) ) { + TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() ); + returnNode = new (_elementPool.Alloc()) XMLElement( this ); + returnNode->_memPool = &_elementPool; + p += elementHeaderLen; + } + else { + TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); + returnNode = new (_textPool.Alloc()) XMLText( this ); + returnNode->_memPool = &_textPool; + p = start; // Back it up, all the text counts. + } + + TIXMLASSERT( returnNode ); + TIXMLASSERT( p ); + *node = returnNode; + return p; +} + + +bool XMLDocument::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + if ( visitor->VisitEnter( *this ) ) { + for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { + if ( !node->Accept( visitor ) ) { + break; + } + } + } + return visitor->VisitExit( *this ); +} + + +// --------- XMLNode ----------- // + +XMLNode::XMLNode( XMLDocument* doc ) : + _document( doc ), + _parent( 0 ), + _firstChild( 0 ), _lastChild( 0 ), + _prev( 0 ), _next( 0 ), + _memPool( 0 ) +{ +} + + +XMLNode::~XMLNode() +{ + DeleteChildren(); + if ( _parent ) { + _parent->Unlink( this ); + } +} + +const char* XMLNode::Value() const +{ + return _value.GetStr(); +} + +void XMLNode::SetValue( const char* str, bool staticMem ) +{ + if ( staticMem ) { + _value.SetInternedStr( str ); + } + else { + _value.SetStr( str ); + } +} + + +void XMLNode::DeleteChildren() +{ + while( _firstChild ) { + TIXMLASSERT( _firstChild->_document == _document ); + XMLNode* node = _firstChild; + Unlink( node ); + + DeleteNode( node ); + } + _firstChild = _lastChild = 0; +} + + +void XMLNode::Unlink( XMLNode* child ) +{ + TIXMLASSERT( child ); + TIXMLASSERT( child->_document == _document ); + if ( child == _firstChild ) { + _firstChild = _firstChild->_next; + } + if ( child == _lastChild ) { + _lastChild = _lastChild->_prev; + } + + if ( child->_prev ) { + child->_prev->_next = child->_next; + } + if ( child->_next ) { + child->_next->_prev = child->_prev; + } + child->_parent = 0; +} + + +void XMLNode::DeleteChild( XMLNode* node ) +{ + TIXMLASSERT( node ); + TIXMLASSERT( node->_document == _document ); + TIXMLASSERT( node->_parent == this ); + DeleteNode( node ); +} + + +XMLNode* XMLNode::InsertEndChild( XMLNode* addThis ) +{ + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } + InsertChildPreamble( addThis ); + + if ( _lastChild ) { + TIXMLASSERT( _firstChild ); + TIXMLASSERT( _lastChild->_next == 0 ); + _lastChild->_next = addThis; + addThis->_prev = _lastChild; + _lastChild = addThis; + + addThis->_next = 0; + } + else { + TIXMLASSERT( _firstChild == 0 ); + _firstChild = _lastChild = addThis; + + addThis->_prev = 0; + addThis->_next = 0; + } + addThis->_parent = this; + return addThis; +} + + +XMLNode* XMLNode::InsertFirstChild( XMLNode* addThis ) +{ + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } + InsertChildPreamble( addThis ); + + if ( _firstChild ) { + TIXMLASSERT( _lastChild ); + TIXMLASSERT( _firstChild->_prev == 0 ); + + _firstChild->_prev = addThis; + addThis->_next = _firstChild; + _firstChild = addThis; + + addThis->_prev = 0; + } + else { + TIXMLASSERT( _lastChild == 0 ); + _firstChild = _lastChild = addThis; + + addThis->_prev = 0; + addThis->_next = 0; + } + addThis->_parent = this; + return addThis; +} + + +XMLNode* XMLNode::InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ) +{ + TIXMLASSERT( addThis ); + if ( addThis->_document != _document ) { + TIXMLASSERT( false ); + return 0; + } + + TIXMLASSERT( afterThis ); + + if ( afterThis->_parent != this ) { + TIXMLASSERT( false ); + return 0; + } + + if ( afterThis->_next == 0 ) { + // The last node or the only node. + return InsertEndChild( addThis ); + } + InsertChildPreamble( addThis ); + addThis->_prev = afterThis; + addThis->_next = afterThis->_next; + afterThis->_next->_prev = addThis; + afterThis->_next = addThis; + addThis->_parent = this; + return addThis; +} + + + + +const XMLElement* XMLNode::FirstChildElement( const char* value ) const +{ + for( XMLNode* node=_firstChild; node; node=node->_next ) { + XMLElement* element = node->ToElement(); + if ( element ) { + if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) { + return element; + } + } + } + return 0; +} + + +const XMLElement* XMLNode::LastChildElement( const char* value ) const +{ + for( XMLNode* node=_lastChild; node; node=node->_prev ) { + XMLElement* element = node->ToElement(); + if ( element ) { + if ( !value || XMLUtil::StringEqual( element->Name(), value ) ) { + return element; + } + } + } + return 0; +} + + +const XMLElement* XMLNode::NextSiblingElement( const char* value ) const +{ + for( XMLNode* node=this->_next; node; node = node->_next ) { + const XMLElement* element = node->ToElement(); + if ( element + && (!value || XMLUtil::StringEqual( value, node->Value() ))) { + return element; + } + } + return 0; +} + + +const XMLElement* XMLNode::PreviousSiblingElement( const char* value ) const +{ + for( XMLNode* node=_prev; node; node = node->_prev ) { + const XMLElement* element = node->ToElement(); + if ( element + && (!value || XMLUtil::StringEqual( value, node->Value() ))) { + return element; + } + } + return 0; +} + + +char* XMLNode::ParseDeep( char* p, StrPair* parentEnd ) +{ + // This is a recursive method, but thinking about it "at the current level" + // it is a pretty simple flat list: + // + // + // + // With a special case: + // + // + // + // + // Where the closing element (/foo) *must* be the next thing after the opening + // element, and the names must match. BUT the tricky bit is that the closing + // element will be read by the child. + // + // 'endTag' is the end tag for this node, it is returned by a call to a child. + // 'parentEnd' is the end tag for the parent, which is filled in and returned. + + while( p && *p ) { + XMLNode* node = 0; + + p = _document->Identify( p, &node ); + if ( node == 0 ) { + break; + } + + StrPair endTag; + p = node->ParseDeep( p, &endTag ); + if ( !p ) { + DeleteNode( node ); + if ( !_document->Error() ) { + _document->SetError( XML_ERROR_PARSING, 0, 0 ); + } + break; + } + + XMLElement* ele = node->ToElement(); + if ( ele ) { + // We read the end tag. Return it to the parent. + if ( ele->ClosingType() == XMLElement::CLOSING ) { + if ( parentEnd ) { + ele->_value.TransferTo( parentEnd ); + } + node->_memPool->SetTracked(); // created and then immediately deleted. + DeleteNode( node ); + return p; + } + + // Handle an end tag returned to this level. + // And handle a bunch of annoying errors. + bool mismatch = false; + if ( endTag.Empty() ) { + if ( ele->ClosingType() == XMLElement::OPEN ) { + mismatch = true; + } + } + else { + if ( ele->ClosingType() != XMLElement::OPEN ) { + mismatch = true; + } + else if ( !XMLUtil::StringEqual( endTag.GetStr(), node->Value() ) ) { + mismatch = true; + } + } + if ( mismatch ) { + _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 ); + DeleteNode( node ); + break; + } + } + InsertEndChild( node ); + } + return 0; +} + +void XMLNode::DeleteNode( XMLNode* node ) +{ + if ( node == 0 ) { + return; + } + MemPool* pool = node->_memPool; + node->~XMLNode(); + pool->Free( node ); +} + +void XMLNode::InsertChildPreamble( XMLNode* insertThis ) const +{ + TIXMLASSERT( insertThis ); + TIXMLASSERT( insertThis->_document == _document ); + + if ( insertThis->_parent ) + insertThis->_parent->Unlink( insertThis ); + else + insertThis->_memPool->SetTracked(); +} + +// --------- XMLText ---------- // +char* XMLText::ParseDeep( char* p, StrPair* ) +{ + const char* start = p; + if ( this->CData() ) { + p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION ); + if ( !p ) { + _document->SetError( XML_ERROR_PARSING_CDATA, start, 0 ); + } + return p; + } + else { + int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES; + if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) { + flags |= StrPair::COLLAPSE_WHITESPACE; + } + + p = _value.ParseText( p, "<", flags ); + if ( p && *p ) { + return p-1; + } + if ( !p ) { + _document->SetError( XML_ERROR_PARSING_TEXT, start, 0 ); + } + } + return 0; +} + + +XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLText* text = doc->NewText( Value() ); // fixme: this will always allocate memory. Intern? + text->SetCData( this->CData() ); + return text; +} + + +bool XMLText::ShallowEqual( const XMLNode* compare ) const +{ + const XMLText* text = compare->ToText(); + return ( text && XMLUtil::StringEqual( text->Value(), Value() ) ); +} + + +bool XMLText::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + + +// --------- XMLComment ---------- // + +XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLComment::~XMLComment() +{ +} + + +char* XMLComment::ParseDeep( char* p, StrPair* ) +{ + // Comment parses as text. + const char* start = p; + p = _value.ParseText( p, "-->", StrPair::COMMENT ); + if ( p == 0 ) { + _document->SetError( XML_ERROR_PARSING_COMMENT, start, 0 ); + } + return p; +} + + +XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLComment* comment = doc->NewComment( Value() ); // fixme: this will always allocate memory. Intern? + return comment; +} + + +bool XMLComment::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLComment* comment = compare->ToComment(); + return ( comment && XMLUtil::StringEqual( comment->Value(), Value() )); +} + + +bool XMLComment::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + + +// --------- XMLDeclaration ---------- // + +XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLDeclaration::~XMLDeclaration() +{ + //printf( "~XMLDeclaration\n" ); +} + + +char* XMLDeclaration::ParseDeep( char* p, StrPair* ) +{ + // Declaration parses as text. + const char* start = p; + p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION ); + if ( p == 0 ) { + _document->SetError( XML_ERROR_PARSING_DECLARATION, start, 0 ); + } + return p; +} + + +XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLDeclaration* dec = doc->NewDeclaration( Value() ); // fixme: this will always allocate memory. Intern? + return dec; +} + + +bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLDeclaration* declaration = compare->ToDeclaration(); + return ( declaration && XMLUtil::StringEqual( declaration->Value(), Value() )); +} + + + +bool XMLDeclaration::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + +// --------- XMLUnknown ---------- // + +XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc ) +{ +} + + +XMLUnknown::~XMLUnknown() +{ +} + + +char* XMLUnknown::ParseDeep( char* p, StrPair* ) +{ + // Unknown parses as text. + const char* start = p; + + p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION ); + if ( !p ) { + _document->SetError( XML_ERROR_PARSING_UNKNOWN, start, 0 ); + } + return p; +} + + +XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLUnknown* text = doc->NewUnknown( Value() ); // fixme: this will always allocate memory. Intern? + return text; +} + + +bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLUnknown* unknown = compare->ToUnknown(); + return ( unknown && XMLUtil::StringEqual( unknown->Value(), Value() )); +} + + +bool XMLUnknown::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + return visitor->Visit( *this ); +} + +// --------- XMLAttribute ---------- // + +const char* XMLAttribute::Name() const +{ + return _name.GetStr(); +} + +const char* XMLAttribute::Value() const +{ + return _value.GetStr(); +} + +char* XMLAttribute::ParseDeep( char* p, bool processEntities ) +{ + // Parse using the name rules: bug fix, was using ParseText before + p = _name.ParseName( p ); + if ( !p || !*p ) { + return 0; + } + + // Skip white space before = + p = XMLUtil::SkipWhiteSpace( p ); + if ( *p != '=' ) { + return 0; + } + + ++p; // move up to opening quote + p = XMLUtil::SkipWhiteSpace( p ); + if ( *p != '\"' && *p != '\'' ) { + return 0; + } + + char endTag[2] = { *p, 0 }; + ++p; // move past opening quote + + p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES ); + return p; +} + + +void XMLAttribute::SetName( const char* n ) +{ + _name.SetStr( n ); +} + + +XMLError XMLAttribute::QueryIntValue( int* value ) const +{ + if ( XMLUtil::ToInt( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const +{ + if ( XMLUtil::ToUnsigned( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryBoolValue( bool* value ) const +{ + if ( XMLUtil::ToBool( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryFloatValue( float* value ) const +{ + if ( XMLUtil::ToFloat( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +XMLError XMLAttribute::QueryDoubleValue( double* value ) const +{ + if ( XMLUtil::ToDouble( Value(), value )) { + return XML_NO_ERROR; + } + return XML_WRONG_ATTRIBUTE_TYPE; +} + + +void XMLAttribute::SetAttribute( const char* v ) +{ + _value.SetStr( v ); +} + + +void XMLAttribute::SetAttribute( int v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + + +void XMLAttribute::SetAttribute( unsigned v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + + +void XMLAttribute::SetAttribute( bool v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + +void XMLAttribute::SetAttribute( double v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + +void XMLAttribute::SetAttribute( float v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + _value.SetStr( buf ); +} + + +// --------- XMLElement ---------- // +XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ), + _closingType( 0 ), + _rootAttribute( 0 ) +{ +} + + +XMLElement::~XMLElement() +{ + while( _rootAttribute ) { + XMLAttribute* next = _rootAttribute->_next; + DeleteAttribute( _rootAttribute ); + _rootAttribute = next; + } +} + + +const XMLAttribute* XMLElement::FindAttribute( const char* name ) const +{ + for( XMLAttribute* a = _rootAttribute; a; a = a->_next ) { + if ( XMLUtil::StringEqual( a->Name(), name ) ) { + return a; + } + } + return 0; +} + + +const char* XMLElement::Attribute( const char* name, const char* value ) const +{ + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return 0; + } + if ( !value || XMLUtil::StringEqual( a->Value(), value )) { + return a->Value(); + } + return 0; +} + + +const char* XMLElement::GetText() const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + return FirstChild()->Value(); + } + return 0; +} + + +void XMLElement::SetText( const char* inText ) +{ + if ( FirstChild() && FirstChild()->ToText() ) + FirstChild()->SetValue( inText ); + else { + XMLText* theText = GetDocument()->NewText( inText ); + InsertFirstChild( theText ); + } +} + + +void XMLElement::SetText( int v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( unsigned v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( bool v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( float v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +void XMLElement::SetText( double v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + SetText( buf ); +} + + +XMLError XMLElement::QueryIntText( int* ival ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToInt( t, ival ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToUnsigned( t, uval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryBoolText( bool* bval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToBool( t, bval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryDoubleText( double* dval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToDouble( t, dval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + +XMLError XMLElement::QueryFloatText( float* fval ) const +{ + if ( FirstChild() && FirstChild()->ToText() ) { + const char* t = FirstChild()->Value(); + if ( XMLUtil::ToFloat( t, fval ) ) { + return XML_SUCCESS; + } + return XML_CAN_NOT_CONVERT_TEXT; + } + return XML_NO_TEXT_NODE; +} + + + +XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name ) +{ + XMLAttribute* last = 0; + XMLAttribute* attrib = 0; + for( attrib = _rootAttribute; + attrib; + last = attrib, attrib = attrib->_next ) { + if ( XMLUtil::StringEqual( attrib->Name(), name ) ) { + break; + } + } + if ( !attrib ) { + TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() ); + attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); + attrib->_memPool = &_document->_attributePool; + if ( last ) { + last->_next = attrib; + } + else { + _rootAttribute = attrib; + } + attrib->SetName( name ); + attrib->_memPool->SetTracked(); // always created and linked. + } + return attrib; +} + + +void XMLElement::DeleteAttribute( const char* name ) +{ + XMLAttribute* prev = 0; + for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) { + if ( XMLUtil::StringEqual( name, a->Name() ) ) { + if ( prev ) { + prev->_next = a->_next; + } + else { + _rootAttribute = a->_next; + } + DeleteAttribute( a ); + break; + } + prev = a; + } +} + + +char* XMLElement::ParseAttributes( char* p ) +{ + const char* start = p; + XMLAttribute* prevAttribute = 0; + + // Read the attributes. + while( p ) { + p = XMLUtil::SkipWhiteSpace( p ); + if ( !(*p) ) { + _document->SetError( XML_ERROR_PARSING_ELEMENT, start, Name() ); + return 0; + } + + // attribute. + if (XMLUtil::IsNameStartChar( *p ) ) { + TIXMLASSERT( sizeof( XMLAttribute ) == _document->_attributePool.ItemSize() ); + XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); + attrib->_memPool = &_document->_attributePool; + attrib->_memPool->SetTracked(); + + p = attrib->ParseDeep( p, _document->ProcessEntities() ); + if ( !p || Attribute( attrib->Name() ) ) { + DeleteAttribute( attrib ); + _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, start, p ); + return 0; + } + // There is a minor bug here: if the attribute in the source xml + // document is duplicated, it will not be detected and the + // attribute will be doubly added. However, tracking the 'prevAttribute' + // avoids re-scanning the attribute list. Preferring performance for + // now, may reconsider in the future. + if ( prevAttribute ) { + prevAttribute->_next = attrib; + } + else { + _rootAttribute = attrib; + } + prevAttribute = attrib; + } + // end of the tag + else if ( *p == '/' && *(p+1) == '>' ) { + _closingType = CLOSED; + return p+2; // done; sealed element. + } + // end of the tag + else if ( *p == '>' ) { + ++p; + break; + } + else { + _document->SetError( XML_ERROR_PARSING_ELEMENT, start, p ); + return 0; + } + } + return p; +} + +void XMLElement::DeleteAttribute( XMLAttribute* attribute ) +{ + if ( attribute == 0 ) { + return; + } + MemPool* pool = attribute->_memPool; + attribute->~XMLAttribute(); + pool->Free( attribute ); +} + +// +// +// foobar +// +char* XMLElement::ParseDeep( char* p, StrPair* strPair ) +{ + // Read the element name. + p = XMLUtil::SkipWhiteSpace( p ); + + // The closing element is the form. It is + // parsed just like a regular element then deleted from + // the DOM. + if ( *p == '/' ) { + _closingType = CLOSING; + ++p; + } + + p = _value.ParseName( p ); + if ( _value.Empty() ) { + return 0; + } + + p = ParseAttributes( p ); + if ( !p || !*p || _closingType ) { + return p; + } + + p = XMLNode::ParseDeep( p, strPair ); + return p; +} + + + +XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const +{ + if ( !doc ) { + doc = _document; + } + XMLElement* element = doc->NewElement( Value() ); // fixme: this will always allocate memory. Intern? + for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) { + element->SetAttribute( a->Name(), a->Value() ); // fixme: this will always allocate memory. Intern? + } + return element; +} + + +bool XMLElement::ShallowEqual( const XMLNode* compare ) const +{ + TIXMLASSERT( compare ); + const XMLElement* other = compare->ToElement(); + if ( other && XMLUtil::StringEqual( other->Value(), Value() )) { + + const XMLAttribute* a=FirstAttribute(); + const XMLAttribute* b=other->FirstAttribute(); + + while ( a && b ) { + if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) { + return false; + } + a = a->Next(); + b = b->Next(); + } + if ( a || b ) { + // different count + return false; + } + return true; + } + return false; +} + + +bool XMLElement::Accept( XMLVisitor* visitor ) const +{ + TIXMLASSERT( visitor ); + if ( visitor->VisitEnter( *this, _rootAttribute ) ) { + for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { + if ( !node->Accept( visitor ) ) { + break; + } + } + } + return visitor->VisitExit( *this ); +} + + +// --------- XMLDocument ----------- // + +// Warning: List must match 'enum XMLError' +const char* XMLDocument::_errorNames[XML_ERROR_COUNT] = { + "XML_SUCCESS", + "XML_NO_ATTRIBUTE", + "XML_WRONG_ATTRIBUTE_TYPE", + "XML_ERROR_FILE_NOT_FOUND", + "XML_ERROR_FILE_COULD_NOT_BE_OPENED", + "XML_ERROR_FILE_READ_ERROR", + "XML_ERROR_ELEMENT_MISMATCH", + "XML_ERROR_PARSING_ELEMENT", + "XML_ERROR_PARSING_ATTRIBUTE", + "XML_ERROR_IDENTIFYING_TAG", + "XML_ERROR_PARSING_TEXT", + "XML_ERROR_PARSING_CDATA", + "XML_ERROR_PARSING_COMMENT", + "XML_ERROR_PARSING_DECLARATION", + "XML_ERROR_PARSING_UNKNOWN", + "XML_ERROR_EMPTY_DOCUMENT", + "XML_ERROR_MISMATCHED_ELEMENT", + "XML_ERROR_PARSING", + "XML_CAN_NOT_CONVERT_TEXT", + "XML_NO_TEXT_NODE" +}; + + +XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) : + XMLNode( 0 ), + _writeBOM( false ), + _processEntities( processEntities ), + _errorID( XML_NO_ERROR ), + _whitespace( whitespace ), + _errorStr1( 0 ), + _errorStr2( 0 ), + _charBuffer( 0 ) +{ + _document = this; // avoid warning about 'this' in initializer list +} + + +XMLDocument::~XMLDocument() +{ + Clear(); +} + + +void XMLDocument::Clear() +{ + DeleteChildren(); + +#ifdef DEBUG + const bool hadError = Error(); +#endif + _errorID = XML_NO_ERROR; + _errorStr1 = 0; + _errorStr2 = 0; + + delete [] _charBuffer; + _charBuffer = 0; + +#if 0 + _textPool.Trace( "text" ); + _elementPool.Trace( "element" ); + _commentPool.Trace( "comment" ); + _attributePool.Trace( "attribute" ); +#endif + +#ifdef DEBUG + if ( !hadError ) { + TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() ); + TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() ); + TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() ); + TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() ); + } +#endif +} + + +XMLElement* XMLDocument::NewElement( const char* name ) +{ + TIXMLASSERT( sizeof( XMLElement ) == _elementPool.ItemSize() ); + XMLElement* ele = new (_elementPool.Alloc()) XMLElement( this ); + ele->_memPool = &_elementPool; + ele->SetName( name ); + return ele; +} + + +XMLComment* XMLDocument::NewComment( const char* str ) +{ + TIXMLASSERT( sizeof( XMLComment ) == _commentPool.ItemSize() ); + XMLComment* comment = new (_commentPool.Alloc()) XMLComment( this ); + comment->_memPool = &_commentPool; + comment->SetValue( str ); + return comment; +} + + +XMLText* XMLDocument::NewText( const char* str ) +{ + TIXMLASSERT( sizeof( XMLText ) == _textPool.ItemSize() ); + XMLText* text = new (_textPool.Alloc()) XMLText( this ); + text->_memPool = &_textPool; + text->SetValue( str ); + return text; +} + + +XMLDeclaration* XMLDocument::NewDeclaration( const char* str ) +{ + TIXMLASSERT( sizeof( XMLDeclaration ) == _commentPool.ItemSize() ); + XMLDeclaration* dec = new (_commentPool.Alloc()) XMLDeclaration( this ); + dec->_memPool = &_commentPool; + dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" ); + return dec; +} + + +XMLUnknown* XMLDocument::NewUnknown( const char* str ) +{ + TIXMLASSERT( sizeof( XMLUnknown ) == _commentPool.ItemSize() ); + XMLUnknown* unk = new (_commentPool.Alloc()) XMLUnknown( this ); + unk->_memPool = &_commentPool; + unk->SetValue( str ); + return unk; +} + +static FILE* callfopen( const char* filepath, const char* mode ) +{ + TIXMLASSERT( filepath ); + TIXMLASSERT( mode ); +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) + FILE* fp = 0; + errno_t err = fopen_s( &fp, filepath, mode ); + if ( err ) { + return 0; + } +#else + FILE* fp = fopen( filepath, mode ); +#endif + return fp; +} + +void XMLDocument::DeleteNode( XMLNode* node ) { + TIXMLASSERT( node ); + TIXMLASSERT(node->_document == this ); + if (node->_parent) { + node->_parent->DeleteChild( node ); + } + else { + // Isn't in the tree. + // Use the parent delete. + // Also, we need to mark it tracked: we 'know' + // it was never used. + node->_memPool->SetTracked(); + // Call the static XMLNode version: + XMLNode::DeleteNode(node); + } +} + + +XMLError XMLDocument::LoadFile( const char* filename ) +{ + Clear(); + FILE* fp = callfopen( filename, "rb" ); + if ( !fp ) { + SetError( XML_ERROR_FILE_NOT_FOUND, filename, 0 ); + return _errorID; + } + LoadFile( fp ); + fclose( fp ); + return _errorID; +} + + +XMLError XMLDocument::LoadFile( FILE* fp ) +{ + Clear(); + + fseek( fp, 0, SEEK_SET ); + if ( fgetc( fp ) == EOF && ferror( fp ) != 0 ) { + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + + fseek( fp, 0, SEEK_END ); + const long filelength = ftell( fp ); + fseek( fp, 0, SEEK_SET ); + if ( filelength == -1L ) { + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + + const size_t size = filelength; + if ( size == 0 ) { + SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); + return _errorID; + } + + _charBuffer = new char[size+1]; + size_t read = fread( _charBuffer, 1, size, fp ); + if ( read != size ) { + SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); + return _errorID; + } + + _charBuffer[size] = 0; + + Parse(); + return _errorID; +} + + +XMLError XMLDocument::SaveFile( const char* filename, bool compact ) +{ + FILE* fp = callfopen( filename, "w" ); + if ( !fp ) { + SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, filename, 0 ); + return _errorID; + } + SaveFile(fp, compact); + fclose( fp ); + return _errorID; +} + + +XMLError XMLDocument::SaveFile( FILE* fp, bool compact ) +{ + XMLPrinter stream( fp, compact ); + Print( &stream ); + return _errorID; +} + + +XMLError XMLDocument::Parse( const char* p, size_t len ) +{ + Clear(); + + if ( len == 0 || !p || !*p ) { + SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); + return _errorID; + } + if ( len == (size_t)(-1) ) { + len = strlen( p ); + } + _charBuffer = new char[ len+1 ]; + memcpy( _charBuffer, p, len ); + _charBuffer[len] = 0; + + Parse(); + if ( Error() ) { + // clean up now essentially dangling memory. + // and the parse fail can put objects in the + // pools that are dead and inaccessible. + DeleteChildren(); + _elementPool.Clear(); + _attributePool.Clear(); + _textPool.Clear(); + _commentPool.Clear(); + } + return _errorID; +} + + +void XMLDocument::Print( XMLPrinter* streamer ) const +{ + XMLPrinter stdStreamer( stdout ); + if ( !streamer ) { + streamer = &stdStreamer; + } + Accept( streamer ); +} + + +void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 ) +{ + TIXMLASSERT( error >= 0 && error < XML_ERROR_COUNT ); + _errorID = error; + _errorStr1 = str1; + _errorStr2 = str2; +} + +const char* XMLDocument::ErrorName() const +{ + TIXMLASSERT( _errorID >= 0 && _errorID < XML_ERROR_COUNT ); + return _errorNames[_errorID]; +} + +void XMLDocument::PrintError() const +{ + if ( Error() ) { + static const int LEN = 20; + char buf1[LEN] = { 0 }; + char buf2[LEN] = { 0 }; + + if ( _errorStr1 ) { + TIXML_SNPRINTF( buf1, LEN, "%s", _errorStr1 ); + } + if ( _errorStr2 ) { + TIXML_SNPRINTF( buf2, LEN, "%s", _errorStr2 ); + } + + printf( "XMLDocument error id=%d '%s' str1=%s str2=%s\n", + _errorID, ErrorName(), buf1, buf2 ); + } +} + +void XMLDocument::Parse() +{ + TIXMLASSERT( NoChildren() ); // Clear() must have been called previously + TIXMLASSERT( _charBuffer ); + char* p = _charBuffer; + p = XMLUtil::SkipWhiteSpace( p ); + p = const_cast( XMLUtil::ReadBOM( p, &_writeBOM ) ); + if ( !*p ) { + SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); + return; + } + ParseDeep(p, 0 ); +} + +XMLPrinter::XMLPrinter( FILE* file, bool compact, int depth ) : + _elementJustOpened( false ), + _firstElement( true ), + _fp( file ), + _depth( depth ), + _textDepth( -1 ), + _processEntities( true ), + _compactMode( compact ) +{ + for( int i=0; i'] = true; // not required, but consistency is nice + _buffer.Push( 0 ); +} + + +void XMLPrinter::Print( const char* format, ... ) +{ + va_list va; + va_start( va, format ); + + if ( _fp ) { + vfprintf( _fp, format, va ); + } + else { +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + #if defined(WINCE) + int len = 512; + do { + len = len*2; + char* str = new char[len](); + len = _vsnprintf(str, len, format, va); + delete[] str; + }while (len < 0); + #else + int len = _vscprintf( format, va ); + #endif +#else + int len = vsnprintf( 0, 0, format, va ); +#endif + // Close out and re-start the va-args + va_end( va ); + va_start( va, format ); + TIXMLASSERT( _buffer.Size() > 0 && _buffer[_buffer.Size() - 1] == 0 ); + char* p = _buffer.PushArr( len ) - 1; // back up over the null terminator. +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) + #if defined(WINCE) + _vsnprintf( p, len+1, format, va ); + #else + vsnprintf_s( p, len+1, _TRUNCATE, format, va ); + #endif +#else + vsnprintf( p, len+1, format, va ); +#endif + } + va_end( va ); +} + + +void XMLPrinter::PrintSpace( int depth ) +{ + for( int i=0; i 0 && *q < ENTITY_RANGE ) { + // Check for entities. If one is found, flush + // the stream up until the entity, write the + // entity, and keep looking. + if ( flag[(unsigned char)(*q)] ) { + while ( p < q ) { + Print( "%c", *p ); + ++p; + } + for( int i=0; i 0) ) { + Print( "%s", p ); + } +} + + +void XMLPrinter::PushHeader( bool writeBOM, bool writeDec ) +{ + if ( writeBOM ) { + static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 }; + Print( "%s", bom ); + } + if ( writeDec ) { + PushDeclaration( "xml version=\"1.0\"" ); + } +} + + +void XMLPrinter::OpenElement( const char* name, bool compactMode ) +{ + SealElementIfJustOpened(); + _stack.Push( name ); + + if ( _textDepth < 0 && !_firstElement && !compactMode ) { + Print( "\n" ); + } + if ( !compactMode ) { + PrintSpace( _depth ); + } + + Print( "<%s", name ); + _elementJustOpened = true; + _firstElement = false; + ++_depth; +} + + +void XMLPrinter::PushAttribute( const char* name, const char* value ) +{ + TIXMLASSERT( _elementJustOpened ); + Print( " %s=\"", name ); + PrintString( value, false ); + Print( "\"" ); +} + + +void XMLPrinter::PushAttribute( const char* name, int v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + PushAttribute( name, buf ); +} + + +void XMLPrinter::PushAttribute( const char* name, unsigned v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + PushAttribute( name, buf ); +} + + +void XMLPrinter::PushAttribute( const char* name, bool v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + PushAttribute( name, buf ); +} + + +void XMLPrinter::PushAttribute( const char* name, double v ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( v, buf, BUF_SIZE ); + PushAttribute( name, buf ); +} + + +void XMLPrinter::CloseElement( bool compactMode ) +{ + --_depth; + const char* name = _stack.Pop(); + + if ( _elementJustOpened ) { + Print( "/>" ); + } + else { + if ( _textDepth < 0 && !compactMode) { + Print( "\n" ); + PrintSpace( _depth ); + } + Print( "", name ); + } + + if ( _textDepth == _depth ) { + _textDepth = -1; + } + if ( _depth == 0 && !compactMode) { + Print( "\n" ); + } + _elementJustOpened = false; +} + + +void XMLPrinter::SealElementIfJustOpened() +{ + if ( !_elementJustOpened ) { + return; + } + _elementJustOpened = false; + Print( ">" ); +} + + +void XMLPrinter::PushText( const char* text, bool cdata ) +{ + _textDepth = _depth-1; + + SealElementIfJustOpened(); + if ( cdata ) { + Print( "" ); + } + else { + PrintString( text, true ); + } +} + +void XMLPrinter::PushText( int value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( unsigned value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( bool value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( float value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushText( double value ) +{ + char buf[BUF_SIZE]; + XMLUtil::ToStr( value, buf, BUF_SIZE ); + PushText( buf, false ); +} + + +void XMLPrinter::PushComment( const char* comment ) +{ + SealElementIfJustOpened(); + if ( _textDepth < 0 && !_firstElement && !_compactMode) { + Print( "\n" ); + PrintSpace( _depth ); + } + _firstElement = false; + Print( "", comment ); +} + + +void XMLPrinter::PushDeclaration( const char* value ) +{ + SealElementIfJustOpened(); + if ( _textDepth < 0 && !_firstElement && !_compactMode) { + Print( "\n" ); + PrintSpace( _depth ); + } + _firstElement = false; + Print( "", value ); +} + + +void XMLPrinter::PushUnknown( const char* value ) +{ + SealElementIfJustOpened(); + if ( _textDepth < 0 && !_firstElement && !_compactMode) { + Print( "\n" ); + PrintSpace( _depth ); + } + _firstElement = false; + Print( "", value ); +} + + +bool XMLPrinter::VisitEnter( const XMLDocument& doc ) +{ + _processEntities = doc.ProcessEntities(); + if ( doc.HasBOM() ) { + PushHeader( true, false ); + } + return true; +} + + +bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute ) +{ + const XMLElement* parentElem = NULL; + if ( element.Parent() ) { + parentElem = element.Parent()->ToElement(); + } + bool compactMode = parentElem ? CompactMode(*parentElem) : _compactMode; + OpenElement( element.Name(), compactMode ); + while ( attribute ) { + PushAttribute( attribute->Name(), attribute->Value() ); + attribute = attribute->Next(); + } + return true; +} + + +bool XMLPrinter::VisitExit( const XMLElement& element ) +{ + CloseElement( CompactMode(element) ); + return true; +} + + +bool XMLPrinter::Visit( const XMLText& text ) +{ + PushText( text.Value(), text.CData() ); + return true; +} + + +bool XMLPrinter::Visit( const XMLComment& comment ) +{ + PushComment( comment.Value() ); + return true; +} + +bool XMLPrinter::Visit( const XMLDeclaration& declaration ) +{ + PushDeclaration( declaration.Value() ); + return true; +} + + +bool XMLPrinter::Visit( const XMLUnknown& unknown ) +{ + PushUnknown( unknown.Value() ); + return true; +} + +} // namespace tinyxml2 + diff --git a/sg_agent/src/comm/tinyxml2.h b/sg_agent/src/comm/tinyxml2.h new file mode 100755 index 0000000..a6da2ec --- /dev/null +++ b/sg_agent/src/comm/tinyxml2.h @@ -0,0 +1,2130 @@ +/* +Original code by Lee Thomason (www.grinninglizard.com) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must +not claim that you wrote the original software. If you use this +software in a product, an acknowledgment in the product documentation +would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source +distribution. +*/ + +#ifndef TINYXML2_INCLUDED +#define TINYXML2_INCLUDED + +#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__) +# include +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +# include +# include +#endif + +/* + TODO: intern strings instead of allocation. +*/ +/* + gcc: + g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe + + Formatting, Artistic Style: + AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h +*/ + +#if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__) +# ifndef DEBUG +# define DEBUG +# endif +#endif + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable: 4251) +#endif + +#ifdef _WIN32 +# ifdef TINYXML2_EXPORT +# define TINYXML2_LIB __declspec(dllexport) +# elif defined(TINYXML2_IMPORT) +# define TINYXML2_LIB __declspec(dllimport) +# else +# define TINYXML2_LIB +# endif +#else +# define TINYXML2_LIB +#endif + + +#if defined(DEBUG) +# if defined(_MSC_VER) +# // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like +# define TIXMLASSERT( x ) if ( !((void)0,(x))) { __debugbreak(); } //if ( !(x)) WinDebugBreak() +# elif defined (ANDROID_NDK) +# include +# define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); } +# else +# include +# define TIXMLASSERT assert +# endif +# else +# define TIXMLASSERT( x ) {} +#endif + + +#if defined(_MSC_VER) && (_MSC_VER >= 1400 ) && (!defined WINCE) +// Microsoft visual studio, version 2005 and higher. +/*int _snprintf_s( + char *buffer, + size_t sizeOfBuffer, + size_t count, + const char *format [, + argument] ... +);*/ +inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) +{ + va_list va; + va_start( va, format ); + int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); + va_end( va ); + return result; +} +#define TIXML_SSCANF sscanf_s +#elif defined WINCE +#define TIXML_SNPRINTF _snprintf +#define TIXML_SSCANF sscanf +#else +// GCC version 3 and higher +//#warning( "Using sn* functions." ) +#define TIXML_SNPRINTF snprintf +#define TIXML_SSCANF sscanf +#endif + +/* Versioning, past 1.0.14: + http://semver.org/ +*/ +static const int TIXML2_MAJOR_VERSION = 3; +static const int TIXML2_MINOR_VERSION = 0; +static const int TIXML2_PATCH_VERSION = 0; + +namespace tinyxml2 +{ +class XMLDocument; +class XMLElement; +class XMLAttribute; +class XMLComment; +class XMLText; +class XMLDeclaration; +class XMLUnknown; +class XMLPrinter; + +/* + A class that wraps strings. Normally stores the start and end + pointers into the XML file itself, and will apply normalization + and entity translation if actually read. Can also store (and memory + manage) a traditional char[] +*/ +class StrPair +{ +public: + enum { + NEEDS_ENTITY_PROCESSING = 0x01, + NEEDS_NEWLINE_NORMALIZATION = 0x02, + COLLAPSE_WHITESPACE = 0x04, + + TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, + TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, + ATTRIBUTE_NAME = 0, + ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, + ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, + COMMENT = NEEDS_NEWLINE_NORMALIZATION + }; + + StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {} + ~StrPair(); + + void Set( char* start, char* end, int flags ) { + Reset(); + _start = start; + _end = end; + _flags = flags | NEEDS_FLUSH; + } + + const char* GetStr(); + + bool Empty() const { + return _start == _end; + } + + void SetInternedStr( const char* str ) { + Reset(); + _start = const_cast(str); + } + + void SetStr( const char* str, int flags=0 ); + + char* ParseText( char* in, const char* endTag, int strFlags ); + char* ParseName( char* in ); + + void TransferTo( StrPair* other ); + +private: + void Reset(); + void CollapseWhitespace(); + + enum { + NEEDS_FLUSH = 0x100, + NEEDS_DELETE = 0x200 + }; + + // After parsing, if *_end != 0, it can be set to zero. + int _flags; + char* _start; + char* _end; + + StrPair( const StrPair& other ); // not supported + void operator=( StrPair& other ); // not supported, use TransferTo() +}; + + +/* + A dynamic array of Plain Old Data. Doesn't support constructors, etc. + Has a small initial memory pool, so that low or no usage will not + cause a call to new/delete +*/ +template +class DynArray +{ +public: + DynArray() { + _mem = _pool; + _allocated = INIT; + _size = 0; + } + + ~DynArray() { + if ( _mem != _pool ) { + delete [] _mem; + } + } + + void Clear() { + _size = 0; + } + + void Push( T t ) { + TIXMLASSERT( _size < INT_MAX ); + EnsureCapacity( _size+1 ); + _mem[_size++] = t; + } + + T* PushArr( int count ) { + TIXMLASSERT( count >= 0 ); + TIXMLASSERT( _size <= INT_MAX - count ); + EnsureCapacity( _size+count ); + T* ret = &_mem[_size]; + _size += count; + return ret; + } + + T Pop() { + TIXMLASSERT( _size > 0 ); + return _mem[--_size]; + } + + void PopArr( int count ) { + TIXMLASSERT( _size >= count ); + _size -= count; + } + + bool Empty() const { + return _size == 0; + } + + T& operator[](int i) { + TIXMLASSERT( i>= 0 && i < _size ); + return _mem[i]; + } + + const T& operator[](int i) const { + TIXMLASSERT( i>= 0 && i < _size ); + return _mem[i]; + } + + const T& PeekTop() const { + TIXMLASSERT( _size > 0 ); + return _mem[ _size - 1]; + } + + int Size() const { + TIXMLASSERT( _size >= 0 ); + return _size; + } + + int Capacity() const { + return _allocated; + } + + const T* Mem() const { + return _mem; + } + + T* Mem() { + return _mem; + } + +private: + DynArray( const DynArray& ); // not supported + void operator=( const DynArray& ); // not supported + + void EnsureCapacity( int cap ) { + TIXMLASSERT( cap > 0 ); + if ( cap > _allocated ) { + TIXMLASSERT( cap <= INT_MAX / 2 ); + int newAllocated = cap * 2; + T* newMem = new T[newAllocated]; + memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs + if ( _mem != _pool ) { + delete [] _mem; + } + _mem = newMem; + _allocated = newAllocated; + } + } + + T* _mem; + T _pool[INIT]; + int _allocated; // objects allocated + int _size; // number objects in use +}; + + +/* + Parent virtual class of a pool for fast allocation + and deallocation of objects. +*/ +class MemPool +{ +public: + MemPool() {} + virtual ~MemPool() {} + + virtual int ItemSize() const = 0; + virtual void* Alloc() = 0; + virtual void Free( void* ) = 0; + virtual void SetTracked() = 0; + virtual void Clear() = 0; +}; + + +/* + Template child class to create pools of the correct type. +*/ +template< int SIZE > +class MemPoolT : public MemPool +{ +public: + MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {} + ~MemPoolT() { + Clear(); + } + + void Clear() { + // Delete the blocks. + while( !_blockPtrs.Empty()) { + Block* b = _blockPtrs.Pop(); + delete b; + } + _root = 0; + _currentAllocs = 0; + _nAllocs = 0; + _maxAllocs = 0; + _nUntracked = 0; + } + + virtual int ItemSize() const { + return SIZE; + } + int CurrentAllocs() const { + return _currentAllocs; + } + + virtual void* Alloc() { + if ( !_root ) { + // Need a new block. + Block* block = new Block(); + _blockPtrs.Push( block ); + + for( int i=0; ichunk[i].next = &block->chunk[i+1]; + } + block->chunk[COUNT-1].next = 0; + _root = block->chunk; + } + void* result = _root; + _root = _root->next; + + ++_currentAllocs; + if ( _currentAllocs > _maxAllocs ) { + _maxAllocs = _currentAllocs; + } + _nAllocs++; + _nUntracked++; + return result; + } + + virtual void Free( void* mem ) { + if ( !mem ) { + return; + } + --_currentAllocs; + Chunk* chunk = static_cast( mem ); +#ifdef DEBUG + memset( chunk, 0xfe, sizeof(Chunk) ); +#endif + chunk->next = _root; + _root = chunk; + } + void Trace( const char* name ) { + printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n", + name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() ); + } + + void SetTracked() { + _nUntracked--; + } + + int Untracked() const { + return _nUntracked; + } + + // This number is perf sensitive. 4k seems like a good tradeoff on my machine. + // The test file is large, 170k. + // Release: VS2010 gcc(no opt) + // 1k: 4000 + // 2k: 4000 + // 4k: 3900 21000 + // 16k: 5200 + // 32k: 4300 + // 64k: 4000 21000 + enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private + +private: + MemPoolT( const MemPoolT& ); // not supported + void operator=( const MemPoolT& ); // not supported + + union Chunk { + Chunk* next; + char mem[SIZE]; + }; + struct Block { + Chunk chunk[COUNT]; + }; + DynArray< Block*, 10 > _blockPtrs; + Chunk* _root; + + int _currentAllocs; + int _nAllocs; + int _maxAllocs; + int _nUntracked; +}; + + + +/** + Implements the interface to the "Visitor pattern" (see the Accept() method.) + If you call the Accept() method, it requires being passed a XMLVisitor + class to handle callbacks. For nodes that contain other nodes (Document, Element) + you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs + are simply called with Visit(). + + If you return 'true' from a Visit method, recursive parsing will continue. If you return + false, no children of this node or its siblings will be visited. + + All flavors of Visit methods have a default implementation that returns 'true' (continue + visiting). You need to only override methods that are interesting to you. + + Generally Accept() is called on the XMLDocument, although all nodes support visiting. + + You should never change the document from a callback. + + @sa XMLNode::Accept() +*/ +class TINYXML2_LIB XMLVisitor +{ +public: + virtual ~XMLVisitor() {} + + /// Visit a document. + virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { + return true; + } + /// Visit a document. + virtual bool VisitExit( const XMLDocument& /*doc*/ ) { + return true; + } + + /// Visit an element. + virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { + return true; + } + /// Visit an element. + virtual bool VisitExit( const XMLElement& /*element*/ ) { + return true; + } + + /// Visit a declaration. + virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { + return true; + } + /// Visit a text node. + virtual bool Visit( const XMLText& /*text*/ ) { + return true; + } + /// Visit a comment node. + virtual bool Visit( const XMLComment& /*comment*/ ) { + return true; + } + /// Visit an unknown node. + virtual bool Visit( const XMLUnknown& /*unknown*/ ) { + return true; + } +}; + +// WARNING: must match XMLDocument::_errorNames[] +enum XMLError { + XML_SUCCESS = 0, + XML_NO_ERROR = 0, + XML_NO_ATTRIBUTE, + XML_WRONG_ATTRIBUTE_TYPE, + XML_ERROR_FILE_NOT_FOUND, + XML_ERROR_FILE_COULD_NOT_BE_OPENED, + XML_ERROR_FILE_READ_ERROR, + XML_ERROR_ELEMENT_MISMATCH, + XML_ERROR_PARSING_ELEMENT, + XML_ERROR_PARSING_ATTRIBUTE, + XML_ERROR_IDENTIFYING_TAG, + XML_ERROR_PARSING_TEXT, + XML_ERROR_PARSING_CDATA, + XML_ERROR_PARSING_COMMENT, + XML_ERROR_PARSING_DECLARATION, + XML_ERROR_PARSING_UNKNOWN, + XML_ERROR_EMPTY_DOCUMENT, + XML_ERROR_MISMATCHED_ELEMENT, + XML_ERROR_PARSING, + XML_CAN_NOT_CONVERT_TEXT, + XML_NO_TEXT_NODE, + + XML_ERROR_COUNT +}; + + +/* + Utility functionality. +*/ +class XMLUtil +{ +public: + static const char* SkipWhiteSpace( const char* p ) { + TIXMLASSERT( p ); + while( IsWhiteSpace(*p) ) { + ++p; + } + TIXMLASSERT( p ); + return p; + } + static char* SkipWhiteSpace( char* p ) { + return const_cast( SkipWhiteSpace( const_cast(p) ) ); + } + + // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't + // correct, but simple, and usually works. + static bool IsWhiteSpace( char p ) { + return !IsUTF8Continuation(p) && isspace( static_cast(p) ); + } + + inline static bool IsNameStartChar( unsigned char ch ) { + if ( ch >= 128 ) { + // This is a heuristic guess in attempt to not implement Unicode-aware isalpha() + return true; + } + if ( isalpha( ch ) ) { + return true; + } + return ch == ':' || ch == '_'; + } + + inline static bool IsNameChar( unsigned char ch ) { + return IsNameStartChar( ch ) + || isdigit( ch ) + || ch == '.' + || ch == '-'; + } + + inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) { + if ( p == q ) { + return true; + } + int n = 0; + while( *p && *q && *p == *q && n(const_cast(this)->FirstChildElement( value )); + } + + /// Get the last child node, or null if none exists. + const XMLNode* LastChild() const { + return _lastChild; + } + + XMLNode* LastChild() { + return const_cast(const_cast(this)->LastChild() ); + } + + /** Get the last child element or optionally the last child + element with the specified name. + */ + const XMLElement* LastChildElement( const char* value=0 ) const; + + XMLElement* LastChildElement( const char* value=0 ) { + return const_cast(const_cast(this)->LastChildElement(value) ); + } + + /// Get the previous (left) sibling node of this node. + const XMLNode* PreviousSibling() const { + return _prev; + } + + XMLNode* PreviousSibling() { + return _prev; + } + + /// Get the previous (left) sibling element of this node, with an optionally supplied name. + const XMLElement* PreviousSiblingElement( const char* value=0 ) const ; + + XMLElement* PreviousSiblingElement( const char* value=0 ) { + return const_cast(const_cast(this)->PreviousSiblingElement( value ) ); + } + + /// Get the next (right) sibling node of this node. + const XMLNode* NextSibling() const { + return _next; + } + + XMLNode* NextSibling() { + return _next; + } + + /// Get the next (right) sibling element of this node, with an optionally supplied name. + const XMLElement* NextSiblingElement( const char* value=0 ) const; + + XMLElement* NextSiblingElement( const char* value=0 ) { + return const_cast(const_cast(this)->NextSiblingElement( value ) ); + } + + /** + Add a child node as the last (right) child. + If the child node is already part of the document, + it is moved from its old location to the new location. + Returns the addThis argument or 0 if the node does not + belong to the same document. + */ + XMLNode* InsertEndChild( XMLNode* addThis ); + + XMLNode* LinkEndChild( XMLNode* addThis ) { + return InsertEndChild( addThis ); + } + /** + Add a child node as the first (left) child. + If the child node is already part of the document, + it is moved from its old location to the new location. + Returns the addThis argument or 0 if the node does not + belong to the same document. + */ + XMLNode* InsertFirstChild( XMLNode* addThis ); + /** + Add a node after the specified child node. + If the child node is already part of the document, + it is moved from its old location to the new location. + Returns the addThis argument or 0 if the afterThis node + is not a child of this node, or if the node does not + belong to the same document. + */ + XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ); + + /** + Delete all the children of this node. + */ + void DeleteChildren(); + + /** + Delete a child of this node. + */ + void DeleteChild( XMLNode* node ); + + /** + Make a copy of this node, but not its children. + You may pass in a Document pointer that will be + the owner of the new Node. If the 'document' is + null, then the node returned will be allocated + from the current Document. (this->GetDocument()) + + Note: if called on a XMLDocument, this will return null. + */ + virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0; + + /** + Test if 2 nodes are the same, but don't test children. + The 2 nodes do not need to be in the same Document. + + Note: if called on a XMLDocument, this will return false. + */ + virtual bool ShallowEqual( const XMLNode* compare ) const = 0; + + /** Accept a hierarchical visit of the nodes in the TinyXML-2 DOM. Every node in the + XML tree will be conditionally visited and the host will be called back + via the XMLVisitor interface. + + This is essentially a SAX interface for TinyXML-2. (Note however it doesn't re-parse + the XML for the callbacks, so the performance of TinyXML-2 is unchanged by using this + interface versus any other.) + + The interface has been based on ideas from: + + - http://www.saxproject.org/ + - http://c2.com/cgi/wiki?HierarchicalVisitorPattern + + Which are both good references for "visiting". + + An example of using Accept(): + @verbatim + XMLPrinter printer; + tinyxmlDoc.Accept( &printer ); + const char* xmlcstr = printer.CStr(); + @endverbatim + */ + virtual bool Accept( XMLVisitor* visitor ) const = 0; + + // internal + virtual char* ParseDeep( char*, StrPair* ); + +protected: + XMLNode( XMLDocument* ); + virtual ~XMLNode(); + + XMLDocument* _document; + XMLNode* _parent; + mutable StrPair _value; + + XMLNode* _firstChild; + XMLNode* _lastChild; + + XMLNode* _prev; + XMLNode* _next; + +private: + MemPool* _memPool; + void Unlink( XMLNode* child ); + static void DeleteNode( XMLNode* node ); + void InsertChildPreamble( XMLNode* insertThis ) const; + + XMLNode( const XMLNode& ); // not supported + XMLNode& operator=( const XMLNode& ); // not supported +}; + + +/** XML text. + + Note that a text node can have child element nodes, for example: + @verbatim + This is bold + @endverbatim + + A text node can have 2 ways to output the next. "normal" output + and CDATA. It will default to the mode it was parsed from the XML file and + you generally want to leave it alone, but you can change the output mode with + SetCData() and query it with CData(). +*/ +class TINYXML2_LIB XMLText : public XMLNode +{ + friend class XMLBase; + friend class XMLDocument; +public: + virtual bool Accept( XMLVisitor* visitor ) const; + + virtual XMLText* ToText() { + return this; + } + virtual const XMLText* ToText() const { + return this; + } + + /// Declare whether this should be CDATA or standard text. + void SetCData( bool isCData ) { + _isCData = isCData; + } + /// Returns true if this is a CDATA text element. + bool CData() const { + return _isCData; + } + + char* ParseDeep( char*, StrPair* endTag ); + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {} + virtual ~XMLText() {} + +private: + bool _isCData; + + XMLText( const XMLText& ); // not supported + XMLText& operator=( const XMLText& ); // not supported +}; + + +/** An XML Comment. */ +class TINYXML2_LIB XMLComment : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLComment* ToComment() { + return this; + } + virtual const XMLComment* ToComment() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + char* ParseDeep( char*, StrPair* endTag ); + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLComment( XMLDocument* doc ); + virtual ~XMLComment(); + +private: + XMLComment( const XMLComment& ); // not supported + XMLComment& operator=( const XMLComment& ); // not supported +}; + + +/** In correct XML the declaration is the first entry in the file. + @verbatim + + @endverbatim + + TinyXML-2 will happily read or write files without a declaration, + however. + + The text of the declaration isn't interpreted. It is parsed + and written as a string. +*/ +class TINYXML2_LIB XMLDeclaration : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLDeclaration* ToDeclaration() { + return this; + } + virtual const XMLDeclaration* ToDeclaration() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + char* ParseDeep( char*, StrPair* endTag ); + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLDeclaration( XMLDocument* doc ); + virtual ~XMLDeclaration(); + +private: + XMLDeclaration( const XMLDeclaration& ); // not supported + XMLDeclaration& operator=( const XMLDeclaration& ); // not supported +}; + + +/** Any tag that TinyXML-2 doesn't recognize is saved as an + unknown. It is a tag of text, but should not be modified. + It will be written back to the XML, unchanged, when the file + is saved. + + DTD tags get thrown into XMLUnknowns. +*/ +class TINYXML2_LIB XMLUnknown : public XMLNode +{ + friend class XMLDocument; +public: + virtual XMLUnknown* ToUnknown() { + return this; + } + virtual const XMLUnknown* ToUnknown() const { + return this; + } + + virtual bool Accept( XMLVisitor* visitor ) const; + + char* ParseDeep( char*, StrPair* endTag ); + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +protected: + XMLUnknown( XMLDocument* doc ); + virtual ~XMLUnknown(); + +private: + XMLUnknown( const XMLUnknown& ); // not supported + XMLUnknown& operator=( const XMLUnknown& ); // not supported +}; + + + +/** An attribute is a name-value pair. Elements have an arbitrary + number of attributes, each with a unique name. + + @note The attributes are not XMLNodes. You may only query the + Next() attribute in a list. +*/ +class TINYXML2_LIB XMLAttribute +{ + friend class XMLElement; +public: + /// The name of the attribute. + const char* Name() const; + + /// The value of the attribute. + const char* Value() const; + + /// The next attribute in the list. + const XMLAttribute* Next() const { + return _next; + } + + /** IntValue interprets the attribute as an integer, and returns the value. + If the value isn't an integer, 0 will be returned. There is no error checking; + use QueryIntValue() if you need error checking. + */ + int IntValue() const { + int i=0; + QueryIntValue( &i ); + return i; + } + /// Query as an unsigned integer. See IntValue() + unsigned UnsignedValue() const { + unsigned i=0; + QueryUnsignedValue( &i ); + return i; + } + /// Query as a boolean. See IntValue() + bool BoolValue() const { + bool b=false; + QueryBoolValue( &b ); + return b; + } + /// Query as a double. See IntValue() + double DoubleValue() const { + double d=0; + QueryDoubleValue( &d ); + return d; + } + /// Query as a float. See IntValue() + float FloatValue() const { + float f=0; + QueryFloatValue( &f ); + return f; + } + + /** QueryIntValue interprets the attribute as an integer, and returns the value + in the provided parameter. The function will return XML_NO_ERROR on success, + and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful. + */ + XMLError QueryIntValue( int* value ) const; + /// See QueryIntValue + XMLError QueryUnsignedValue( unsigned int* value ) const; + /// See QueryIntValue + XMLError QueryBoolValue( bool* value ) const; + /// See QueryIntValue + XMLError QueryDoubleValue( double* value ) const; + /// See QueryIntValue + XMLError QueryFloatValue( float* value ) const; + + /// Set the attribute to a string value. + void SetAttribute( const char* value ); + /// Set the attribute to value. + void SetAttribute( int value ); + /// Set the attribute to value. + void SetAttribute( unsigned value ); + /// Set the attribute to value. + void SetAttribute( bool value ); + /// Set the attribute to value. + void SetAttribute( double value ); + /// Set the attribute to value. + void SetAttribute( float value ); + +private: + enum { BUF_SIZE = 200 }; + + XMLAttribute() : _next( 0 ), _memPool( 0 ) {} + virtual ~XMLAttribute() {} + + XMLAttribute( const XMLAttribute& ); // not supported + void operator=( const XMLAttribute& ); // not supported + void SetName( const char* name ); + + char* ParseDeep( char* p, bool processEntities ); + + mutable StrPair _name; + mutable StrPair _value; + XMLAttribute* _next; + MemPool* _memPool; +}; + + +/** The element is a container class. It has a value, the element name, + and can contain other elements, text, comments, and unknowns. + Elements also contain an arbitrary number of attributes. +*/ +class TINYXML2_LIB XMLElement : public XMLNode +{ + friend class XMLBase; + friend class XMLDocument; +public: + /// Get the name of an element (which is the Value() of the node.) + const char* Name() const { + return Value(); + } + /// Set the name of the element. + void SetName( const char* str, bool staticMem=false ) { + SetValue( str, staticMem ); + } + + virtual XMLElement* ToElement() { + return this; + } + virtual const XMLElement* ToElement() const { + return this; + } + virtual bool Accept( XMLVisitor* visitor ) const; + + /** Given an attribute name, Attribute() returns the value + for the attribute of that name, or null if none + exists. For example: + + @verbatim + const char* value = ele->Attribute( "foo" ); + @endverbatim + + The 'value' parameter is normally null. However, if specified, + the attribute will only be returned if the 'name' and 'value' + match. This allow you to write code: + + @verbatim + if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar(); + @endverbatim + + rather than: + @verbatim + if ( ele->Attribute( "foo" ) ) { + if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar(); + } + @endverbatim + */ + const char* Attribute( const char* name, const char* value=0 ) const; + + /** Given an attribute name, IntAttribute() returns the value + of the attribute interpreted as an integer. 0 will be + returned if there is an error. For a method with error + checking, see QueryIntAttribute() + */ + int IntAttribute( const char* name ) const { + int i=0; + QueryIntAttribute( name, &i ); + return i; + } + /// See IntAttribute() + unsigned UnsignedAttribute( const char* name ) const { + unsigned i=0; + QueryUnsignedAttribute( name, &i ); + return i; + } + /// See IntAttribute() + bool BoolAttribute( const char* name ) const { + bool b=false; + QueryBoolAttribute( name, &b ); + return b; + } + /// See IntAttribute() + double DoubleAttribute( const char* name ) const { + double d=0; + QueryDoubleAttribute( name, &d ); + return d; + } + /// See IntAttribute() + float FloatAttribute( const char* name ) const { + float f=0; + QueryFloatAttribute( name, &f ); + return f; + } + + /** Given an attribute name, QueryIntAttribute() returns + XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion + can't be performed, or XML_NO_ATTRIBUTE if the attribute + doesn't exist. If successful, the result of the conversion + will be written to 'value'. If not successful, nothing will + be written to 'value'. This allows you to provide default + value: + + @verbatim + int value = 10; + QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 + @endverbatim + */ + XMLError QueryIntAttribute( const char* name, int* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryIntValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryUnsignedValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryBoolAttribute( const char* name, bool* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryBoolValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryDoubleAttribute( const char* name, double* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryDoubleValue( value ); + } + /// See QueryIntAttribute() + XMLError QueryFloatAttribute( const char* name, float* value ) const { + const XMLAttribute* a = FindAttribute( name ); + if ( !a ) { + return XML_NO_ATTRIBUTE; + } + return a->QueryFloatValue( value ); + } + + + /** Given an attribute name, QueryAttribute() returns + XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion + can't be performed, or XML_NO_ATTRIBUTE if the attribute + doesn't exist. It is overloaded for the primitive types, + and is a generally more convenient replacement of + QueryIntAttribute() and related functions. + + If successful, the result of the conversion + will be written to 'value'. If not successful, nothing will + be written to 'value'. This allows you to provide default + value: + + @verbatim + int value = 10; + QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 + @endverbatim + */ + int QueryAttribute( const char* name, int* value ) const { + return QueryIntAttribute( name, value ); + } + + int QueryAttribute( const char* name, unsigned int* value ) const { + return QueryUnsignedAttribute( name, value ); + } + + int QueryAttribute( const char* name, bool* value ) const { + return QueryBoolAttribute( name, value ); + } + + int QueryAttribute( const char* name, double* value ) const { + return QueryDoubleAttribute( name, value ); + } + + int QueryAttribute( const char* name, float* value ) const { + return QueryFloatAttribute( name, value ); + } + + /// Sets the named attribute to value. + void SetAttribute( const char* name, const char* value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, int value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, unsigned value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, bool value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, double value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + /// Sets the named attribute to value. + void SetAttribute( const char* name, float value ) { + XMLAttribute* a = FindOrCreateAttribute( name ); + a->SetAttribute( value ); + } + + /** + Delete an attribute. + */ + void DeleteAttribute( const char* name ); + + /// Return the first attribute in the list. + const XMLAttribute* FirstAttribute() const { + return _rootAttribute; + } + /// Query a specific attribute in the list. + const XMLAttribute* FindAttribute( const char* name ) const; + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, GetText() is limited compared to getting the XMLText child + and accessing it directly. + + If the first child of 'this' is a XMLText, the GetText() + returns the character string of the Text node, else null is returned. + + This is a convenient method for getting the text of simple contained text: + @verbatim + This is text + const char* str = fooElement->GetText(); + @endverbatim + + 'str' will be a pointer to "This is text". + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then the value of str would be null. The first child node isn't a text node, it is + another element. From this XML: + @verbatim + This is text + @endverbatim + GetText() will return "This is ". + */ + const char* GetText() const; + + /** Convenience function for easy access to the text inside an element. Although easy + and concise, SetText() is limited compared to creating an XMLText child + and mutating it directly. + + If the first child of 'this' is a XMLText, SetText() sets its value to + the given string, otherwise it will create a first child that is an XMLText. + + This is a convenient method for setting the text of simple contained text: + @verbatim + This is text + fooElement->SetText( "Hullaballoo!" ); + Hullaballoo! + @endverbatim + + Note that this function can be misleading. If the element foo was created from + this XML: + @verbatim + This is text + @endverbatim + + then it will not change "This is text", but rather prefix it with a text element: + @verbatim + Hullaballoo!This is text + @endverbatim + + For this XML: + @verbatim + + @endverbatim + SetText() will generate + @verbatim + Hullaballoo! + @endverbatim + */ + void SetText( const char* inText ); + /// Convenience method for setting text inside and element. See SetText() for important limitations. + void SetText( int value ); + /// Convenience method for setting text inside and element. See SetText() for important limitations. + void SetText( unsigned value ); + /// Convenience method for setting text inside and element. See SetText() for important limitations. + void SetText( bool value ); + /// Convenience method for setting text inside and element. See SetText() for important limitations. + void SetText( double value ); + /// Convenience method for setting text inside and element. See SetText() for important limitations. + void SetText( float value ); + + /** + Convenience method to query the value of a child text node. This is probably best + shown by example. Given you have a document is this form: + @verbatim + + 1 + 1.4 + + @endverbatim + + The QueryIntText() and similar functions provide a safe and easier way to get to the + "value" of x and y. + + @verbatim + int x = 0; + float y = 0; // types of x and y are contrived for example + const XMLElement* xElement = pointElement->FirstChildElement( "x" ); + const XMLElement* yElement = pointElement->FirstChildElement( "y" ); + xElement->QueryIntText( &x ); + yElement->QueryFloatText( &y ); + @endverbatim + + @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted + to the requested type, and XML_NO_TEXT_NODE if there is no child text to query. + + */ + XMLError QueryIntText( int* ival ) const; + /// See QueryIntText() + XMLError QueryUnsignedText( unsigned* uval ) const; + /// See QueryIntText() + XMLError QueryBoolText( bool* bval ) const; + /// See QueryIntText() + XMLError QueryDoubleText( double* dval ) const; + /// See QueryIntText() + XMLError QueryFloatText( float* fval ) const; + + // internal: + enum { + OPEN, // + CLOSED, // + CLOSING // + }; + int ClosingType() const { + return _closingType; + } + char* ParseDeep( char* p, StrPair* endTag ); + virtual XMLNode* ShallowClone( XMLDocument* document ) const; + virtual bool ShallowEqual( const XMLNode* compare ) const; + +private: + XMLElement( XMLDocument* doc ); + virtual ~XMLElement(); + XMLElement( const XMLElement& ); // not supported + void operator=( const XMLElement& ); // not supported + + XMLAttribute* FindAttribute( const char* name ) { + return const_cast(const_cast(this)->FindAttribute( name )); + } + XMLAttribute* FindOrCreateAttribute( const char* name ); + //void LinkAttribute( XMLAttribute* attrib ); + char* ParseAttributes( char* p ); + static void DeleteAttribute( XMLAttribute* attribute ); + + enum { BUF_SIZE = 200 }; + int _closingType; + // The attribute list is ordered; there is no 'lastAttribute' + // because the list needs to be scanned for dupes before adding + // a new attribute. + XMLAttribute* _rootAttribute; +}; + + +enum Whitespace { + PRESERVE_WHITESPACE, + COLLAPSE_WHITESPACE +}; + + +/** A Document binds together all the functionality. + It can be saved, loaded, and printed to the screen. + All Nodes are connected and allocated to a Document. + If the Document is deleted, all its Nodes are also deleted. +*/ +class TINYXML2_LIB XMLDocument : public XMLNode +{ + friend class XMLElement; +public: + /// constructor + XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE ); + ~XMLDocument(); + + virtual XMLDocument* ToDocument() { + return this; + } + virtual const XMLDocument* ToDocument() const { + return this; + } + + /** + Parse an XML file from a character string. + Returns XML_NO_ERROR (0) on success, or + an errorID. + + You may optionally pass in the 'nBytes', which is + the number of bytes which will be parsed. If not + specified, TinyXML-2 will assume 'xml' points to a + null terminated string. + */ + XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) ); + + /** + Load an XML file from disk. + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError LoadFile( const char* filename ); + + /** + Load an XML file from disk. You are responsible + for providing and closing the FILE*. + + NOTE: The file should be opened as binary ("rb") + not text in order for TinyXML-2 to correctly + do newline normalization. + + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError LoadFile( FILE* ); + + /** + Save the XML file to disk. + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError SaveFile( const char* filename, bool compact = false ); + + /** + Save the XML file to disk. You are responsible + for providing and closing the FILE*. + + Returns XML_NO_ERROR (0) on success, or + an errorID. + */ + XMLError SaveFile( FILE* fp, bool compact = false ); + + bool ProcessEntities() const { + return _processEntities; + } + Whitespace WhitespaceMode() const { + return _whitespace; + } + + /** + Returns true if this document has a leading Byte Order Mark of UTF8. + */ + bool HasBOM() const { + return _writeBOM; + } + /** Sets whether to write the BOM when writing the file. + */ + void SetBOM( bool useBOM ) { + _writeBOM = useBOM; + } + + /** Return the root element of DOM. Equivalent to FirstChildElement(). + To get the first node, use FirstChild(). + */ + XMLElement* RootElement() { + return FirstChildElement(); + } + const XMLElement* RootElement() const { + return FirstChildElement(); + } + + /** Print the Document. If the Printer is not provided, it will + print to stdout. If you provide Printer, this can print to a file: + @verbatim + XMLPrinter printer( fp ); + doc.Print( &printer ); + @endverbatim + + Or you can use a printer to print to memory: + @verbatim + XMLPrinter printer; + doc.Print( &printer ); + // printer.CStr() has a const char* to the XML + @endverbatim + */ + void Print( XMLPrinter* streamer=0 ) const; + virtual bool Accept( XMLVisitor* visitor ) const; + + /** + Create a new Element associated with + this Document. The memory for the Element + is managed by the Document. + */ + XMLElement* NewElement( const char* name ); + /** + Create a new Comment associated with + this Document. The memory for the Comment + is managed by the Document. + */ + XMLComment* NewComment( const char* comment ); + /** + Create a new Text associated with + this Document. The memory for the Text + is managed by the Document. + */ + XMLText* NewText( const char* text ); + /** + Create a new Declaration associated with + this Document. The memory for the object + is managed by the Document. + + If the 'text' param is null, the standard + declaration is used.: + @verbatim + + @endverbatim + */ + XMLDeclaration* NewDeclaration( const char* text=0 ); + /** + Create a new Unknown associated with + this Document. The memory for the object + is managed by the Document. + */ + XMLUnknown* NewUnknown( const char* text ); + + /** + Delete a node associated with this document. + It will be unlinked from the DOM. + */ + void DeleteNode( XMLNode* node ); + + void SetError( XMLError error, const char* str1, const char* str2 ); + + /// Return true if there was an error parsing the document. + bool Error() const { + return _errorID != XML_NO_ERROR; + } + /// Return the errorID. + XMLError ErrorID() const { + return _errorID; + } + const char* ErrorName() const; + + /// Return a possibly helpful diagnostic location or string. + const char* GetErrorStr1() const { + return _errorStr1; + } + /// Return a possibly helpful secondary diagnostic location or string. + const char* GetErrorStr2() const { + return _errorStr2; + } + /// If there is an error, print it to stdout. + void PrintError() const; + + /// Clear the document, resetting it to the initial state. + void Clear(); + + // internal + char* Identify( char* p, XMLNode** node ); + + virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { + return 0; + } + virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { + return false; + } + +private: + XMLDocument( const XMLDocument& ); // not supported + void operator=( const XMLDocument& ); // not supported + + bool _writeBOM; + bool _processEntities; + XMLError _errorID; + Whitespace _whitespace; + const char* _errorStr1; + const char* _errorStr2; + char* _charBuffer; + + MemPoolT< sizeof(XMLElement) > _elementPool; + MemPoolT< sizeof(XMLAttribute) > _attributePool; + MemPoolT< sizeof(XMLText) > _textPool; + MemPoolT< sizeof(XMLComment) > _commentPool; + + static const char* _errorNames[XML_ERROR_COUNT]; + + void Parse(); +}; + + +/** + A XMLHandle is a class that wraps a node pointer with null checks; this is + an incredibly useful thing. Note that XMLHandle is not part of the TinyXML-2 + DOM structure. It is a separate utility class. + + Take an example: + @verbatim + + + + + + + @endverbatim + + Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very + easy to write a *lot* of code that looks like: + + @verbatim + XMLElement* root = document.FirstChildElement( "Document" ); + if ( root ) + { + XMLElement* element = root->FirstChildElement( "Element" ); + if ( element ) + { + XMLElement* child = element->FirstChildElement( "Child" ); + if ( child ) + { + XMLElement* child2 = child->NextSiblingElement( "Child" ); + if ( child2 ) + { + // Finally do something useful. + @endverbatim + + And that doesn't even cover "else" cases. XMLHandle addresses the verbosity + of such code. A XMLHandle checks for null pointers so it is perfectly safe + and correct to use: + + @verbatim + XMLHandle docHandle( &document ); + XMLElement* child2 = docHandle.FirstChildElement( "Document" ).FirstChildElement( "Element" ).FirstChildElement().NextSiblingElement(); + if ( child2 ) + { + // do something useful + @endverbatim + + Which is MUCH more concise and useful. + + It is also safe to copy handles - internally they are nothing more than node pointers. + @verbatim + XMLHandle handleCopy = handle; + @endverbatim + + See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects. +*/ +class TINYXML2_LIB XMLHandle +{ +public: + /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. + XMLHandle( XMLNode* node ) { + _node = node; + } + /// Create a handle from a node. + XMLHandle( XMLNode& node ) { + _node = &node; + } + /// Copy constructor + XMLHandle( const XMLHandle& ref ) { + _node = ref._node; + } + /// Assignment + XMLHandle& operator=( const XMLHandle& ref ) { + _node = ref._node; + return *this; + } + + /// Get the first child of this handle. + XMLHandle FirstChild() { + return XMLHandle( _node ? _node->FirstChild() : 0 ); + } + /// Get the first child element of this handle. + XMLHandle FirstChildElement( const char* value=0 ) { + return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 ); + } + /// Get the last child of this handle. + XMLHandle LastChild() { + return XMLHandle( _node ? _node->LastChild() : 0 ); + } + /// Get the last child element of this handle. + XMLHandle LastChildElement( const char* _value=0 ) { + return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 ); + } + /// Get the previous sibling of this handle. + XMLHandle PreviousSibling() { + return XMLHandle( _node ? _node->PreviousSibling() : 0 ); + } + /// Get the previous sibling element of this handle. + XMLHandle PreviousSiblingElement( const char* _value=0 ) { + return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 ); + } + /// Get the next sibling of this handle. + XMLHandle NextSibling() { + return XMLHandle( _node ? _node->NextSibling() : 0 ); + } + /// Get the next sibling element of this handle. + XMLHandle NextSiblingElement( const char* _value=0 ) { + return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 ); + } + + /// Safe cast to XMLNode. This can return null. + XMLNode* ToNode() { + return _node; + } + /// Safe cast to XMLElement. This can return null. + XMLElement* ToElement() { + return ( ( _node == 0 ) ? 0 : _node->ToElement() ); + } + /// Safe cast to XMLText. This can return null. + XMLText* ToText() { + return ( ( _node == 0 ) ? 0 : _node->ToText() ); + } + /// Safe cast to XMLUnknown. This can return null. + XMLUnknown* ToUnknown() { + return ( ( _node == 0 ) ? 0 : _node->ToUnknown() ); + } + /// Safe cast to XMLDeclaration. This can return null. + XMLDeclaration* ToDeclaration() { + return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() ); + } + +private: + XMLNode* _node; +}; + + +/** + A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the + same in all regards, except for the 'const' qualifiers. See XMLHandle for API. +*/ +class TINYXML2_LIB XMLConstHandle +{ +public: + XMLConstHandle( const XMLNode* node ) { + _node = node; + } + XMLConstHandle( const XMLNode& node ) { + _node = &node; + } + XMLConstHandle( const XMLConstHandle& ref ) { + _node = ref._node; + } + + XMLConstHandle& operator=( const XMLConstHandle& ref ) { + _node = ref._node; + return *this; + } + + const XMLConstHandle FirstChild() const { + return XMLConstHandle( _node ? _node->FirstChild() : 0 ); + } + const XMLConstHandle FirstChildElement( const char* value=0 ) const { + return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 ); + } + const XMLConstHandle LastChild() const { + return XMLConstHandle( _node ? _node->LastChild() : 0 ); + } + const XMLConstHandle LastChildElement( const char* _value=0 ) const { + return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 ); + } + const XMLConstHandle PreviousSibling() const { + return XMLConstHandle( _node ? _node->PreviousSibling() : 0 ); + } + const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const { + return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 ); + } + const XMLConstHandle NextSibling() const { + return XMLConstHandle( _node ? _node->NextSibling() : 0 ); + } + const XMLConstHandle NextSiblingElement( const char* _value=0 ) const { + return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 ); + } + + + const XMLNode* ToNode() const { + return _node; + } + const XMLElement* ToElement() const { + return ( ( _node == 0 ) ? 0 : _node->ToElement() ); + } + const XMLText* ToText() const { + return ( ( _node == 0 ) ? 0 : _node->ToText() ); + } + const XMLUnknown* ToUnknown() const { + return ( ( _node == 0 ) ? 0 : _node->ToUnknown() ); + } + const XMLDeclaration* ToDeclaration() const { + return ( ( _node == 0 ) ? 0 : _node->ToDeclaration() ); + } + +private: + const XMLNode* _node; +}; + + +/** + Printing functionality. The XMLPrinter gives you more + options than the XMLDocument::Print() method. + + It can: + -# Print to memory. + -# Print to a file you provide. + -# Print XML without a XMLDocument. + + Print to Memory + + @verbatim + XMLPrinter printer; + doc.Print( &printer ); + SomeFunction( printer.CStr() ); + @endverbatim + + Print to a File + + You provide the file pointer. + @verbatim + XMLPrinter printer( fp ); + doc.Print( &printer ); + @endverbatim + + Print without a XMLDocument + + When loading, an XML parser is very useful. However, sometimes + when saving, it just gets in the way. The code is often set up + for streaming, and constructing the DOM is just overhead. + + The Printer supports the streaming case. The following code + prints out a trivially simple XML file without ever creating + an XML document. + + @verbatim + XMLPrinter printer( fp ); + printer.OpenElement( "foo" ); + printer.PushAttribute( "foo", "bar" ); + printer.CloseElement(); + @endverbatim +*/ +class TINYXML2_LIB XMLPrinter : public XMLVisitor +{ +public: + /** Construct the printer. If the FILE* is specified, + this will print to the FILE. Else it will print + to memory, and the result is available in CStr(). + If 'compact' is set to true, then output is created + with only required whitespace and newlines. + */ + XMLPrinter( FILE* file=0, bool compact = false, int depth = 0 ); + virtual ~XMLPrinter() {} + + /** If streaming, write the BOM and declaration. */ + void PushHeader( bool writeBOM, bool writeDeclaration ); + /** If streaming, start writing an element. + The element must be closed with CloseElement() + */ + void OpenElement( const char* name, bool compactMode=false ); + /// If streaming, add an attribute to an open element. + void PushAttribute( const char* name, const char* value ); + void PushAttribute( const char* name, int value ); + void PushAttribute( const char* name, unsigned value ); + void PushAttribute( const char* name, bool value ); + void PushAttribute( const char* name, double value ); + /// If streaming, close the Element. + virtual void CloseElement( bool compactMode=false ); + + /// Add a text node. + void PushText( const char* text, bool cdata=false ); + /// Add a text node from an integer. + void PushText( int value ); + /// Add a text node from an unsigned. + void PushText( unsigned value ); + /// Add a text node from a bool. + void PushText( bool value ); + /// Add a text node from a float. + void PushText( float value ); + /// Add a text node from a double. + void PushText( double value ); + + /// Add a comment + void PushComment( const char* comment ); + + void PushDeclaration( const char* value ); + void PushUnknown( const char* value ); + + virtual bool VisitEnter( const XMLDocument& /*doc*/ ); + virtual bool VisitExit( const XMLDocument& /*doc*/ ) { + return true; + } + + virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute ); + virtual bool VisitExit( const XMLElement& element ); + + virtual bool Visit( const XMLText& text ); + virtual bool Visit( const XMLComment& comment ); + virtual bool Visit( const XMLDeclaration& declaration ); + virtual bool Visit( const XMLUnknown& unknown ); + + /** + If in print to memory mode, return a pointer to + the XML file in memory. + */ + const char* CStr() const { + return _buffer.Mem(); + } + /** + If in print to memory mode, return the size + of the XML file in memory. (Note the size returned + includes the terminating null.) + */ + int CStrSize() const { + return _buffer.Size(); + } + /** + If in print to memory mode, reset the buffer to the + beginning. + */ + void ClearBuffer() { + _buffer.Clear(); + _buffer.Push(0); + } + +protected: + virtual bool CompactMode( const XMLElement& ) { return _compactMode; } + + /** Prints out the space before an element. You may override to change + the space and tabs used. A PrintSpace() override should call Print(). + */ + virtual void PrintSpace( int depth ); + void Print( const char* format, ... ); + + void SealElementIfJustOpened(); + bool _elementJustOpened; + DynArray< const char*, 10 > _stack; + +private: + void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities. + + bool _firstElement; + FILE* _fp; + int _depth; + int _textDepth; + bool _processEntities; + bool _compactMode; + + enum { + ENTITY_RANGE = 64, + BUF_SIZE = 200 + }; + bool _entityFlag[ENTITY_RANGE]; + bool _restrictedEntityFlag[ENTITY_RANGE]; + + DynArray< char, 20 > _buffer; +}; + + +} // tinyxml2 + +#if defined(_MSC_VER) +# pragma warning(pop) +#endif + +#endif // TINYXML2_INCLUDED diff --git a/sg_agent/src/main.cc b/sg_agent/src/main.cc new file mode 100644 index 0000000..bb90517 --- /dev/null +++ b/sg_agent/src/main.cc @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include "mns/agent_server.h" +#include "mns/agent_init.h" +#include +#include "ServiceAgent.h" +#include "mns/config_loader.h" +#include "mns/agent_init.h" + +using namespace std; +using namespace muduo; +using namespace muduo::net; +using namespace meituan_cthrift; +using namespace meituan_mns; + +int main(int argc, char **argv) { + + meituan_mns::AgentInit agent_init; + std::string log_path = ""; + agent_init.PreloadLogConfigPath(log_path); + log4cplus::PropertyConfigurator::doConfigure(LOG4CPLUS_TEXT(log_path)); + agent_init.Init(); + + string str_svr_appkey(CXmlFile::GetStrPara(CXmlFile::AgentAppKey)); //服务端的appkey + uint16_t u16_port = 5266; + bool b_single_thread = false; //当时单线程运行时,worker thread num 只能是1 + int32_t i32_timeout_ms = 30; + int32_t i32_max_conn_num = 20000; + int16_t i16_worker_thread_num = 4; + switch (argc) { + case 1: + break; + case 7: + str_svr_appkey.assign(argv[1]); + u16_port = static_cast(atoi(argv[2])); + b_single_thread = (1 == atoi(argv[3])) ? true : false; + i32_timeout_ms = atoi(argv[4]); + i32_max_conn_num = atoi(argv[5]); + i16_worker_thread_num = static_cast(atoi(argv[6])); + break; + default: + exit(-1); + } + std::cout << "start server........." << std::endl; + + try { + boost::shared_ptr handler(new meituan_mns::SGAgentServer()); + meituan_mns::ServiceAgentProcessor *processor_tmp = new + meituan_mns::ServiceAgentProcessor(handler); + boost::shared_ptr processor(processor_tmp); + + meituan_cthrift::CthriftSvr server(processor); + + if(server.Init() != 0) { + cerr << "server init error" << endl; + return -1; + } + + sleep(6); + server.serve(); + std::cout << "start naming service server..."<< std::endl; + } catch (meituan_cthrift::TException &tx) { + LOG_ERROR << tx.what(); + return -1; + } catch (int e) { + return e; + } + + return 0; +} diff --git a/sg_agent/src/mns/CMakeLists.txt b/sg_agent/src/mns/CMakeLists.txt new file mode 100644 index 0000000..548e293 --- /dev/null +++ b/sg_agent/src/mns/CMakeLists.txt @@ -0,0 +1,103 @@ +INCLUDE_DIRECTORIES(${THRIFT_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(/usr/include) +INCLUDE_DIRECTORIES(${CLOG_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${BOOST_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${MUDUO_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${ZOOKEEPER_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${THRIFT_GEN_CPP_PATH}) +INCLUDE_DIRECTORIES(${AGENT_SRC_PATH}) +INCLUDE_DIRECTORIES(${CTHRIFT_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${UTIL_PATH}) +INCLUDE_DIRECTORIES(${RULE_PATH}) +INCLUDE_DIRECTORIES(${MCC_PATH}) +INCLUDE_DIRECTORIES(${COMMONLOG_PATH}) +INCLUDE_DIRECTORIES(${MAFKA_PATH}) +INCLUDE_DIRECTORIES(${FALCON_PATH}) +INCLUDE_DIRECTORIES(${MONITOR_COLLECTOR_PATH}) +INCLUDE_DIRECTORIES(${LOG4CPLUS_PATH}) +INCLUDE_DIRECTORIES(${LOG4CPLUS_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${CTHRIFT_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${SDK_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(../../thrid_party/log4cplus) +INCLUDE_DIRECTORIES(../../../common/gen-cpp) +INCLUDE_DIRECTORIES(../remote/monitor) +INCLUDE_DIRECTORIES(../util) +INCLUDE_DIRECTORIES(../comm) +INCLUDE_DIRECTORIES(../rule) +INCLUDE_DIRECTORIES(../mns) + +SET(THRIFT_GEN_CPP_PATH ../../../common/gen-cpp) +MESSAGE(STATUS "THRIFT_GEN_CPP_PATH DIR ${THRIFT_GEN_CPP_PATH}") + +SET(MNS_SDK_LIB thrid_party/cthrift/lib/libmns_sdk.a) + +SET(THRIFT_GENCPP_SRCS + ${THRIFT_GEN_CPP_PATH}/MNSCacheService.cpp + ${THRIFT_GEN_CPP_PATH}/mnsc_data_constants.cpp + ${THRIFT_GEN_CPP_PATH}/mnsc_data_types.cpp + ${THRIFT_GEN_CPP_PATH}/mnsc_service_constants.cpp + ${THRIFT_GEN_CPP_PATH}/mnsc_service_types.cpp + ${THRIFT_GEN_CPP_PATH}/naming_common_constants.cpp + ${THRIFT_GEN_CPP_PATH}/naming_common_types.cpp + ${THRIFT_GEN_CPP_PATH}/naming_service_constants.cpp + ${THRIFT_GEN_CPP_PATH}/naming_service_types.cpp + ${THRIFT_GEN_CPP_PATH}/unified_protocol_constants.cpp + ${THRIFT_GEN_CPP_PATH}/unified_protocol_types.cpp + ${THRIFT_GEN_CPP_PATH}/ServiceAgent.cpp + ) + +SET(AGENT_COMM_SRCS + ${COMMON_PATH}/tinyxml2.cc + ${COMMON_PATH}/md5.cc + ${COMMON_PATH}/cJSON.c + ) + +SET(AGENT_UTIL_SRCS + ${UTIL_PATH}/json_data_tools.cc + ${UTIL_PATH}/zk_path_tools.cc + ${UTIL_PATH}/version_manager.cc + ${UTIL_PATH}/thrift_connection.cc + ${UTIL_PATH}/whitelist_manager.cc + ${UTIL_PATH}/falcon_mgr.cc + ) + +SET(AGENT_RULE_SRCS + ${RULE_PATH}/route_rule.cc + ${RULE_PATH}/route_base.cc + ${RULE_PATH}/route_info.cc + ) + +SET(MNS_LIB_SRCS + zk_client.cc + zk_client_pool.cc + registry_service.cc + registry_strategy.cc + discovery_service.cc + discovery_zk_client.cc + hot_load_config.cc + config_loader.cc + agent_init.cc + agent_server.cc + service_channels.cc + mnsc_client.cc + http_service.cc + ) + +SET(MONITOR_COLLECTOR_SRCS + ${MONITOR_COLLECTOR_PATH}/monitor_collector.cc + ) +SET(LOG4CPLUS_SRCS + ${LOG4CPLUS_PATH}/log4cplus.cpp + ) + +ADD_EXECUTABLE(ServiceAgent ${AGENT_SRC_PATH}/main.cc ${MNS_LIB_SRCS} + ${THRIFT_GENCPP_SRCS} ${AGENT_COMM_SRCS} ${MONITOR_COLLECTOR_SRCS} + ${AGENT_UTIL_SRCS} ${AGENT_RULE_SRCS} ${LOG4CPLUS_SRCS} + ) +TARGET_LINK_LIBRARIES(ServiceAgent -Xlinker "-(" ${MUDUO_BASE_LIBRARY} + ${THRIFTNB_STATIC_LIB} ${THRIFT_STATIC_LIB} ${LOG4CPLUS_LIBRARY} + ${MUDUO_NET_LIBRARY} ${MUDUO_HTTP_LIBRARY} ${MNS_SDK_LIBRARY} + ${CTHRIFT_LIBRARY} ${ZOOKEEPER_LIBRARY} boost_system event uuid ssl + dl pthread rt -Xlinker "-)" ) + + diff --git a/sg_agent/src/mns/agent_init.cc b/sg_agent/src/mns/agent_init.cc new file mode 100644 index 0000000..7c131ae --- /dev/null +++ b/sg_agent/src/mns/agent_init.cc @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include "agent_init.h" +#include "zk_client_pool.h" +#include "log4cplus.h" +#include "base_consts.h" +#include +#include "http_service.h" +#include "hot_load_config.h" +#include "discovery_service.h" +#include "registry_service.h" +namespace meituan_mns { + +AgentInit::AgentInit(): is_zk_init_(false), + is_loadfile_init_(false), + is_disc_init_(false), + latch(1), + healthy_interval_secs(HealthCheckInterval) {} + +AgentInit::~AgentInit() {} + +void AgentInit::SetLocolServiceNode(SGService& service){ + service.appkey = CXmlFile::GetStrPara(CXmlFile::AgentAppKey); + service.version = CXmlFile::GetStrPara(CXmlFile::AgentVersion); + service.ip = CXmlFile::GetStrPara(CXmlFile::LocalIp); + service.port = CXmlFile::GetI32Para(CXmlFile::AgentPort); + service.weight = kDefaultWeight; + service.fweight = kDefaultFweight; + service.status = fb_status::ALIVE; + service.protocol = kDefaultStrProtocol; + service.envir = CXmlFile::GetAppenv()->GetIntEnv(); + service.lastUpdateTime = time(0); + service.role = 0; + service.warmup = 0; + NS_LOG_INFO(" service.appkey = " << service.appkey << ", service.port = " + << service.port << ", service.fweigit = " + << service.fweight); +} + +int32_t AgentInit::PreloadLogConfigPath(std::string& log_path){ + log_path = cxml_file_.GetLogPath(); + std::cout <<"agent log path:" <StartHttpServer(); + NS_LOG_INFO("OCTO Service Agent End ..."); + + SGService oservice; + SetLocolServiceNode(oservice); + int ret = RegistryService::GetInstance()->RegistryStart(oservice, UptCmd::ADD); + if (SUCCESS != ret) { + NS_LOG_ERROR("failed to regist sg_agent to registry center, ret = " + << ret); + } + NS_LOG_INFO("succeed to regist self to mns ret:" << ret); +} + +void AgentInit::HealthCheckFailed() { + if (healthy_interval_secs >= HealthCheckMaxInterval) { + healthy_interval_secs = HealthCheckMaxInterval; + } + healthy_loop_->runAfter(HealthCheckInterval, + boost::bind(&AgentInit::HealthCheck, this)); + healthy_interval_secs += HealthCheckInterval; +} + +int32_t AgentInit::HealthCheck() { + int32_t ret = 0; + if (!is_loadfile_init_) { + ret = cxml_file_.CXmlFileInit(); + if (0 != ret) { + HealthCheckFailed(); + return ret; + } + is_loadfile_init_ = true; + } + if (!is_zk_init_) { + std::string zk_lists = cxml_file_.GetStrPara(CXmlFile::ZkLists); + boost::trim(zk_lists); + ret = + ZkClientPool::GetInstance()->Init(CXmlFile::GetStrPara(CXmlFile::ZkLists), + CXmlFile::GetI32Para(CXmlFile::ZkClientNum), + CXmlFile::GetI32Para(CXmlFile::ZkTimeout), + CXmlFile::GetI32Para(CXmlFile::RetryTimes)); + if (SUCCESS != ret) { + NS_LOG_ERROR("failed to create zkclient pool ,ret = " << ret); + HealthCheckFailed(); + return ret; + } + is_zk_init_ = true; + } + + if (!is_disc_init_) { + ret = DiscoveryService::GetInstance()->Init(); + if (SUCCESS != ret) { + NS_LOG_INFO("failed to init discovery service."); + HealthCheckFailed(); + return ret; + } + is_disc_init_ = true; + } + NS_LOG_INFO("Healthy check success"); + if (1 == latch.getCount()) { + latch.countDown(); + } +} + +} // namespace meituan_mns diff --git a/sg_agent/src/mns/agent_init.h b/sg_agent/src/mns/agent_init.h new file mode 100644 index 0000000..48b9980 --- /dev/null +++ b/sg_agent/src/mns/agent_init.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef SRC_MNS_AGENT_INIT_H_ +#define SRC_MNS_AGENT_INIT_H_ +#include "config_loader.h" +#include +#include +#include +#include "naming_common_types.h" +#include +namespace meituan_mns { + +class AgentInit { + public: + AgentInit(); + ~AgentInit(); + void Init(void); + int32_t HealthCheck(void); + void HealthCheckFailed(void); + int32_t PreloadLogConfigPath(std::string& log_path); + protected: + private: + void SetLocolServiceNode(SGService& service); + + CXmlFile cxml_file_; + bool is_zk_init_; + bool is_loadfile_init_; + bool is_disc_init_; + muduo::CountDownLatch latch; + int32_t healthy_interval_secs; + muduo::net::EventLoopThread healthy_loop_thread_; + muduo::net::EventLoop *healthy_loop_; +}; +} // namespace meituan_mns + +#endif // SRC_MNS_AGENT_INIT_H_ diff --git a/sg_agent/src/mns/agent_server.cc b/sg_agent/src/mns/agent_server.cc new file mode 100644 index 0000000..7b6ace0 --- /dev/null +++ b/sg_agent/src/mns/agent_server.cc @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include "agent_server.h" +#include "registry_service.h" +#include "naming_common_types.h" +#include "registry_base.h" +#include "service_channels.h" +#include "discovery_service.h" + +namespace meituan_mns { + +SGAgentServer::SGAgentServer() { +} + +int SGAgentServer::Init() { + return 0; +} +/** + *@ rpc注册接口 + * + *@param 上下线类型 + *@param SGService 注册参数 + * + *@return int + * + * */ + +int32_t SGAgentServer::registServicewithCmd(const int32_t uptCmd, + const SGService &oService) { + NS_LOG_INFO("the registry cmd = "<< uptCmd + <<"registry appkey = "<< oService.appkey + <<"registry ip = "<< oService.ip); + int ret = -1; + + boost::shared_ptr registry_factory = + boost::make_shared(); + + Registry *registry = registry_factory->CreateRegistry((RegistryType)uptCmd); + + ret = registry->RegistryStart(oService, uptCmd); + + return ret; +} +/** + *@ rpc服务下线接口 + * + *@param SGService 注册参数 + * + *@return int + * + * */ +int32_t SGAgentServer::unRegistService(const SGService &oService) { + NS_LOG_INFO("the unRegistry"<< oService.appkey <<" ;registry ip = " + << oService.ip); + int ret = -1; + + boost::shared_ptr registry_factory = boost::make_shared(); + + Registry *registry = registry_factory->CreateRegistry(kAddReg); + + ret = registry->RegistryStart(oService, RegistCmd::UNREGIST); + + return ret; +} + +void SGAgentServer::getServiceListByProtocol(ProtocolResponse &_return, const ProtocolRequest &req) { + boost::shared_ptr service_channel = boost::make_shared(); + service_channel->SetAllChannel(false); + service_channel->SetBankboneChannel(false); + service_channel->SetOriginChannel(false); + service_channel->SetSwimlaneChannel(false); + + DiscoveryService::GetInstance()->DiscGetSrvList(_return.servicelist, req, service_channel); + + NS_LOG_INFO("getOriginServiceList size = " << _return.servicelist.size() + << ", remoteAppkey = " << req.remoteAppkey + << ", protocol = " << req.protocol + << ", errorCode = " << _return.errcode); + +} + +void SGAgentServer::getOriginServiceList(ProtocolResponse &_return, + const ProtocolRequest &req) { + boost::shared_ptr service_channel = + boost::make_shared(); + service_channel->SetAllChannel(false); + service_channel->SetBankboneChannel(false); + service_channel->SetOriginChannel(true); + service_channel->SetSwimlaneChannel(false); + + DiscoveryService::GetInstance()->DiscGetSrvList(_return.servicelist, + req, service_channel); + + NS_LOG_INFO("getOriginServiceList size = " + << _return.servicelist.size() + << ", remoteAppkey = " << req.remoteAppkey + << ", protocol = " << req.protocol + << ", errorCode = " << _return.errcode); + +} + +int32_t SGAgentServer::registService(const SGService &oService) { + NS_LOG_INFO("the registry appkey = "< +#include "comm/tinyxml2.h" +#include "ServiceAgent.h" +#include "naming_service_types.h" +#include "log4cplus.h" + + +#define HANDLERNAME "sg_agent" + +using namespace __gnu_cxx; +namespace meituan_mns { +const size_t NMATCH = 10; + +class SGAgentServer : virtual public ServiceAgentIf { + public: + SGAgentServer(); + + int Init(); + + /** + * 按协议类型获取服务列表 + * @param _return,req + * + * @return void + * + * */ + void getServiceListByProtocol(ProtocolResponse &_return, const ProtocolRequest &req); + /** + * 按权重获取服务列表 + * @param _return,req + * + * @return void + * + * */ + void getOriginServiceList(ProtocolResponse &_return, const ProtocolRequest &req); + /** + * 服务注册 + * @param oService + * + * @return int32_t + * + * */ + int32_t registService(const SGService &oService); + + int32_t registServicewithCmd(const int32_t uptCmd, const SGService &oService); + /** + * 服务下线 + * @param oService + * + * @return int32_t + * + * */ + int32_t unRegistService(const SGService &oService); + + +}; + +} // namespace meituan_mns + +#endif diff --git a/sg_agent/src/mns/config_loader.cc b/sg_agent/src/mns/config_loader.cc new file mode 100644 index 0000000..7e7226c --- /dev/null +++ b/sg_agent/src/mns/config_loader.cc @@ -0,0 +1,745 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include "config_loader.h" +#include "base_consts.h" +#include "inc_comm.h" +#include "route_info.h" +#include "registry_strategy.h" + +namespace meituan_mns { + +boost::unordered_map CXmlFile::global_int_params_; +boost::unordered_map CXmlFile::global_str_params_; +boost::unordered_map CXmlFile::sg_agent_fun_; +boost::shared_ptr > > CXmlFile::register_whitelist_idcs_; +boost::shared_ptr > > CXmlFile::idcs_; +boost::unordered_map CXmlFile::white_lists_; +AppEnvPtr CXmlFile::env_; + +muduo::MutexLock CXmlFile::update_idc_lock_; + +CXmlFile::CXmlFile():idc_md5_("") { +} +std::string CXmlFile::FetchElemValByTinyXML(const tinyxml2::XMLElement *p_xml_elem, + const std::string &str_key) { + const tinyxml2::XMLElement *p_xml_elem_key = + p_xml_elem->FirstChildElement(str_key.c_str()); + if (NULL == p_xml_elem_key) { + NS_LOG_ERROR(str_key << " not find."); + return ""; + } + NS_LOG_DEBUG("Fetch " << str_key << " value: " << p_xml_elem_key->GetText()); + + return std::string(p_xml_elem_key->GetText()); +} + +int32_t CXmlFile::CXmlFileInit() { + register_whitelist_idcs_ = + boost::make_shared > >(); + idcs_ = boost::make_shared > >(); + env_ = boost::make_shared(); + + int32_t ret = InitAppenv(); + if (SUCCESS != ret) { + NS_LOG_ERROR("failed to load appenv, ret = " << ret); + return ret; + } + ret = InitAddrInfo(); + if (SUCCESS != ret) { + NS_LOG_ERROR("failed to get local ip."); + return ret; + } + ret = LoadIdcFile(idcs_); + if (SUCCESS != ret) { + NS_LOG_ERROR("failed to load idc."); + return ret; + } + ret = LoadMutableFile(); + if (SUCCESS != ret) { + NS_LOG_ERROR("failed to load mutable."); + return ret; + } + ret = LoadWhiteFile(); + if (SUCCESS != ret) { + NS_LOG_ERROR("failed to load whitelist."); + return ret; + } + return ret; +} + + +int32_t CXmlFile::InitAppenv() { + + std::ifstream appenv_fin; + std::string str_agent_env_ = ""; + std::string str_agent_deployenv_ = ""; + + try { + appenv_fin.open(APPENV_FILE.c_str(), std::ios::in); + if (!appenv_fin.is_open()) { + NS_LOG_ERROR("failed to init appenv, there is not" + << APPENV_FILE); + return ERR_INVALID_ENV; + } + + std::string env_str; + while (std::getline(appenv_fin, env_str) && + (str_agent_env_.empty() || str_agent_deployenv_.empty())) { + std::size_t pos = env_str.find_first_of("="); + if (std::string::npos != pos) { + std::string key = env_str.substr(0, pos); + std::string value = env_str.substr(pos + 1); + boost::trim(key); + boost::trim(value); + if ("env" == key) { + str_agent_env_ = value; + NS_LOG_INFO("parsing env:" << str_agent_env_); + } else if ("deployenv" == key) { + str_agent_deployenv_ = value; + NS_LOG_INFO("parsing deployenv:" << str_agent_deployenv_); + } + } + env_str.clear(); + } + appenv_fin.close(); + + } catch (std::exception &e) { + appenv_fin.close(); + NS_LOG_ERROR("fail to load " << APPENV_FILE + << "OR fetch deployenv/appenv failed, reason: " + << e.what()); + return ERR_INVALID_ENV; + } + transform(str_agent_deployenv_.begin(), + str_agent_deployenv_.end(), + str_agent_deployenv_.begin(), ::tolower); + + transform(str_agent_env_.begin(), + str_agent_env_.end(), + str_agent_env_.begin(), ::tolower); + + NS_LOG_INFO("get env = " << str_agent_env_ + << ", deployenv = " << str_agent_deployenv_ + << " from " << meituan_mns::APPENV_FILE); + if(InitEnv(str_agent_env_,str_agent_deployenv_) < 0){ + NS_LOG_ERROR("the env info error, str_agent_env_: " + <SetIntEnv(local_env_int); + env_->SetEnvFlag(is_online); + env_->SetStrEnv(local_env_str); + env_->SetTypeEnv(g_appenv); + NS_LOG_INFO("Local env : \n\t\t\t int_env : " + << local_env_int + << "\n\t\t\t str_env : " << local_env_str + << "\n\t\t\t type_env : " << g_appenv + << "\n\t\t\t is_online : " << is_online); + return SUCCESS; +} + +int32_t CXmlFile::InitAddrInfo(void) { + char ip[INET_ADDRSTRLEN] = {0}; + char mask[INET_ADDRSTRLEN] = {0}; + + std::string local_ip = ""; + std::string local_mask = ""; + int iRet = getIntranet(ip, mask); // mask default = 255.255.0.0 + if (SUCCESS != iRet) { + NS_LOG_ERROR("failed to get IP, Mask by getIntranet, ret = " << iRet); + + // 使用host方式获取IP + iRet = getHost(local_ip); + if (SUCCESS != iRet) { + NS_LOG_ERROR("failed to get IP by getHost, ret = " << iRet); + return FAILURE; + } + NS_LOG_INFO("get local IP = " << local_ip); + } else { + local_ip = std::string(ip); + local_mask = std::string(mask); + NS_LOG_INFO("get local IP = " << local_ip + << ", Mask = " << mask); + } + global_str_params_.insert( + std::make_pair(CXmlFile::LocalIp, local_ip)); + global_str_params_.insert( + std::make_pair(CXmlFile::LocalMask, local_mask)); + return SUCCESS; +} + + +int32_t CXmlFile::LoadWhiteAppkeys(const tinyxml2::XMLElement *agent_xml_conf, + CXmlFile::Type type) { + std::string key = ""; + switch (type) { + case CXmlFile::AllEnvWhiteLists: { + key = "AllEnvWhiteLists"; + break; + } + case CXmlFile::NoWatcherWhiteLists : { + key = "NoWatcherWhiteLists"; + break; + } + case CXmlFile::RegisteUnlimitWhiteList : { + key = "RegisteUnlimitWhiteList"; + break; + } + case CXmlFile::MacRegisterUnlimitAppkeys : { + key = "MacRegisterUnlimitAppkeys"; + break; + } + default: { + NS_LOG_ERROR("known type = " << type); + return FAILURE; + } + } + + const tinyxml2::XMLElement *appkeys = agent_xml_conf->FirstChildElement(key.c_str()); + if (NULL == appkeys) { + NS_LOG_ERROR("Failed to load appkey, type = " << key); + return FAILURE; + } + const tinyxml2::XMLElement *appkey_item = appkeys->FirstChildElement("Item"); + UnorderedMapPtr map_ptr(new boost::unordered_set()); + NS_LOG_INFO(key << ":"); + while (NULL != appkey_item) { + std::string appkey_str(appkey_item->GetText()); + boost::trim(appkey_str); + if (!appkey_str.empty()) { + map_ptr->insert(appkey_str); + NS_LOG_INFO( "\t " << appkey_str); + } + appkey_item = appkey_item->NextSiblingElement("Item"); + } + white_lists_.insert(std::make_pair(type, map_ptr)); + return SUCCESS; +} + + +int32_t CXmlFile::LoadMutableFile() { + tinyxml2::XMLDocument agent_mutable; + const tinyxml2::XMLError agent_xml_ret = + agent_mutable.LoadFile(AGENT_MUTABLE_CONF.c_str()); + if (tinyxml2::XML_SUCCESS != agent_xml_ret) { + NS_LOG_ERROR("fail to load " << AGENT_MUTABLE_CONF << ", ret = " + << agent_xml_ret); + return FAILURE; + } + const tinyxml2::XMLElement *agent_xml_conf = + agent_mutable.FirstChildElement("SGAgentMutableConf"); + if (NULL == agent_xml_conf) { + NS_LOG_ERROR( + "can't find SGAgentMutableConf in " << AGENT_MUTABLE_CONF); + return FAILURE; + } + try { + std::string str_reg_threads + (FetchElemValByTinyXML(agent_xml_conf, "RegistryThreads")); + int32_t i32_registry_threads = atoi(str_reg_threads.c_str()); + global_int_params_.insert(std::make_pair(CXmlFile::RegistryThreads, + i32_registry_threads)); + NS_LOG_INFO("RegistryThreads : " << i32_registry_threads); + + std::string + str_client_num(FetchElemValByTinyXML(agent_xml_conf, "ClientNum")); + int32_t i32_client_num = atoi(str_client_num.c_str()); + global_int_params_.insert(std::make_pair(CXmlFile::ClientNum, + i32_client_num)); + NS_LOG_INFO("ClientNum : " << i32_client_num); + std::string str_client_threads + (FetchElemValByTinyXML(agent_xml_conf, "ClientThreads")); + int32_t i32_client_threads = atoi(str_client_threads.c_str()); + global_int_params_.insert(std::make_pair(CXmlFile::ClientThreads, + i32_client_threads)); + NS_LOG_INFO("ClientThreads : " << i32_client_threads); + + std::string str_watcher_pull_threads + (FetchElemValByTinyXML(agent_xml_conf, "WatcherPullThreads")); + int32_t i32_watcher_pull_threads = atoi(str_watcher_pull_threads.c_str()); + global_int_params_.insert(std::make_pair(CXmlFile::WatcherDispatchThreads, + i32_watcher_pull_threads)); + NS_LOG_INFO("WatcherPullThreads : " << i32_watcher_pull_threads); + + std::string str_watcher_dis_threads + (FetchElemValByTinyXML(agent_xml_conf, "WatcherDispatchThreads")); + int32_t + i32_watcher_dispatch_threads = atoi(str_watcher_dis_threads.c_str()); + global_int_params_.insert(std::make_pair(CXmlFile::WatcherDispatchThreads, + i32_watcher_dispatch_threads)); + NS_LOG_INFO("WatcherDispatchThreads : " << i32_watcher_dispatch_threads); + + std::string str_fast_get_threads + (FetchElemValByTinyXML(agent_xml_conf, "FastGetThreads")); + int32_t i32_fastget_threads = atoi(str_fast_get_threads.c_str()); + global_int_params_.insert(std::make_pair(CXmlFile::FastGetThreads, + i32_fastget_threads)); + NS_LOG_INFO("FastGetThreads : " << i32_fastget_threads); + + std::string + str_retrytimes(FetchElemValByTinyXML(agent_xml_conf, "RetryTimes")); + int32_t i32_retrytimes_ = atoi(str_retrytimes.c_str()); + global_int_params_.insert(std::make_pair(CXmlFile::RetryTimes, + i32_retrytimes_)); + NS_LOG_INFO("RetryTimes : " << i32_retrytimes_); + + std::string str_registry_action + (FetchElemValByTinyXML(agent_xml_conf, "RegistryCenter")); + int32_t i32_registry_action = atoi(str_registry_action.c_str()); + global_int_params_.insert(std::make_pair(CXmlFile::RegistryCenter, + i32_registry_action)); + NS_LOG_INFO("RegistryCenter : " << i32_registry_action); + + + std::string + str_mnsc_timeout(FetchElemValByTinyXML(agent_xml_conf, "MnscTimeOut")); + int32_t i32_mnsc_timeout_action = atoi(str_mnsc_timeout.c_str()); + global_int_params_.insert(std::make_pair(CXmlFile::MnscTimeOut, + i32_mnsc_timeout_action)); + NS_LOG_INFO("MnscTimeOut : " << i32_mnsc_timeout_action); + + std::string + str_registry_entry(FetchElemValByTinyXML(agent_xml_conf, + "RegistryEntry")); + int32_t i32_registry_entry = atoi(str_registry_entry.c_str()); + global_int_params_.insert(std::make_pair(CXmlFile::RegistryEntry, + i32_registry_entry)); + NS_LOG_INFO("RegistryEntry : " << i32_registry_entry); + + std::string + str_discovery_type(FetchElemValByTinyXML(agent_xml_conf, + "DiscoveryType")); + int32_t i32_discovery_entry = atoi(str_discovery_type.c_str()); + global_int_params_.insert(std::make_pair(CXmlFile::DiscoveryType, + i32_discovery_entry)); + NS_LOG_INFO("DiscoveryType : " << i32_discovery_entry); + + std::string + str_agent_port(FetchElemValByTinyXML(agent_xml_conf, + "AgentPort")); + int32_t i32_agent_port = atoi(str_agent_port.c_str()); + global_int_params_.insert(std::make_pair(CXmlFile::AgentPort, + i32_agent_port)); + NS_LOG_INFO("AgentPort : " << i32_agent_port); + + std::string + str_agent_appkey = FetchElemValByTinyXML(agent_xml_conf, "AgentAppKey"); + std::string str_agent_version = + FetchElemValByTinyXML(agent_xml_conf, "AgentVersion"); + std::string str_mnsccache_appkey = + FetchElemValByTinyXML(agent_xml_conf, "MNSCacheAppkey"); + std::string str_agent_log = + FetchElemValByTinyXML(agent_xml_conf, "AgentLog"); + + NS_LOG_INFO("AgentAppKey : " + << str_agent_appkey + << "\n\t\t\t AgentVersion : " << str_agent_version + << "\n\t\t\t MNSCacheAppkey : " << str_mnsccache_appkey); + global_str_params_.insert(std::make_pair(CXmlFile::AgentAppKey, + str_agent_appkey)); + global_str_params_.insert(std::make_pair(CXmlFile::AgentVersion, + str_agent_version)); + global_str_params_.insert(std::make_pair(CXmlFile::MNSCacheAppkey, + str_mnsccache_appkey)); + global_str_params_.insert(std::make_pair(CXmlFile::AgentLog, + str_agent_log)); + + LoadAgentFuncFlag(agent_xml_conf); + int32_t ret = LoadZkConfig(agent_xml_conf); + if (SUCCESS != ret) { + NS_LOG_ERROR("failed to load zk config."); + return ret; + } + + } catch (boost::exception &e) { + NS_LOG_ERROR("Failed to load mutable"); + return FAILURE; + } + return SUCCESS; +} + +int32_t CXmlFile::LoadWhiteFile() { + tinyxml2::XMLDocument agent_whitelist; + const tinyxml2::XMLError agent_xml_ret = + agent_whitelist.LoadFile(AGENT_WHITELIST_CONF.c_str()); + + if (tinyxml2::XML_SUCCESS != agent_xml_ret) { + NS_LOG_ERROR("fail to load " << AGENT_WHITELIST_CONF << ", ret = " + << agent_xml_ret); + return FAILURE; + } + const tinyxml2::XMLElement *agent_xml_conf = + agent_whitelist.FirstChildElement("SGAgentWhiteListConf"); + if (NULL == agent_xml_conf) { + NS_LOG_ERROR( + "can't find SGAgentMutableConf in " << AGENT_WHITELIST_CONF); + return FAILURE; + } + + int32_t ret = LoadWhiteAppkeys(agent_xml_conf, + CXmlFile::MacRegisterUnlimitAppkeys); + if (SUCCESS != ret) { + return ret; + } + ret = LoadWhiteAppkeys(agent_xml_conf, + CXmlFile::AllEnvWhiteLists); + if (SUCCESS != ret) { + return ret; + } + ret = LoadWhiteAppkeys(agent_xml_conf, + CXmlFile::RegisteUnlimitWhiteList); + if (SUCCESS != ret) { + return ret; + } + ret = LoadWhiteAppkeys(agent_xml_conf, + CXmlFile::NoWatcherWhiteLists); + if (SUCCESS != ret) { + return ret; + } + ret = LoadRegisterWhitelistIdc(agent_xml_conf); + if (SUCCESS != ret) { + return ret; + } + return ret; +} +const std::string CXmlFile::GetLogPath(){ + std::string default_path = "/octo/ns/sg_agent/log4cplus.conf"; + tinyxml2::XMLDocument agent_mutable; + const tinyxml2::XMLError agent_xml_ret = + agent_mutable.LoadFile(AGENT_MUTABLE_CONF.c_str()); + if (tinyxml2::XML_SUCCESS != agent_xml_ret) { + std::cout<<"fail to load " << AGENT_MUTABLE_CONF << std::endl; + return default_path; + } + const tinyxml2::XMLElement *agent_xml_conf = + agent_mutable.FirstChildElement("SGAgentMutableConf"); + if (NULL == agent_xml_conf) { + std::cout<< "can't find SGAgentMutableConf" << std::endl; + return default_path; + } + std::string + str_log_path = FetchElemValByTinyXML(agent_xml_conf, "AgentLogPath"); + + return str_log_path; +} + +int32_t CXmlFile::LoadAgentFuncFlag(const tinyxml2::XMLElement *agent_xml_conf) { + std::string res = FetchElemValByTinyXML(agent_xml_conf, "OpenMNSCache"); + sg_agent_fun_.insert(std::make_pair(CXmlFile::OpenMNSCache, + 0 != res.compare("open") ? false : true)); + NS_LOG_INFO("OpenMNSCache : " << res); + res = FetchElemValByTinyXML(agent_xml_conf, "OpenAutoRoute"); + sg_agent_fun_.insert(std::make_pair(CXmlFile::OpenAutoRoute, + 0 != res.compare("open") ? false : true)); + NS_LOG_INFO("OpenAutoRoute : " << res); + + return SUCCESS; +} + + +int32_t CXmlFile::LoadRegisterWhitelistIdc(const tinyxml2::XMLElement *sg_agent_idc) { + const tinyxml2::XMLElement *idcs = + sg_agent_idc->FirstChildElement("MacRegisterUnlimitAppkeysIDC"); + if (NULL == idcs) { + NS_LOG_ERROR("can not find the xml element HotelTravelRegisterIDC."); + return FAILURE; + } + NS_LOG_INFO("MacRegisterUnlimitAppkeysIDC : "); + const tinyxml2::XMLElement *idc_item = idcs->FirstChildElement("Item"); + NS_LOG_INFO("IDC : "); + while (NULL != idc_item) { + const tinyxml2::XMLElement *ip_ptr = idc_item->FirstChildElement("IP"); + const tinyxml2::XMLElement *mask_ptr = idc_item->FirstChildElement("MASK"); + if (NULL != ip_ptr && NULL != mask_ptr) { + std::string ip_str(ip_ptr->GetText()); + std::string mask_str(mask_ptr->GetText()); + boost::trim(ip_str); + boost::trim(mask_str); + if ((!ip_str.empty()) && (!mask_str.empty())) { + boost::shared_ptr idc(new IDC()); + idc->SetIp(ip_str); + idc->SetMask(mask_str); + idc->CalculateIpMask(); + NS_LOG_INFO("\t IP = " << ip_str << ", MASK = " << mask_str); + register_whitelist_idcs_->push_back(idc); + } else { + NS_LOG_WARN("IP or MASK is empty"); + } + } else { + NS_LOG_WARN("IP or MASK miss."); + } + idc_item = idc_item->NextSiblingElement("Item"); + } + return false; +} + + +int32_t CXmlFile::LoadIdcFile(IdcsPtr &idcs) { + NS_LOG_INFO("loading " << kStrIDCFileFullPath); + tinyxml2::XMLDocument conf_regions; + tinyxml2::XMLError eResult = + conf_regions.LoadFile(kStrIDCFileFullPath.c_str()); + + if (tinyxml2::XML_SUCCESS != eResult) { + NS_LOG_ERROR("failed to load config: " << kStrIDCFileFullPath + << ", errorCode = " << eResult); + return FAILURE; + } + tinyxml2::XMLElement *xmlRegion = + conf_regions.FirstChildElement("SGAgent")->FirstChildElement("Region"); + + while (NULL != xmlRegion) { + tinyxml2::XMLElement *xmlRegionName = + xmlRegion->FirstChildElement("RegionName"); + + tinyxml2::XMLElement *xmlIDC = xmlRegion->FirstChildElement("IDC"); + while (NULL != xmlIDC) { + tinyxml2::XMLElement *xmlItem = xmlIDC->FirstChildElement("Item"); + tinyxml2::XMLElement *idc_ptr = xmlIDC->FirstChildElement("IDCName"); + tinyxml2::XMLElement *center_ptr = xmlIDC->FirstChildElement("CenterName"); + while (NULL != xmlItem) { + boost::shared_ptr idc(new IDC()); + std::string ip_str = FetchElemValByTinyXML(xmlItem, "IP"); + std::string mask_str = FetchElemValByTinyXML(xmlItem, "MASK"); + if ((!ip_str.empty()) && (!mask_str.empty())) { + std::string region_name = + NULL != xmlRegionName ? xmlRegionName->GetText() : "unknown" ; + std::string center_name = + NULL != center_ptr ? center_ptr->GetText() : "unknown"; + std::string idc_name = + NULL != idc_ptr ? idc_ptr->GetText() : "unknown"; + boost::shared_ptr idc(new IDC()); + idc->SetRegion(region_name); + idc->SetIp(ip_str); + idc->SetMask(mask_str); + idc->SetIdc(idc_name); + idc->SetCenter(center_name); + idc->CalculateIpMask(); + NS_LOG_INFO("region = " << region_name + << " idc = " << idc_name + << " center = " << center_name + << " ip = " << ip_str + << " mask = " << mask_str); + idcs->push_back(idc); + } else { + NS_LOG_WARN("IP or MASK is empty"); + } + xmlItem = xmlItem->NextSiblingElement("Item"); + } + xmlIDC = xmlIDC->NextSiblingElement("IDC"); + } + xmlRegion = xmlRegion->NextSiblingElement("Region"); + } + return SUCCESS; + +} + +int32_t CXmlFile::LoadZkConfig(const tinyxml2::XMLElement *sg_agent_conf) { + boost::shared_ptr local_ip_idc = IdcUtil::GetIdc(env_->GetStrEnv()); + std::string region_name = NULL != local_ip_idc.get() ? + local_ip_idc->GetRegion() : "beijing"; + if ("unknown" == region_name || region_name.empty()) { + region_name = "beijing"; + } + NS_LOG_INFO("identify the region name is " << region_name); + + std::string str_zk_client_nums + (FetchElemValByTinyXML(sg_agent_conf, "ZkClientNum")); + int32_t i32_zk_client_nums_ = atoi(str_zk_client_nums.c_str()); + global_int_params_.insert(std::make_pair(CXmlFile::ZkClientNum, + i32_zk_client_nums_)); + + std::string + str_zk_timeout(FetchElemValByTinyXML(sg_agent_conf, "ZkTimeout")); + int32_t i32_zk_timeout_ = atoi(str_zk_timeout.c_str()); + global_int_params_.insert(std::make_pair(CXmlFile::ZkTimeout, + i32_zk_timeout_)); + + + //初始化ZkClient进行连接管理 + const tinyxml2::XMLElement *xml_mns_host = sg_agent_conf->FirstChildElement("MnsHost"); + if (NULL == xml_mns_host) { + NS_LOG_ERROR("miss mns host in config mutable xml"); + return ERR_CONFIG_PARAM_MISS; + } + const tinyxml2::XMLElement *is_online_element = + xml_mns_host->FirstChildElement(env_->GetEnvFlag() ? "online" : "offline"); + if (NULL == is_online_element) { + NS_LOG_ERROR("miss online or offline element in sg_agent_mutable.xml"); + return ERR_CONFIG_PARAM_MISS; + } + + std::string zk_lists = FetchElemValByTinyXML(is_online_element, region_name); + if (zk_lists.empty()) { + NS_LOG_ERROR("zk list is empty."); + return FAILURE; + } + std::string idc_zk_lists = IdcUtil::GetSameIdcZk(zk_lists, env_->GetStrEnv()); + boost::trim(idc_zk_lists); + NS_LOG_INFO("zk list is " << idc_zk_lists); + global_str_params_.insert(std::make_pair(CXmlFile::ZkLists, idc_zk_lists)); + return SUCCESS; +} + +bool CXmlFile::GetAgentFunFlag(const CXmlFile::Type type) { + if (sg_agent_fun_.end() == sg_agent_fun_.find(type)) { + NS_LOG_ERROR("cannot find type " << type); + return false; + } + return sg_agent_fun_.at(type); +} + +UnorderedMapPtr CXmlFile::GetWhiteAppkeys(const CXmlFile::Type type) { + if (white_lists_.end() == white_lists_.find(type)) { + NS_LOG_ERROR("cannot find type " << type); + return boost::make_shared >(); + } + return white_lists_.at(type); +} + +const std::string CXmlFile::GetStrPara(const CXmlFile::Type type) { + if (global_str_params_.end() == global_str_params_.find(type)) { + NS_LOG_ERROR("cannot find type " << type); + return ""; + } + return global_str_params_.at(type); +} + +int32_t CXmlFile::GetI32Para(const CXmlFile::Type type) { + if (global_int_params_.end() == global_int_params_.find(type)) { + NS_LOG_ERROR("cannot find type " << type); + return 0; + } + return global_int_params_.at(type); +} + +void CXmlFile::UpdateIdcs() { + IdcsPtr new_idcs = boost::make_shared > >(); + int32_t ret = LoadIdcFile(new_idcs); + if (ret != SUCCESS) { + NS_LOG_ERROR("failed to update idc."); + return; + } + muduo::MutexLockGuard lock(update_idc_lock_); + idcs_ = new_idcs; +} +void CXmlFile::UpdateIdcsTimer() { + std::string idc_md5_tmp = CalculateMd5(IDC_FILE_NAME, AGENT_CONF_PATH); + if (idc_md5_tmp.empty() || + 0 == idc_md5_tmp.compare(idc_md5_)) { + return ; + } + IdcsPtr new_idcs = boost::make_shared > >(); + int32_t ret = LoadIdcFile(new_idcs); + if (ret != SUCCESS) { + NS_LOG_ERROR("failed to update idc."); + return; + } + idc_md5_ = idc_md5_tmp; + muduo::MutexLockGuard lock(update_idc_lock_); + idcs_ = new_idcs; +} + +IdcsPtr CXmlFile::GetIdc(void) { + muduo::MutexLockGuard lock(update_idc_lock_); + return idcs_; +} + +} // namespace meituan_mns diff --git a/sg_agent/src/mns/config_loader.h b/sg_agent/src/mns/config_loader.h new file mode 100644 index 0000000..d7107a7 --- /dev/null +++ b/sg_agent/src/mns/config_loader.h @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_CONFIG_LOADER_H +#define OCTO_OPEN_SOURCE_CONFIG_LOADER_H +#include "tinyxml2.h" +#include "route_base.h" +#include +#include +#include +#include +#include +#include +namespace meituan_mns { + +typedef enum { + PROD, STAGING, DEV, PPE, TEST +} Appenv; + + +typedef boost::shared_ptr > UnorderedMapPtr; +typedef boost::shared_ptr > + MccClusterAppkeyPtr; + +class AppEnv { + public: + + int32_t GetIntEnv(void) { return int_env; } + std::string GetStrEnv(void) { return str_env; } + Appenv GetTypeEnv(void) { return type_env; } + bool GetEnvFlag(void) { return is_online; } + + void SetIntEnv(const int32_t env) { int_env = env;} + void SetStrEnv(const std::string &env) { str_env = env;} + void SetTypeEnv(Appenv &env) { type_env = env;} + void SetEnvFlag(const bool flag) {is_online = flag;} + + private: + int32_t int_env; + std::string str_env; + Appenv type_env; + bool is_online; +}; + +typedef boost::shared_ptr AppEnvPtr; +typedef boost::shared_ptr > > IdcsPtr; +class CXmlFile { + + public: + + enum Type { + AgentAppKey = 0, + AgentVersion, + AgentPort, + DefaultMnsPath, + RegistryThreads, + ClientNum, + ClientThreads, + WatcherPullThreads, + WatcherDispatchThreads, + FastGetThreads, + ZkTimeout, + ZkClientNum, + RetryTimes, + RegistryCenter, + CacheDiscSwitch, + ZkLists, + MNSCacheAppkey, + MnscTimeOut, + RegistryEntry, + DiscoveryType, + LocalIp, + LocalMask, + AllEnvWhiteLists, + NoWatcherWhiteLists, + RegisteUnlimitWhiteList, + MacRegisterUnlimitAppkeys, + OpenMNSCache, + OpenAutoRoute, + AgentLog, + AgentLogPath + }; + + + + CXmlFile(); + ~CXmlFile() {} + + /** + * 初始化组件依赖的配置项 + * @param void + * + * @return int32_t + * + * */ + int32_t CXmlFileInit(); + + /** + * 根据配置索引获取Int型配置参数 + * @param index + * + * @return int + * + * */ + static int32_t GetI32Para(const CXmlFile::Type type); + + /** + * 获取字符串类型配置 + * @param void + * + * @return string + * + * */ + static const std::string GetStrPara(const CXmlFile::Type type); + /** + * 获取日志路径 + * @param void + * + * @return string + * + * */ + const std::string GetLogPath(); + /** + * + * @param p_xml_elem + * @param str_key + * @return + */ + std::string FetchElemValByTinyXML(const tinyxml2::XMLElement *p_xml_elem, + const std::string &str_key); + + /** 获取降级开关标示 */ + static bool GetAgentFunFlag(const CXmlFile::Type type); + /** 获取对应appkeys列表 */ + static UnorderedMapPtr GetWhiteAppkeys(const CXmlFile::Type type); + /** 获取当前机器环境 */ + static AppEnvPtr GetAppenv(void) { return env_;} + /** 获取mac注册限制的网段*/ + static IdcsPtr GetRegisterIdc(void) { return register_whitelist_idcs_; } + /** 获取idc文件内容 */ + static IdcsPtr GetIdc(void); + + void UpdateIdcsTimer(void); + + void UpdateIdcs(); + + private: + + /** + * 初始化机器环境 + * @return + */ + int32_t InitAppenv(void); + int32_t InitAddrInfo(void); + /** + * + * @param env_str + * @param deployenv_str + * @return + */ + int32_t InitEnv(const std::string &env_str, const std::string &deployenv_str); + /** 加载mutable文件 */ + int32_t LoadMutableFile(void); + /** 加载white白名单文件 */ + int32_t LoadWhiteFile(void); + + /** + * + * @param agent_xml_conf + * @param type + * @return + */ + int32_t LoadWhiteAppkeys(const tinyxml2::XMLElement *agent_xml_conf, + CXmlFile::Type type); + /** + * + * @param agent_xml_conf + * @return + */ + int32_t LoadAgentFuncFlag(const tinyxml2::XMLElement *agent_xml_conf); + + /** + * + * @param sg_agent_idc + * @return + */ + int32_t LoadRegisterWhitelistIdc(const tinyxml2::XMLElement *sg_agent_idc); + /** + * + * @return + */ + int32_t LoadIdcFile(IdcsPtr &idcs); + /** + * + * @param sg_agent_conf + * @return + */ + int32_t LoadZkConfig(const tinyxml2::XMLElement *sg_agent_conf); + + private: + CXmlFile(const CXmlFile &); + CXmlFile &operator=(const CXmlFile &); + + + + static boost::unordered_map global_int_params_; + static boost::unordered_map global_str_params_; + static boost::unordered_map white_lists_; + static boost::unordered_map sg_agent_fun_; + + static IdcsPtr register_whitelist_idcs_; + static IdcsPtr idcs_; + + static AppEnvPtr env_; + + static muduo::MutexLock update_idc_lock_; + + std::string idc_md5_; + + protected: +}; +} // namespace meituan_mns + +#endif // OCTO_OPEN_SOURCE_CONFIG_LOADER_H diff --git a/sg_agent/src/mns/discovery_model.h b/sg_agent/src/mns/discovery_model.h new file mode 100644 index 0000000..d2374c5 --- /dev/null +++ b/sg_agent/src/mns/discovery_model.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_DISCOVERY_MODEL_H +#define OCTO_OPEN_SOURCE_DISCOVERY_MODEL_H +/** + *服务发现: 1.直接从注册中心(如zk) ;2.直接走缓存服务; + * 3.混合模式:从缓存服务获取&&注册中心 + *@param + *@return + * + **/ +#include +#include +#include "discovery_model.h" +#include "config_loader.h" + +namespace meituan_mns{ + +class DiscoveryModel { + public: + DiscoveryModel() {}; + ~DiscoveryModel() {}; + /** + * 进行服务发现的模式类型,zk,cached(mnsc),mixer(cached firstly zk serconde) + * @param void + * + * @return int + * + */ + static int32_t GetDiscoveryModelType(){return CXmlFile::GetI32Para + (CXmlFile::DiscoveryType);}; + + private: + int32_t is_disc_zookeeper; + int32_t is_disc_cached; + int32_t is_disc_mixer; + int32_t is_disc_extend; +}; + +} // namespace meituan_mns + + + + + +#endif //OCTO_OPEN_SOURCE_DISCOVERY_MODEL_H diff --git a/sg_agent/src/mns/discovery_service.cc b/sg_agent/src/mns/discovery_service.cc new file mode 100644 index 0000000..2822494 --- /dev/null +++ b/sg_agent/src/mns/discovery_service.cc @@ -0,0 +1,914 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "discovery_service.h" +#include "discovery_model.h" +#include "sds_tools.h" +#include "service_channels.h" +#include "route_rule.h" +#include "mnsc_client.h" +#include "registry_strategy.h" + +namespace meituan_mns { + +BufferMgr *DiscoveryService::route_cache_ = NULL; +BufferMgr *DiscoveryService::origin_srvlist_cache_ = NULL; +BufferMgr > *DiscoveryService::filted_srvlist_cache_ = NULL; +BufferMgr *DiscoveryService::srvname_cache_ = NULL; +muduo::MutexLock DiscoveryService::disc_service_lock_; +DiscoveryService *DiscoveryService::disc_service_; +const int kMaxInterval = 20*1000; + + +int32_t DiscoveryService::Init() { + route_cache_ = new BufferMgr(); + if (NULL == route_cache_) { + NS_LOG_ERROR("failed to malloc route_cache_."); + return -1; + } + origin_srvlist_cache_ = new BufferMgr(); + if (NULL == origin_srvlist_cache_) { + NS_LOG_ERROR("failed to malloc origin_srvlist_cache_."); + return -1; + } + filted_srvlist_cache_ = new BufferMgr >(); + if (NULL == filted_srvlist_cache_) { + NS_LOG_ERROR("failed to malloc m_filte_srvlist_cache."); + return -1; + } + srvname_cache_ = new BufferMgr(); + if (NULL == srvname_cache_) { + NS_LOG_ERROR("failed to malloc srvname_cache_."); + return -1; + } + //init discoveryserver thread + DiscoveryZkClient::GetInstance()->Init(); + return 0; +} + +DiscoveryService* DiscoveryService::GetInstance() { + if (NULL == disc_service_) { + muduo::MutexLockGuard lock(disc_service_lock_); + if (NULL == disc_service_) { + disc_service_ = new DiscoveryService(); + } + } + return disc_service_; +} + +void DiscoveryService::StartThread() { + mns_timer_loop_ = mns_timer_thread_.startLoop(); + mns_timer_loop_->runEvery(DEFAULT_PROTOCOL_SCANTIME, + boost::bind(&DiscoveryService::UpdateSrvListTimer, this)); + mns_timer_loop_->runEvery(DEFAULT_PROTOCOL_MAX_UPDATETIME, + boost::bind(&DiscoveryService::UpdateRouteTimer, this)); + mns_timer_loop_->runEvery(DEFAULT_PROTOCOL_SCANTIME, + boost::bind(&DiscoveryService::UpdateSrvNameTimer, this)); + +} + +int32_t DiscoveryService::DiscSrvlistFromCache(std::vector &srv_list, + const ProtocolRequest &req, + boost::shared_ptr &channels) { + return SUCCESS; +} +int32_t DiscoveryService::DiscSrvlistFromMixer(std::vector &srv_list, + const ProtocolRequest &req, + boost::shared_ptr &channels) { + return SUCCESS; +} +void DiscoveryService::UpdateSrvListTimer() { + if (NULL == origin_srvlist_cache_) { + NS_LOG_ERROR("ProtocolServicePlugin's ServiceBufferMgr is NULL, please init it before"); + return; + } + int static update_count = 0; + const int static CountTimes = 60; + update_count = (++update_count) % CountTimes; + NS_LOG_DEBUG("hlb update_count = " << update_count); + + bool null_node_update = (0 == update_count); + + + std::vector keys; + int ret = origin_srvlist_cache_->GetKeyList(keys); + if (0 >= ret) { + NS_LOG_ERROR("keys is empty."); + return ; + } + ServicePtr svc_ptr(new getservice_res_param_t()); + ProtocolRequest req; + std::vector servicelist; + for (std::vector::iterator iter = keys.begin(); + keys.end() != iter; ++iter) { + ret = origin_srvlist_cache_->get(*iter, *svc_ptr); + if (SUCCESS == ret) { + if (svc_ptr->serviceList.empty() && !null_node_update) { + continue; + } + req.__set_remoteAppkey(svc_ptr->remoteAppkey); + req.__set_protocol(svc_ptr->protocol); + req.__set_localAppkey(svc_ptr->localAppkey); + DiscNodesFromZk(servicelist, req); + } + } +} + +void DiscoveryService::UpdateRouteTimer() { + if (NULL == route_cache_) { + NS_LOG_ERROR("ProtocolServicePlugin's ServiceNameBufferMgr is NULL, please init it before"); + return; + } + + std::vector keys; + int ret = route_cache_->GetKeyList(keys); + if (0 >= ret) { + NS_LOG_ERROR("keys is empty."); + return ; + } + RouteService route_service; + for (std::vector::iterator iter = keys.begin(); + keys.end() != iter; ++iter) { + ret = route_cache_->get(*iter, route_service); + if (SUCCESS == ret) { + RoutePtr routePtr = + boost::make_shared(route_service.route_list); + DiscRouteFromZk(routePtr); + } + } +} + +void DiscoveryService::UpdateSrvNameTimer(void) { + if (NULL == srvname_cache_) { + NS_LOG_ERROR("ProtocolServicePlugin's ServiceNameBufferMgr is NULL, please init it before"); + return; + } + + std::vector keys; + int ret = srvname_cache_->GetKeyList(keys); + if (0 >= ret) { + NS_LOG_ERROR("keys is empty."); + return ; + } + std::vector::iterator iter; + ServiceNamePtr servicenamePtr(new getservicename_res_param_t()); + for (iter = keys.begin(); iter != keys.end(); ++iter) { + ret = srvname_cache_->get(*iter, *servicenamePtr); + if (SUCCESS == ret) { + ret = DiscSrvNameFromZk(servicenamePtr); + if (SUCCESS != ret) { + NS_LOG_ERROR("failed to sendServiceMsg, serviceName = " + << servicenamePtr->servicename + << "; version = " << servicenamePtr->version + << "; protocol = " << servicenamePtr->protocol + << "; errorcode = " << ret); + } + } else { + NS_LOG_ERROR("get ServiceNameBufferMgr fail! key = " << *iter + << ", ret = " << ret); + } + } +} + +int32_t DiscoveryService::DiscGetSrvList(std::vector &srvlist, + const ProtocolRequest &req, + boost::shared_ptr &channels) { + + switch (DiscoveryModel::GetDiscoveryModelType()) { + case kDiscZookeeper: { + return DiscSrvlistFromZk(srvlist, req,channels); + } + case kDiscCached: { + return DiscSrvlistFromCache(srvlist, req,channels); + } + case kDiscMixer: { + return DiscSrvlistFromMixer(srvlist, req,channels); + } + default: { + NS_LOG_ERROR("unsupported discovery method: " + << DiscoveryModel::GetDiscoveryModelType()); + return 0; + } + } +} +int32_t DiscoveryService::AdjustInOrigin(std::vector &srv_list, + const std::string &key, + const ProtocolRequest &req) { + + int ret = FAILURE; + boost::shared_ptr + service_param(new getservice_res_param_t); + ret = origin_srvlist_cache_->get(key, *service_param); + + if (SUCCESS == ret) { + srv_list = service_param->serviceList; + RouteService routes; + NS_LOG_INFO("success disc from local cache,size = "<< srv_list.size()); + + if (SUCCESS == route_cache_->get(key, routes)) { + std::vector exclusive_routes; + RouteRule::GetExclusiveRoute(routes.route_list.routeList, exclusive_routes, false); + std::string local_ip = "\"" + CXmlFile::GetStrPara(CXmlFile::LocalIp) + "\""; + + if (!RouteRule::IsMatchRoutesConsumer(exclusive_routes, local_ip)) { + RouteRule::FilterProvidersByExclusiveRoutes(srv_list, exclusive_routes); + } + }else{ + NS_LOG_WARN("Cannot find data from route cache."); + } + NS_LOG_INFO("success disc from local cache,size = "< &srv_list, + const ProtocolRequest &req, + boost::shared_ptr &channels){ + int32_t ret = FAILURE; + std::string key = DiscTools::LocalCacheKey(req.remoteAppkey, req.protocol); + if(channels->GetOriginChannel()){ + ret = AdjustInOrigin(srv_list,key,req); + NS_LOG_INFO("get origin channel service list,size = " + <remoteAppkey, service + ->protocol); + ServicePtr tmpServicePtr = boost::make_shared(); + std::string version = service->version; + boost::trim(version); + if (version.empty()) {//默认为0 + tmpServicePtr->__set_version("0"); + } else { + tmpServicePtr->__set_version(version); + } + int ret = origin_srvlist_cache_->get(key, *tmpServicePtr); + NS_LOG_INFO("remoteAppkey : " << service->remoteAppkey + << ", protocol = " << service->protocol + << ", tmpServicePtr size =" + << tmpServicePtr->serviceList.size()); + if (SUCCESS == ret) { + bool flag = false; + for (std::vector::iterator piter = service->serviceList.begin(); + piter != service->serviceList.end(); ++piter) { + flag = false; + for (std::vector::iterator iter = tmpServicePtr->serviceList.begin(); + iter != tmpServicePtr->serviceList.end(); ++iter) { + if ((iter->ip == piter->ip) && (iter->port == piter->port)) { + if (piter->status >= fb_status::DEAD && piter->status <= fb_status::WARNING) { + iter->__set_status(piter->status); + } else { + NS_LOG_ERROR("status is not in conformity with the specification ,ip : " << piter->ip + << " , port : " << piter->port); + flag = true; + break; + } + if (("thrift" == piter->protocol && 0 == piter->serverType) || + ("http" == piter->protocol && 1 == piter->serverType)) { + iter->__set_protocol(piter->protocol); + iter->__set_serviceInfo(piter->serviceInfo); + } else { + NS_LOG_ERROR("thrift and serverType do not match, protocol: " << piter->protocol + << " ,serverType: " << piter->serverType); + flag = true; + break; + } + if (piter->envir >= 1 && piter->envir <= 3) { + iter->__set_envir(piter->envir); + } else { + NS_LOG_ERROR("envir is not in conformity with the specification, envir : " << piter->envir); + flag = true; + break; + } + if (piter->fweight > 0.0 && piter->fweight <= 100.0) { + iter->__set_weight(piter->fweight); + iter->__set_fweight(piter->fweight); + } else if (piter->weight > 0 && piter->weight <= 100) { + iter->__set_weight(piter->weight); + iter->__set_fweight(piter->weight); + } else { + iter->__set_weight(10); + iter->__set_fweight(10.0); + } + if (piter->role > 0) { + iter->__set_role(piter->role); + } + if (piter->lastUpdateTime > 0) { + iter->__set_lastUpdateTime(piter->lastUpdateTime); + } + iter->__set_version(piter->version); + iter->__set_serviceInfo(piter->serviceInfo); + iter->__set_heartbeatSupport(piter->heartbeatSupport); + flag = true; + break; + } + } + if (!flag) { + NS_LOG_INFO("ip or port is new, need add srvlist to origin_srvlist_cache_"); + tmpServicePtr->serviceList.push_back(*piter); + } + } + origin_srvlist_cache_->insert(key, *tmpServicePtr); + } else { + NS_LOG_INFO("not found,insert the flush node"); + for (std::vector::iterator iter = service->serviceList.begin(); + service->serviceList.end() != iter; ++iter) { + tmpServicePtr->serviceList.push_back(*iter); + } + origin_srvlist_cache_->insert(key, *tmpServicePtr); + } + ret = AdjustListInRouteRule(service->localAppkey, + service->remoteAppkey, + service->protocol, true); + if (SUCCESS != ret) { + NS_LOG_ERROR("Failed to filte service list. localAppkey :" << service->localAppkey + << ", remoteAppkey :" << service->remoteAppkey + << ", protocol :" << service->protocol + << ", ret :" << ret); + } + return ret; +} +int32_t DiscoveryService::GetSrvListAndCacheSize(ServListAndCache &list_and_cache, + const std::string &protocol, + const std::string &appkey) { + if (NULL == origin_srvlist_cache_ || NULL == filted_srvlist_cache_) { + NS_LOG_ERROR("origin_srvlist_cache_ or filted_srvlist_cache_ is NULL, please init it before"); + return ERR_SERVICE_BUFFER_NULL; + } + std::string key = DiscTools::LocalCacheKey(appkey, protocol); + ServicePtr tmpServicePtr = boost::make_shared(); + int ret = origin_srvlist_cache_->get(key, *tmpServicePtr); + if (SUCCESS == ret) { + list_and_cache.origin_servlist_size = tmpServicePtr->serviceList.size(); + list_and_cache.origin_servicelist = tmpServicePtr->serviceList; + } else { + NS_LOG_WARN("cannot find key in origin_srvlist_cache_, ret = " << ret); + list_and_cache.origin_servlist_size = 0; + list_and_cache.origin_servicelist = std::vector(); + } + std::vector filte_servlist; + ret = filted_srvlist_cache_->get(key, filte_servlist); + if (SUCCESS == ret) { + list_and_cache.filte_servlist_size = filte_servlist.size(); + list_and_cache.filte_servicelist = filte_servlist; + } else { + NS_LOG_WARN("cannot find key in m_filte_srvlist_cache, ret = " << ret); + list_and_cache.filte_cache_size = 0; + list_and_cache.filte_servicelist = std::vector(); + } + list_and_cache.origin_cache_size = origin_srvlist_cache_->size(); + list_and_cache.filte_cache_size = filted_srvlist_cache_->size(); + + return SUCCESS; +} +int32_t DiscoveryService::RepalceSrvlist(const + boost::shared_ptr &service){ + if (NULL == origin_srvlist_cache_) { + NS_LOG_ERROR("m_origin_srvlist_cache is NULL, please init."); + return ERR_SERVICE_BUFFER_NULL; + } + if (NULL == filted_srvlist_cache_) { + NS_LOG_ERROR("m_filted_srvlist_cache is NULL, please init."); + return ERR_SERVICE_BUFFER_NULL; + } + std::string key = DiscTools::LocalCacheKey(service->remoteAppkey, service->protocol); + NS_LOG_INFO("remoteAppkey : " << service->remoteAppkey + << "protocol : " << service->protocol + << "service size is " << service->serviceList.size()); + ServicePtr tmp_service = make_shared(); + if (!service->localAppkey.empty()) { + tmp_service->__set_localAppkey(service->localAppkey); + } + tmp_service->__set_remoteAppkey((service->remoteAppkey)); + tmp_service->__set_protocol(service->protocol); + std::string version = service->version; + boost::trim(version); + if (version.empty()) {//版本号没有填写,默认为0 + tmp_service->__set_version("0"); + } else { + tmp_service->__set_version(version); + } + int ret = FAILURE; + for (std::vector::const_iterator iter = service->serviceList.begin(); + service->serviceList.end() != iter; ++iter) { + SGService iservice; + ret = CheckServiceNode(*iter, iservice); + if (SUCCESS != ret) { + NS_LOG_WARN("the service param is illegal, ret = " << ret); + continue; + } else { + tmp_service->serviceList.push_back(iservice); + } + } + if (tmp_service->serviceList.empty()) { + NS_LOG_WARN("input servicelist are all illegal."); + } + origin_srvlist_cache_->insert(key, *tmp_service); + ret = AdjustListInRouteRule(service->localAppkey, + service->remoteAppkey, + service->protocol, false); + if (SUCCESS != ret) { + NS_LOG_ERROR("Failed to filte service list. localAppkey :" << service->localAppkey + << ", remoteAppkey :" << service->remoteAppkey + << ", protocol :" << service->protocol + << ", ret :" << ret); + } + return ret; +} +int32_t DiscoveryService::CheckServiceNode(const SGService &oservice, SGService +&iservice) { + std::string appkey = oservice.appkey; + boost::trim(appkey); + if (appkey.empty()) { + NS_LOG_ERROR("fail to register, because the appkey is empty."); + return ERR_EMPTY_APPKEY; + } else if (!IsAppkeyLegal(appkey)) { + NS_LOG_ERROR("Invalid appkey in regist, appkey = " << appkey); + return ERR_INVALIDAPPKEY; + } + if (!IsIpAndPortLegal(oservice.ip, oservice.port)) { + NS_LOG_ERROR("invalid port: " << oservice.port + << ", appkey: " << oservice.appkey + << ", ip: " << oservice.ip + << ", weight: " << oservice.weight); + return ERR_INVALID_PORT; + } + if (("thrift" == oservice.protocol && 0 == oservice.serverType) || + ("http" == oservice.protocol && 1 == oservice.serverType)) { + iservice.__set_protocol(oservice.protocol); + iservice.__set_serviceInfo(oservice.serviceInfo); + } else { + NS_LOG_ERROR("invalid protocol : " << oservice.protocol + << ", serverType : " << oservice.serverType); + return ERR_INVALID_PROTOCOL; + } + if (oservice.fweight > 0.0 && oservice.fweight <= 100.0) { + iservice.__set_weight(oservice.fweight); + iservice.__set_fweight(oservice.fweight); + } else if (oservice.weight > 0 && oservice.weight <= 100) { + iservice.__set_weight(oservice.weight); + iservice.__set_fweight(oservice.weight); + } else { + iservice.__set_weight(10); + iservice.__set_fweight(10.0); + } + if (oservice.role > 0) { + iservice.__set_role(oservice.role); + } + if (oservice.lastUpdateTime > 0) { + iservice.__set_lastUpdateTime(oservice.lastUpdateTime); + } + iservice.__set_appkey(appkey); + iservice.__set_ip(oservice.ip); + iservice.__set_port(oservice.port); + iservice.__set_version(oservice.version); + iservice.__set_envir(oservice.envir); + iservice.__set_serviceInfo(oservice.serviceInfo); + iservice.__set_heartbeatSupport(oservice.heartbeatSupport); + + return SUCCESS; +} +int32_t DiscoveryService::DiscRouteFromZk(RoutePtr route) { + std::string localAppkey = route->localAppkey; + std::string remoteAppkey = route->remoteAppkey; + std::string version = route->version; + std::string protocol = route->protocol; + if (remoteAppkey.empty() || protocol.empty()) { + NS_LOG_ERROR("routeMsg's remoteAppkey is empty! localAppkey = " + << localAppkey + << ", protocol = " << protocol + << ", version = " << version); + return -1; + } + if (NULL == route_cache_) { + NS_LOG_ERROR("ProtocolServicePlugin's Route BufferMgr is NULL, " + "please init it before"); + return -2; + } + std::vector routeList; + //get From zk + bool exclusive_routes_flag = false; + int32_t ret = DiscoveryZkClient::GetInstance()-> + DiscRouteListByProtocol(routeList, + localAppkey, + remoteAppkey, + version, + protocol, + exclusive_routes_flag); + if (SUCCESS == ret) { + NS_LOG_DEBUG("succeed to get route from zk" + << ", remoteAppkey = " << remoteAppkey + << ", protocol = " << protocol + << ", routelist' size = " << routeList.size()); + + route->__set_version(version); + route->__set_routeList(routeList); + } else if (ERR_NODE_NOTFIND == ret) { + NS_LOG_WARN("can not find route node from zk" + << ", appkey = " << remoteAppkey + << ", protocol = " << protocol + << ", version = " << version); + return ret; + } else if (ret == ERR_ZK_LIST_SAME_BUFFER) { + NS_LOG_DEBUG("ZK getRouteList is the same as buf, localAppkey : " + << localAppkey + << ", remoteAppkey is : " << remoteAppkey + << ", version : " << version); + return ret; + } else { + NS_LOG_ERROR("getServiceList from zk fail, " + << ", serviceName = " << remoteAppkey + << ", protocol = " << protocol + << ", routeList' size = " << routeList.size()); + return ret; + } + RouteRule::SortRouteList(route->routeList); + + //write Cache + std::string key = DiscTools::LocalCacheKey(remoteAppkey, protocol); + do { + RouteService route_service; + route_service.last_update_time = time(0); + route_service.error_code = ret; + route_service.route_list = *route; + route_service.enable_exclusive_routes = exclusive_routes_flag; + muduo::MutexLockGuard lock(route_cache_lock_); + route_cache_->insert(key, route_service); + } while(0); + + NS_LOG_INFO("updating route cache, key = " + << key << ", size =" << routeList.size()); + //todo :更新缓存操作 + AdjustListInRouteRule(localAppkey,remoteAppkey,protocol,false); + return SUCCESS; + +} +int32_t DiscoveryService::DiscRouteList(const std::string &local_appkey, + const std::string &remote_appkey, + const std::string &protocol) { + if (NULL == route_cache_) { + NS_LOG_ERROR("route_cache_ is null, please init it"); + return ERR_SERVICE_BUFFER_NULL; + } + std::string key = DiscTools::LocalCacheKey(remote_appkey, protocol); + RouteService res_route; + //先取服务列表 + int ret = route_cache_->get(key, res_route); + if (SUCCESS != ret || (SUCCESS == ret && ERR_NODE_NOTFIND == res_route.error_code + && time(0) - res_route.last_update_time > kMaxInterval)) { + NS_LOG_DEBUG("Cannot find data from route cache , " + "and try to get data from zk, ret = " << ret); + res_route.route_list.__set_localAppkey(local_appkey); + res_route.route_list.__set_remoteAppkey(remote_appkey); + res_route.route_list.__set_version(""); + res_route.route_list.__set_protocol(protocol); + RoutePtr routePtr = boost::make_shared(res_route.route_list); + ret = DiscRouteFromZk(routePtr); + if (0 != ret) { + NS_LOG_WARN("getRouteList ret = " << ret + << ", protocol = " << protocol + << ", appkey = " << remote_appkey); + return ret; + } + res_route.error_code = ret; + } + return res_route.error_code; + +} +int32_t DiscoveryService::DiscBySI(std::vector &srv_list, + const ProtocolRequest &req, + boost::shared_ptr &channels){ + + if (NULL == origin_srvlist_cache_) { + NS_LOG_ERROR("origin srvlist cache is NULL, please wait its initialization."); + return ERR_SERVICE_BUFFER_NULL; + } + if (NULL == filted_srvlist_cache_) { + NS_LOG_ERROR("filted srvlist cache is NULL, please wait its initialization."); + return ERR_SERVICE_BUFFER_NULL; + } + + int ret = DiscByLC(srv_list,req,channels); + if(SUCCESS != ret){ + NS_LOG_WARN("disc from local cache failed, appkey: " + < &srv_list, + const ProtocolRequest &req, + boost::shared_ptr &channels){ + if (NULL == srvname_cache_) { + NS_LOG_ERROR("servicename cache is NULL, please wait its initialization."); + return ERR_SERVICENAME_BUFFER_NULL; + } + std::string key = DiscTools::LocalCacheKey(req.serviceName, req.protocol); + ServiceNamePtr resServiceNamePtr(new getservicename_res_param_t()); + int ret = srvname_cache_->get(key, *resServiceNamePtr); + if (SUCCESS == ret) { + ProtocolRequest req_tmp = req; + int failure_times = 0; + for (std::set::iterator + iter = resServiceNamePtr->appkeys.begin(); + resServiceNamePtr->appkeys.end() != iter; ++iter) { + std::vector servicelist; + req_tmp.__set_remoteAppkey(*iter); + ret = DiscBySI(servicelist, req_tmp, channels); + if (SUCCESS == ret) { + srv_list.insert(srv_list.begin(), + servicelist.begin(), + servicelist.end()); + } else { + ++failure_times; + NS_LOG_ERROR("Failed to get servicelist by Appkey, Appkey = " + << req_tmp.remoteAppkey + << ", ret = " << ret); + } + } + if (0 != failure_times + && failure_times == resServiceNamePtr->appkeys.size()) { + NS_LOG_ERROR( + "Failed to get allservilists, failure_times = " << failure_times); + return ret; + } + RouteRule::FilterServiceName(srv_list, req.serviceName); + return SUCCESS; + } else { + NS_LOG_WARN("Cannot find data from servicename cache, ret = " << ret); + return ret; + } + +} +int32_t DiscoveryService::DiscByLC(std::vector &srv_list, + const ProtocolRequest &req, + boost::shared_ptr &channels){ + + return AdjustListInChannels(srv_list,req,channels); + +} + +int32_t DiscoveryService::DiscNodesFromZk(std::vector &srv_list, + const ProtocolRequest &req) { + + + ServicePtr service(new getservice_res_param_t()); + service->__set_localAppkey(req.localAppkey); + service->__set_remoteAppkey(req.remoteAppkey); + service->__set_version(""); + service->__set_protocol(req.protocol); + int ret = DiscoveryZkClient::GetInstance()->DiscSrvListByProtocol(service); + if (SUCCESS == ret || ERR_NODE_NOTFIND == ret) { + if (ERR_NODE_NOTFIND == ret) { + NS_LOG_WARN("can not find service node from zk" + << ", appkey = " << req.remoteAppkey + << ", protocol = " << req.protocol); + // return empty list + service->serviceList.clear(); + } + if (SUCCESS == ret) { + NS_LOG_INFO("succeed to get service list from zk" + << ", remoteAppkey = " << req.remoteAppkey + << ", protocol = " << req.protocol + << ", serviceList' size = " << service->serviceList.size()); + srv_list = service->serviceList; + } + } else if (ret == ERR_ZK_LIST_SAME_BUFFER) { + // already log inside + return -3; + } else { + NS_LOG_ERROR("getServiceList from zk fail, " + << ", remoteAppkey = " << req.remoteAppkey + << ", protocol = " << req.protocol + << ", serviceList' size = " << service->serviceList.size()); + return -4; + } + + std::string key = req.protocol + "+" + req.remoteAppkey; + + origin_srvlist_cache_->insert(key, *service); + NS_LOG_INFO("the service resServicePtr list size = " + << service->serviceList.size()); + + ret = AdjustListInRouteRule(req.localAppkey, + req.remoteAppkey, + req.protocol,false); + + if (SUCCESS == ret) { + srv_list.clear(); + ret = filted_srvlist_cache_->get(key, srv_list); + } + return ret; +} + +int32_t DiscoveryService::AdjustListInRouteRule(const std::string &localAppkey, + const std::string &remoteAppkey, + const std::string &protocol, + const bool &is_update_route) { + + const std::string key = DiscTools::LocalCacheKey(remoteAppkey, protocol); + + //RouteService route_service; + boost::shared_ptr routeParamFilte + (new RouteService()); + + boost::shared_ptr serviceParamFilte + (new getservice_res_param_t()); + if (is_update_route) { + DiscRouteList(localAppkey,remoteAppkey,protocol); + } + int32_t ret = route_cache_->get(key, *(routeParamFilte.get())); + if (SUCCESS != ret) { + NS_LOG_WARN("null from route buffer when update service list, key = " + << key << ", ret = " << ret); + return ret; + } + bool route_action = (SUCCESS == ret); + ret = origin_srvlist_cache_->get(key, *(serviceParamFilte.get())); + + if (SUCCESS != ret) { + NS_LOG_WARN("null from route buffer when update service list, key = " + << key << ", ret = " << ret); + return ret; + } + + RouteRule::SyncFweight(serviceParamFilte->serviceList); + if (route_action) { + RouteRule::FilterRoute(serviceParamFilte->serviceList, + routeParamFilte->route_list.routeList, + CXmlFile::GetStrPara(CXmlFile::LocalIp), + routeParamFilte->enable_exclusive_routes, + true); //todo:从配置中获取 + } + filted_srvlist_cache_->insert(key, serviceParamFilte->serviceList); + + NS_LOG_INFO("update filted serviceList, key = " + << key + << ", size = " << serviceParamFilte->serviceList.size()); + + return SUCCESS; +} + +int32_t DiscoveryService::DiscSrvlistFromZk(std::vector &srv_list, + const ProtocolRequest &req, + boost::shared_ptr &channels){ + //兼容现有sdk传入参数逻辑 + int32_t ret = FAILURE; + if(!req.remoteAppkey.empty()){ + + NS_LOG_INFO("discovery srvlist in service instance: "< &srv_list, + const ProtocolRequest &req, + boost::shared_ptr &channels) { + int32_t ret = DiscBySrvName(srv_list, req, channels); + if (SUCCESS != ret) { + NS_LOG_DEBUG("Cannot find data from cache ,and try to get serviceName from zk."); + ServiceNamePtr service_name = boost::make_shared(); + service_name->__set_localAppkey(req.localAppkey); + service_name->__set_servicename(req.serviceName); + service_name->__set_protocol(req.protocol); + service_name->__set_version(""); + ret = DiscSrvNameFromZk(service_name); + if (SUCCESS != ret) { + NS_LOG_ERROR("getAppkeyByServiceNameFromWorker failed. localAppkey = " + << req.localAppkey + << ", serviceName = " << req.serviceName + << ", protocol = " << req.protocol + << ", ret = " << ret); + return ret; + } + ret = DiscBySrvName(srv_list, req, channels); + } + return ret; +} +int32_t DiscoveryService::DiscSrvNameFromZk(ServiceNamePtr &service_name) { + if (NULL == srvname_cache_) { + NS_LOG_ERROR("ProtocolServicePlugin's srvname_cache_ is NULL, " + "please init it before"); + return FAILURE; + } + + std::string localAppkey = service_name->localAppkey; + std::string serviceName = service_name->servicename; + std::string protocol = service_name->protocol; + std::string version = service_name->version; + NS_LOG_INFO("TO get Appkey From Worker, serviceName = " + << serviceName + << ", protocol = " << protocol); + + std::set appkeys; + if (serviceName.empty()) { + NS_LOG_ERROR( + "task which is not complete, serviceName is NULL. localAppkey = " + << localAppkey << ", protocol = " << protocol + << ", version = " << version); + return -2; + } else { + //get From zk + int32_t ret = DiscoveryZkClient::GetInstance()-> + DiscAppkeyByServiceName(appkeys, localAppkey, serviceName, version, protocol); + if (SUCCESS == ret) { + NS_LOG_DEBUG("succeed to get serviceName from zk" + << ", serviceName = " << serviceName + << ", protocol = " << protocol + << ", appkeys' size = " << appkeys.size()); + service_name->__set_version(version); + service_name->__set_appkeys(appkeys); + } else if (ERR_NODE_NOTFIND == ret) { + NS_LOG_WARN("can not find serviceName node from zk" + << ", serviceName = " << serviceName + << ", protocol = " << protocol + << ", version = " << version); + return ret; + } else if (ERR_ZK_LIST_SAME_BUFFER == ret) { + // already log inside + return -3; + } else { + NS_LOG_ERROR("getServiceName from zk fail, " + << ", serviceName = " << serviceName + << ", protocol = " << protocol + << ", appkeys' size = " << appkeys.size()); + return FAILURE; + } + + //write Cache + std::string key = DiscTools::LocalCacheKey(serviceName, protocol); + srvname_cache_->insert(key, *service_name); + + NS_LOG_INFO("Receive ServiceName Task in worker thread, key = " + << key + << ", appkey size:" + << service_name->appkeys.size()); + return SUCCESS; + } +} + +} // namespace meituan_mns diff --git a/sg_agent/src/mns/discovery_service.h b/sg_agent/src/mns/discovery_service.h new file mode 100644 index 0000000..334a6cb --- /dev/null +++ b/sg_agent/src/mns/discovery_service.h @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include +#include +#include +#include +#include +#include +#include +#include "discovery_zk_client.h" +#include "base_consts.h" +#include "naming_data_types.h" + +#include "service_channels.h" +#include "buffer_mgr.h" +#include "base_mns_define.h" + +namespace meituan_mns { + +typedef boost::shared_ptr ServiceNamePtr; +typedef boost::shared_ptr ServicePtr; +typedef boost::shared_ptr RoutePtr; +typedef boost::function ThreadInitCallback; + +struct RouteService { + getroute_res_param_t route_list; + time_t last_update_time; + int error_code; + bool enable_exclusive_routes; + RouteService() : last_update_time(0), error_code(0), enable_exclusive_routes(false) {} +}; + +class DiscoveryService { + + public: + + /** + * 初始化缓存等初始化信息 + * @param + * + * @return + * + */ + int32_t Init(void); + + static DiscoveryService* GetInstance(void); + + void StartThread(void); + + ~DiscoveryService() {}; + + /** + * 为server侧提供获取服务列表接口 + * @param srvlist,req,channels + * + * @return int + * + */ + int32_t DiscGetSrvList(std::vector &srvlist, + const ProtocolRequest &req, + boost::shared_ptr &channels); + + /** + * 从zookeeper拉取服务节点 + * @param srv_list,key,req + * + * @return int + * + */ + int32_t DiscNodesFromZk(std::vector &srv_list, + const ProtocolRequest &req); + + /** + * + * @param service + * @return + */ + int32_t UpdateSrvList(const ServicePtr &service); + + /** + * + * @param list_and_cache + * @param protocol + * @param appkey + * @return + */ + int32_t GetSrvListAndCacheSize(ServListAndCache &list_and_cache, + const std::string &protocol, + const std::string &appkey); + + /** + * + * @param srv_list + * @param req + * @param channels + * @return + */ + int32_t DiscBySI(std::vector &srv_list, + const ProtocolRequest &req, + boost::shared_ptr &channels); + + int32_t RepalceSrvlist(const boost::shared_ptr &service); + + + private: + /** + * 从注册中心=zookeeper发现服务节点 + * @param srvlist,req,channels + * + * @return int + * + */ + int32_t DiscSrvlistFromZk(std::vector &srv_list, + const ProtocolRequest &req, + boost::shared_ptr &channels); + /** + * 从注册中心=cache发现服务节点,如redis,cache(mnsc) + * @param srvlist,req,channels + * + * @return int + * + */ + int32_t DiscSrvlistFromCache(std::vector &srv_list, + const ProtocolRequest &req, + boost::shared_ptr &channels); + /** + * 存储两种以上进行服务节点发现,如zookeeper+cached + * @param srvlist,req,channels + * + * @return int + * + */ + int32_t DiscSrvlistFromMixer(std::vector &srv_list, + const ProtocolRequest &req, + boost::shared_ptr &channels); + /** + * 通过SI: service instance 发现服务节点 + * @param srvlist,req,channels + * + * @return int + * + */ + int32_t DiscBySrvName(std::vector &srv_list, + const ProtocolRequest &req, + boost::shared_ptr &channels); + /** + * 通过SIN:service interface name发现服务节点 + * @param srvlist,req,channels + * + * @return int + * + */ + int32_t DiscBySIN(std::vector &srv_list, + const ProtocolRequest &req, + boost::shared_ptr &channels); + + /** + * 通过LC:本地缓存发现服务节点 + * @param srvlist,req,channels + * + * @return int + * + */ + int32_t DiscByLC(std::vector &srv_list, + const ProtocolRequest &req, + boost::shared_ptr &channels); + + /** + * + * @param servicename + * @return + */ + + int32_t DiscSrvNameFromZk(ServiceNamePtr &service_name); + /** + * 调整服务列表预处理 + * @param srv_list,req,channels + * + * @return int + * + */ + + int32_t AdjustListInChannels(std::vector &srv_list, + const ProtocolRequest &req, + boost::shared_ptr &channels); + /** + * 按泳道对服务列表进行标记处理 + * @param srv_list,req,channels + * + * @return int + * + */ + int32_t AdjustInSwimlane(std::vector *srv_list, + const ProtocolRequest &req, + boost::shared_ptr &channels); + + + /** + * 按原始全量服务列表处理 + * @param srv_list,key,req + * + * @return int + * + */ + int32_t AdjustInOrigin(std::vector &srv_list, + const std::string& key, + const ProtocolRequest &req); + + /** + * 获取路由信息 + * @param local_appkey,remote_appkey,protocol + * + * @return int32_t + * + */ + int32_t DiscRouteList(const std::string &local_appkey, + const std::string &remote_appkey, + const std::string &protocol); + + /** + * 从zookeeper获取路由配置信息 + * @param local_appkey,remote_appkey,protocol + * + * @return int32_t + * + */ + int32_t DiscRouteFromZk(RoutePtr route); + + /** + * 按路由规则调整服务列表 + * @param local_appkey,remote_appkey,protocol + * + * @return int32_t + * + */ + int AdjustListInRouteRule(const std::string &localAppkey, + const std::string &remoteAppkey, + const std::string &protocol, + const bool &is_update_route); + + + int32_t CheckServiceNode(const SGService &oservice, SGService + &iservice); + + /** + * 定时更新srvlist + */ + void UpdateSrvListTimer(); + /** + *定时更行routelist + */ + void UpdateRouteTimer(); + /** + *定时更新servname + */ + void UpdateSrvNameTimer(); + + private: + DiscoveryService() {}; + + + static muduo::MutexLock disc_service_lock_; + static DiscoveryService *disc_service_; + + + + static BufferMgr *route_cache_; + muduo::MutexLock route_cache_lock_; + + static BufferMgr *origin_srvlist_cache_; + muduo::MutexLock origin_srvlist_cache_lock_; + + // 用于存储分组后的serviceList + static BufferMgr > *filted_srvlist_cache_; + muduo::MutexLock filted_srvlist_cache_lock; + + static BufferMgr *srvname_cache_; + muduo::MutexLock srvname_cache_lock_; + + muduo::net::EventLoop *mns_timer_loop_; + muduo::net::EventLoopThread mns_timer_thread_; + + protected: + +}; + +} // namespace meituan_mns diff --git a/sg_agent/src/mns/discovery_zk_client.cc b/sg_agent/src/mns/discovery_zk_client.cc new file mode 100644 index 0000000..3e183ee --- /dev/null +++ b/sg_agent/src/mns/discovery_zk_client.cc @@ -0,0 +1,484 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "discovery_zk_client.h" +#include "discovery_service.h" +#include "log4cplus.h" +#include "zk_client.h" +#include "zk_client_pool.h" +#include "json_data_tools.h" +#include "base_mns_consts.h" +#include "base_errors_consts.h" +#include "base_consts.h" +#include "sds_tools.h" +#include "zk_path_tools.h" +#include "inc_comm.h" + +namespace meituan_mns { + +DiscoveryZkClient *DiscoveryZkClient::disc_zk_instance_ = NULL; +muduo::net::EventLoopThreadPool *DiscoveryZkClient::disc_pool_ = NULL; +muduo::MutexLock DiscoveryZkClient::disc_zk_service_lock_; + +void DiscoveryZkClient::ThreadInfo(void) { + NS_LOG_INFO("registry thread info,pid = " << getpid() + << "; tid = " + << muduo::CurrentThread::tid()); +} + +DiscoveryZkClient *DiscoveryZkClient::GetInstance() { + + if (NULL == disc_zk_instance_) { + muduo::MutexLockGuard lock(disc_zk_service_lock_); + if (NULL == disc_zk_instance_) { + disc_zk_instance_ = new DiscoveryZkClient(); + } + } + return disc_zk_instance_; +} + +void DiscoveryZkClient::Init() { + + disc_loop_ = disc_loop_thread_.startLoop(); + disc_loop_->runInLoop(boost::bind(&DiscoveryZkClient::InitDiscThreadPool, + this, disc_loop_, + CXmlFile::GetI32Para(CXmlFile::WatcherDispatchThreads), + "disc-num")); +} + +void DiscoveryZkClient::InitDiscThreadPool(muduo::net::EventLoop *mns_loop, + int32_t num_threads, + const std::string &name) { + + NS_LOG_INFO("Init discovery threads num: " << num_threads); + if (0 == num_threads || num_threads > kMaxDiscThreads) { + NS_LOG_WARN("the discovery thread is " << num_threads); + num_threads = kMaxDiscThreads; + } + disc_pool_ = new muduo::net::EventLoopThreadPool(mns_loop, name); + disc_pool_->setThreadNum(num_threads); + SetThreadInitCallback(boost::bind(&DiscoveryZkClient::ThreadInfo, this)); + disc_pool_->start(threadInitCallback_); + disc_loops_ = disc_pool_->getAllLoops(); +} + +int32_t DiscoveryZkClient::DiscAppkeyByServiceName(std::set &appkeys, + const std::string &local_appkey, + const std::string &service_name, + std::string &version, + const std::string &protocol) { + std::string zk_path = ""; + int32_t ret = agent_zk_path_.GenServiceNameZkPathNode(zk_path, service_name, protocol); + if (SUCCESS != ret) { + NS_LOG_ERROR("_gen genServiceNameZkPathNode fail! protocol is empty! zkPath: " + << zk_path); + return ret; + } + + std::string strJson; + ZkGetRequestPtr request = boost::make_shared(); + request->path = zk_path; + request->watch = 0; + ZkGetResponsePtr response = boost::make_shared(); + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)-> + ZkGet(request, response); + if (ZOK != ret) { + // the zkPath contains necessary info + NS_LOG_ERROR( + "fail to getAppkeyByServiceName, path = " + << zk_path << ", err_code = " << ret); + return ret; + } + strJson = response->buffer; + ServiceNode oserviceNode; + ret = JsonZkMgr::Json2ServiceNode(strJson, oserviceNode); + if (SUCCESS != ret) { + NS_LOG_ERROR("getAppkeyByServiceName _Json2ServiceNode fail, Json: " + << strJson + << ", ret = " << ret); + return ret; + } + if (!version.empty() && + response->stat.version <= atoi(version.c_str())) { + NS_LOG_INFO("srvname: "<< service_name <<" buff version has no change."); + return ERR_ZK_LIST_SAME_BUFFER; + } + ret = ConvertInt2String(response->stat.version, version); + if (SUCCESS != ret) { + NS_LOG_ERROR("version : " << response->stat.version + << " Failed to ConvertInt2String."); + } + appkeys = oserviceNode.appkeys; + return SUCCESS; +} + +void DiscoveryZkClient::DiscByProtocolWatcher(zhandle_t *zh, + int32_t type, + int32_t state, + const char *path, + void *watcherCtx) { + + NS_LOG_INFO("rcv the watcher from the ZK server by protocol,path" + << path << "type" << type); + if (strlen(path) == 0 || type == -1) { + NS_LOG_ERROR("get event serviceByProtocolWatcher, " + "that ZK server may down! state = " << state + << ", type = " << type + << ", path = " << path); + return; + } else { + std::string path_str(path); + NS_LOG_INFO("zk watch trigger: path = " << path_str); + } + + std::string appkey = ""; + std::string protocol = ""; + int32_t ret = AgentZkPath::DeGenZkPath(path, appkey, protocol); + + if (SUCCESS != ret) { + NS_LOG_ERROR("deGenZkPath is serviceByProtocolWatcher is wrong! path:" + << path << ", appkey:" << appkey + << ", protocol:" << protocol); + return; + } + DiscoveryService *disc = static_cast(watcherCtx); + std::vector service_list; + ProtocolRequest request; + request.__set_remoteAppkey(appkey); + request.__set_protocol(protocol); + request.__set_localAppkey("sg_agent_protocol_watcher"); + disc->DiscNodesFromZk(service_list, request); + +} +int32_t DiscoveryZkClient::DiscSrvListByProtocol(ServicePtr &service, + bool is_watcher_callback) { + + service->serviceList.clear(); + // generate the zk path of provider + std::string provider_path = ""; + std::string node_type = "provider"; + int32_t ret = agent_zk_path_.GenProtocolZkPath(provider_path, + service->remoteAppkey, + service->protocol, + node_type); + if (SUCCESS != ret) { + return ret; + } + // wget the data of provider path + ZkWGetRequestPtr zk_wget_req(new ZkWGetRequest); + zk_wget_req->path = provider_path; + if (whitelist_manager_.IsAppkeyInWhitList(service->remoteAppkey)) { + zk_wget_req->watch = NULL; + } else { + zk_wget_req->watch = DiscByProtocolWatcher; + zk_wget_req->watcherCtx = DiscoveryService::GetInstance(); + } + + ZkWGetResponsePtr zk_wget_res(new ZkWGetResponse()); + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)-> + ZkWget(zk_wget_req,zk_wget_res); + if(ZOK != ret){ + NS_LOG_ERROR("fail to zk wget. ret = " + << ret << ", path = " << provider_path); + return ret; + } + struct Stat stat = zk_wget_res->stat; + std::string version = service->version; + GetMnsCacheParams params; + params.appkey = service->remoteAppkey; + params.protocol = service->protocol; + params.env = CXmlFile::GetAppenv()->GetStrEnv(); + params.version = GetVersion(stat.mtime, stat.cversion, stat.version); + ret = version_manager_.CheckZkVersion(service->remoteAppkey + service->protocol, + params.version, version); + + if (0 != params.appkey.compare(CXmlFile::GetStrPara + (CXmlFile::MNSCacheAppkey))) { + ret = + MnscClient::GetInstance()->GetServicelistFromMnsc(service->serviceList, + params); + if (SUCCESS == ret) { + NS_LOG_INFO("register watcher for parent node"); + return SUCCESS; + } + } + NS_LOG_INFO("register watcher for parent node"); + ZkWGetChildrenRequestPtr zk_wget_child_req = + boost::shared_ptr(new (ZkWGetChildrenRequest)); + ZkWGetChildrenResponsePtr zk_wget_child_res = + boost::shared_ptr(new (ZkWGetChildrenResponse)); + + zk_wget_child_req->path = provider_path; + zk_wget_child_req->watch = DiscByProtocolWatcher; + zk_wget_child_req->watcherCtx = 0; + + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)-> + ZkWgetChildren(zk_wget_child_req, zk_wget_child_res); + if (ZOK != ret) { + NS_LOG_ERROR("fail to get children nodes from zk. ret = " + << ret << ", path = " << provider_path); + return ret; + } + muduo::CountDownLatch thread_finish_countdown(kMaxDiscThreads); + SubGetServiceParams sub_params; + sub_params.provider_path = provider_path; + sub_params.remote_appkey = service->remoteAppkey; + sub_params.wg_child_params = zk_wget_child_res; + + std::vector all_res; + for (int32_t i = 0; i < kMaxDiscThreads; ++i) { + NS_LOG_INFO("the watcher zk threads get loops length = " + << disc_loops_[i]->queueSize()); + SubGetServiceResPtr sub_res(new SubGetServiceRes()); + all_res.push_back(sub_res); + sub_params.index = i; + disc_loops_[i]->runInLoop(boost::bind(&DiscoveryZkClient::GetSubSrvListFromZk, + this, + sub_res, + sub_params, + &thread_finish_countdown)); + } + thread_finish_countdown.wait(); + for (std::vector::iterator iter = all_res.begin(); + all_res.end() != iter; ++iter) { + if (!(*iter)->is_ok) { + return FAILURE; + } + service->serviceList.insert(service->serviceList.begin(), + (*iter)->srvlist.begin(), (*iter)->srvlist.end()); + } + NS_LOG_INFO("watcher get svrlist from the zk, size is " + << service->serviceList.size() + << ", thread num = " << kMaxDiscThreads); + + // 服务节点下线或者反序列化失败 + if (zk_wget_child_res->count != service->serviceList.size()) { + NS_LOG_WARN("srvlist size is " << service->serviceList.size() + << ", childnode num is " + << zk_wget_child_res->count + << ". Json failed or nodes have been deleted."); + } + return SUCCESS; + +} + +void DiscoveryZkClient::DivRangeDiscIndex(const int32_t &index, + int32_t &begin, + int32_t &end, + const int32_t &child_count) { + begin = index * child_count / kMaxDiscThreads; + end = (index + 1) * child_count / kMaxDiscThreads; + + NS_LOG_INFO("the index " << index << ", begin " + << begin << ", end " + << end << ", child_count " + << child_count); +} +int32_t DiscoveryZkClient::GetSubSrvListFromZk(SubGetServiceResPtr &sub_res, + const SubGetServiceParams &sub_params, + muduo::CountDownLatch *p_countdown){ + int32_t ret = -1; + sub_res->srvlist.clear(); + int32_t begin = 0, end = 0; + NS_LOG_INFO("the remote appkey is " + << sub_params.remote_appkey + << ", cout = " << sub_params.wg_child_params->count); + + DivRangeDiscIndex(sub_params.index, begin, + end, sub_params.wg_child_params->count); + for (int32_t i = begin; i < end; ++i){ + std::string zk_node_path = sub_params.provider_path + "/" + sub_params.wg_child_params->data[i]; + ZkGetRequestPtr zk_get_req = boost::shared_ptr(new ZkGetRequest()); + ZkGetResponsePtr zk_get_res = boost::shared_ptr(new ZkGetResponse()); + zk_get_req->path = zk_node_path; + zk_get_req->watch = 0; + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)->ZkGet(zk_get_req, zk_get_res); + + if (ERR_NODE_NOTFIND == ret) { + NS_LOG_WARN("the service node has been deleted, " + "ignore it and continue updating service list. path = " + << zk_node_path); + continue; + } else if (ZOK != ret){ + NS_LOG_ERROR("fail to get zk data. ret = " + << ret << ", path = : " << zk_node_path); + sub_res->is_ok = false; + p_countdown->countDown(); + return ret; + } + std::string node_json_str = zk_get_res->buffer; + NS_LOG_INFO("succeed to zoo_get, json: " << node_json_str); + SGService oservice; + ret = JsonZkMgr::Json2SGService(node_json_str, oservice); + if (ret != 0) { + NS_LOG_WARN("fail to parse node json str. " + << ", ret = " << ret + << ", path = " << zk_node_path + << ", json = " << node_json_str); + continue; + } + if (oservice.appkey != sub_params.remote_appkey) { + NS_LOG_WARN("expected appkey: " << sub_params.remote_appkey + << ", but node.appky = " << oservice.appkey + << ", path = " << zk_node_path); + continue; + } + //update srvlist + sub_res->srvlist.push_back(oservice); + NS_LOG_INFO("srvlist size : " << sub_res->srvlist.size()); + } + p_countdown->countDown(); +} + +int32_t DiscoveryZkClient::DiscRouteListByProtocol(std::vector &routeList, + const std::string &localAppkey, + const std::string &appKey, + std::string &version, + const std::string &protocol, + bool &route_flag){ + std::string zk_path = ""; + std::string nodeType = "route"; + int32_t ret = agent_zk_path_.GenProtocolZkPath(zk_path, appKey, protocol, nodeType); + if (0 != ret) { + NS_LOG_ERROR("gen zk route path failed, zk path:"<(new ZkGetRequest()); + ZkGetResponsePtr zk_get_res = boost::shared_ptr(new ZkGetResponse()); + zk_get_req->path = zk_path; + zk_get_req->watch = 0; + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)->ZkGet(zk_get_req, zk_get_res); + if(ZOK != ret){ + NS_LOG_WARN("fail to get route data, ret = " << ret << ", path = " + << zk_get_req->path); + return ret; + }else if(ERR_NODE_NOTFIND == ret) { + NS_LOG_WARN("fail to get route data, because the zk node don't exist. ret = " << ret + << ", path = " + << zk_get_req->path); + return ERR_NODE_NOTFIND; + } + str_json = zk_get_res->buffer; + data_len = zk_get_res->buffer_len; + stat = zk_get_res->stat; + if (str_json.empty()) { + NS_LOG_ERROR("strJson is empty , cannot Json2RouteNode."); + return ERR_DATA_TO_JSON_FAIL; + } + CRouteNode oroute; + ret = JsonZkMgr::Json2RouteNode(str_json, stat.mtime, stat.version, stat.cversion, oroute); + if (ret != 0) { + NS_LOG_ERROR("_Json2RouteNode fail ret = " << ret + << ", json is: " << str_json.c_str()); + return ERR_DATA_TO_JSON_FAIL; + } + std::string zk_version = GetVersion(oroute.mtime, oroute.cversion, oroute.version); + NS_LOG_INFO("the route info, key: "<(new (ZkWGetChildrenRequest)); + ZkWGetChildrenResponsePtr zk_wget_child_res = + boost::shared_ptr(new (ZkWGetChildrenResponse)); + + zk_wget_child_req->path = zk_path; + zk_wget_child_req->watch = 0; + + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)->ZkWgetChildren(zk_wget_child_req, + zk_wget_child_res); + + if (ZOK != ret) { + NS_LOG_WARN("getRoute.zoo_wget_children fail, zkPath: " << zk_path + << ", ret = " << ret); + return ret; + } else if (zk_wget_child_res->count == 0) { + NS_LOG_WARN("getRouteList strings.count == 0 !"); + return 0; + } + + //如果子节点非空,则遍历所有子节点,构造返回服务列表 + + std::string route_node_path = ""; + for (int32_t i = 0; i < zk_wget_child_res->count; i++) { + route_node_path = agent_zk_path_.GenRoutePath(zk_path, + zk_wget_child_res->data[i]); + + //获取子节点信息时,去掉watcher + ZkGetRequestPtr zk_get_req(new ZkGetRequest()); + ZkGetResponsePtr zk_get_res(new ZkGetResponse()); + zk_get_req->path = route_node_path; + zk_get_req->watch = 0; + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)-> + ZkGet(zk_get_req, zk_get_res); + if (ZOK != ret) { + NS_LOG_ERROR("getRouteList.zoo_wget children " + << i << ", fail ret: " << ret + << " zkpath is : " << route_node_path); + return ret; + } + + str_json.assign(zk_get_res->buffer); + data_len = zk_get_res->buffer_len; + stat_child = zk_get_res->stat; + + if (str_json.empty() || 0 == data_len) { + continue; + } + + CRouteData routeData; + ret = JsonZkMgr::Json2RouteData(str_json, routeData); + if (SUCCESS != ret) { + NS_LOG_ERROR("json2routeData fail, strJson is:" << str_json.c_str() + << ", ret = " << ret); + continue; + } + + /// double check + if (routeData.appkey != appKey) { + NS_LOG_ERROR("unexpected exception! appkey " << appKey.c_str() + << "routeData.appKey " + << routeData.appkey.c_str() + << "datalen " << data_len); + continue; + } + //将数据插入到返回列表中 + routeList.push_back(routeData); + if (!route_flag && 4 == routeData.category) { + route_flag = true; + } + } + + return 0; +} + +} // namespace meituan_mns diff --git a/sg_agent/src/mns/discovery_zk_client.h b/sg_agent/src/mns/discovery_zk_client.h new file mode 100644 index 0000000..1c97712 --- /dev/null +++ b/sg_agent/src/mns/discovery_zk_client.h @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_DISCOVERY_ZK_CLIENT_H +#define OCTO_OPEN_SOURCE_DISCOVERY_ZK_CLIENT_H + +#include "naming_service_types.h" +#include +#include +#include +#include +#include "naming_data_types.h" +#include +#include +#include +#include +#include "version_manager.h" +#include "zk_path_tools.h" +#include "zk_invoke_param.h" +#include "mnsc_client.h" + +extern "C" { +#include +#include "comm/cJSON.h" +} + +namespace meituan_mns { + + +class DiscoveryZkClient { + public: + + void Init(void); + + static DiscoveryZkClient *GetInstance(void); + + typedef boost::function ThreadInitCallback; + /** + * + * @param srvlist + * @param localAppkey + * @param appKey + * @param protocol + * @param is_watcher_callback + * @return + */ + int32_t DiscSrvListByProtocol(boost::shared_ptr &service, + bool is_watcher_callback = false); + + /** + * + * @param routeList + * @param localAppkey + * @param appKey + * @param version + * @param protocol + * @return + */ + int32_t DiscRouteListByProtocol(std::vector &routeList, + const std::string &localAppkey, + const std::string &appKey, + std::string &version, + const std::string &protocol, + bool &route_flag); + + /** + * + * @param zh + * @param type + * @param state + * @param path + * @param watcherCtx + */ + static void DiscByProtocolWatcher(zhandle_t *zh, int32_t type, int32_t state, + const char *path, void *watcherCtx); + /** + * + * @param appkeys + * @param local_appkey + * @param service_name + * @param version + * @param protocol + * @return + */ + + int32_t DiscAppkeyByServiceName(std::set &appkeys, + const std::string &local_appkey, + const std::string &service_name, + std::string &version, + const std::string + &protocol); + + private: + + int32_t DiscoveryListFromCache(std::vector &srvlist, + GetMnsCacheParams& params); + /** + * + * @param index + * @param begin + * @param threads + * @param end + * @param child_count + */ + void DivRangeDiscIndex(const int32_t &index, + int32_t &begin, + int32_t &end, + const int32_t &child_count); + + int32_t GetSubSrvListFromZk(SubGetServiceResPtr &sub_res, + const SubGetServiceParams &sub_params, + muduo::CountDownLatch *p_countdown); + + + DiscoveryZkClient(){}; + ~DiscoveryZkClient() {}; + + + + static DiscoveryZkClient *disc_zk_instance_; + + /** + *初始化注册处理线程 + *@param mns_loop,num_threads,name + * + *@return void type + * + **/ + void InitDiscThreadPool(muduo::net::EventLoop *mns_loop, + int32_t num_threads, const std::string &name); + /** + * + * @param cb + */ + void SetThreadInitCallback(const ThreadInitCallback &cb) { threadInitCallback_ = cb; }; + + void ThreadInfo(void); + + + private: + + AgentZkPath agent_zk_path_; + VersionManager version_manager_; + WhiteListManager whitelist_manager_; + + ThreadInitCallback threadInitCallback_; + muduo::net::EventLoopThread disc_loop_thread_; + muduo::net::EventLoop *disc_loop_; + static muduo::net::EventLoopThreadPool *disc_pool_; + std::vector disc_loops_; + static muduo::MutexLock disc_zk_service_lock_; + + protected: + +}; + +} // namespace meituan_mns + + + +#endif //OCTO_OPEN_SOURCE_DISCOVERY_ZK_CLIENT_H diff --git a/sg_agent/src/mns/hot_load_config.cc b/sg_agent/src/mns/hot_load_config.cc new file mode 100644 index 0000000..bec3602 --- /dev/null +++ b/sg_agent/src/mns/hot_load_config.cc @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "hot_load_config.h" +#include "inc_comm.h" +#include "base_consts.h" +#include "md5.h" +#include + +namespace meituan_mns { + + +const int kPeriodTime = 5*60;//5min +const int kSleepTime = 20*1000;//50ms +const std::string idc_file_name = "idc.xml"; + + +DynamicLoadConfig* DynamicLoadConfig::dynamic_load_config_ = NULL; +muduo::MutexLock DynamicLoadConfig::dynamic_load_config_lock_; + +DynamicLoadConfig::DynamicLoadConfig() : + idc_md5_(""), + appkeys_md5_(""), + check_loop_ (NULL), + check_thread_ (boost::function(), "sg_agent") {} + +DynamicLoadConfig::~DynamicLoadConfig() { + if (NULL != check_loop_) { + check_loop_->quit(); + // sleep for avoiding race condition + usleep(kSleepTime); + delete check_loop_; + check_loop_ = NULL; + } + SAFE_DELETE(dynamic_load_config_); +} + +DynamicLoadConfig* DynamicLoadConfig::GetInstance() { + if (NULL == dynamic_load_config_) { + muduo::MutexLockGuard lock(dynamic_load_config_lock_); + if (NULL == dynamic_load_config_) { + dynamic_load_config_ = new DynamicLoadConfig(); + } + } + return dynamic_load_config_; +} +void DynamicLoadConfig::Init() { + idc_md5_ = CalculateMd5(idc_file_name, AGENT_CONF_PATH); + check_loop_ = check_thread_.startLoop(); + check_loop_->runEvery(kPeriodTime, boost::bind(&DynamicLoadConfig::UpdateIdcsTimer, + this)); +} + +void DynamicLoadConfig::UpdateIdcsTimer(void) { + std::string idc_md5_tmp = CalculateMd5(idc_file_name, AGENT_CONF_PATH); + if (idc_md5_tmp.empty() || + 0 == idc_md5_tmp.compare(idc_md5_)) { + return ; + } + cxml_file_.UpdateIdcs(); +} + + + +std::string DynamicLoadConfig::CalculateMd5(const std::string &file_name, + const std::string &file_path) { + std::string context = ""; + int32_t ret = loadFile(context, file_name, file_path); + if (SUCCESS != ret) { + NS_LOG_ERROR("failed to load idc."); + return ""; + } + MD5 md5_string(context); + return md5_string.md5(); +} + + +} \ No newline at end of file diff --git a/sg_agent/src/mns/hot_load_config.h b/sg_agent/src/mns/hot_load_config.h new file mode 100644 index 0000000..a6f285d --- /dev/null +++ b/sg_agent/src/mns/hot_load_config.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef DYNAMICLOADCONFIG_H +#define DYNAMICLOADCONFIG_H + +#include +#include "muduo/net/EventLoop.h" +#include "muduo/net/EventLoopThread.h" +#include "config_loader.h" + +namespace meituan_mns { +class DynamicLoadConfig { + public: + static DynamicLoadConfig* GetInstance(void); + + ~DynamicLoadConfig(); + + void Init(void); + + void UpdateIdcsTimer(void); + + std::string CalculateMd5(const std::string &file_name, + const std::string &file_path); + private: + DynamicLoadConfig(); + + static DynamicLoadConfig* dynamic_load_config_; + static muduo::MutexLock dynamic_load_config_lock_; + CXmlFile cxml_file_; + + muduo::net::EventLoopThread check_thread_; + muduo::net::EventLoop *check_loop_; + + std::string idc_md5_; + std::string appkeys_md5_; + +}; + +} + +#endif //OCTO_OPEN_SOURCE_上午11_17_21_DYNAMICLOADCONFIG_H diff --git a/sg_agent/src/mns/http_service.cc b/sg_agent/src/mns/http_service.cc new file mode 100644 index 0000000..046023f --- /dev/null +++ b/sg_agent/src/mns/http_service.cc @@ -0,0 +1,810 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "http_service.h" +#include "route_info.h" +#include "config_loader.h" +#include "discovery_service.h" +#include "monitor_collector.h" +using namespace meituan_mns; + +muduo::MutexLock HttpService::http_service_lock_; +HttpService *HttpService::http_service_ = NULL; + + +HttpService *HttpService::GetInstance() { + if (NULL == http_service_) { + muduo::MutexLockGuard lock(http_service_lock_); + if (NULL == http_service_) { + http_service_ = new HttpService(); + } + } + return http_service_; +} +HttpService::~HttpService() { + + if (NULL != http_service_loop_) { + http_service_loop_->quit(); + usleep(kThreadTime * http_service_loop_->queueSize()); + delete http_service_loop_; + http_service_loop_ = NULL; + } +} + +/* + * parse data from http + */ +int32_t HttpService::ParseServiceDataFromHttp(const char *post_data, + ServicePtr &service) { + if (NULL == post_data) { + NS_LOG_ERROR("the http post msg is null"); + return FAILURE; + } + cJSON *root = cJSON_Parse(post_data); + if (NULL == root) { + NS_LOG_ERROR("the cJSON_Parse error"); + return FAILURE; + } + cJSON *pItem = cJSON_GetObjectItem(root, "remoteAppkey"); + if (NULL != pItem) { + std::string remote_appkey = pItem->valuestring; + boost::trim(remote_appkey); + if (!remote_appkey.empty()) { + service->__set_remoteAppkey(remote_appkey); + } else { + NS_LOG_ERROR("remoteappkey is empty."); + cJSON_Delete(root); + return FAILURE; + } + } else { + NS_LOG_ERROR("the flush service remoteappkey is null"); + cJSON_Delete(root); + return FAILURE; + } + pItem = cJSON_GetObjectItem(root, "protocol"); + if (NULL != pItem) { + std::string protocol = pItem->valuestring; + boost::trim(protocol); + if (!protocol.empty()) { + service->__set_protocol(protocol); + } else { + NS_LOG_ERROR("procotol is empty."); + cJSON_Delete(root); + return FAILURE; + } + } else { + NS_LOG_ERROR("the flush service procotol is null"); + cJSON_Delete(root); + return FAILURE; + } + pItem = cJSON_GetObjectItem(root, "localAppkey"); + if (NULL != pItem) { + service->__set_localAppkey(pItem->valuestring); + } + pItem = cJSON_GetObjectItem(root, "version"); + if (NULL != pItem) { + service->__set_version(pItem->valuestring); + } + pItem = cJSON_GetObjectItem(root, "serviceList"); + if (NULL != pItem) { + std::vector servicelist; + int size = cJSON_GetArraySize(pItem); + cJSON *item = NULL; + for (int i = 0; i < size; ++i) { + SGService serviceInfo; + item = cJSON_GetArrayItem(pItem, i); + if (SUCCESS == ParseNodeData(item, serviceInfo)) { + serviceInfo.__set_appkey(service->remoteAppkey); + serviceInfo.__set_protocol(service->protocol); + serviceInfo.__set_envir(CXmlFile::GetAppenv()->GetIntEnv());//获取本地sg_agent环境 + serviceInfo.__set_lastUpdateTime(time(NULL));//获取当前时间 + servicelist.push_back(serviceInfo); + } else { + NS_LOG_WARN("Failed to parse the " << i << "th serviceInfo."); + } + } + if (!servicelist.empty()) { + service->__set_serviceList(servicelist); + } else { + NS_LOG_WARN("servlist is empty , remoteAppkey = " << service->remoteAppkey + << ", protocol = " << service->protocol); + } + } + cJSON_Delete(root); + return SUCCESS; +} +int32_t HttpService::ParseNodeData(cJSON *root, SGService &service_info) { + cJSON *pItem = cJSON_GetObjectItem(root, "ip"); + if (NULL != pItem) { + service_info.__set_ip(pItem->valuestring); + } else { + NS_LOG_ERROR("the flush service ip is null"); + return FAILURE; + } + pItem = cJSON_GetObjectItem(root, "port"); + if (NULL != pItem) { + service_info.__set_port(pItem->valueint); + } else { + NS_LOG_ERROR("the flush port is null"); + return FAILURE; + } + pItem = cJSON_GetObjectItem(root, "version"); + if (NULL != pItem) { + service_info.__set_version(pItem->valuestring); + } + pItem = cJSON_GetObjectItem(root, "weight"); + if (NULL != pItem) { + service_info.__set_weight(pItem->valueint); + } + pItem = cJSON_GetObjectItem(root, "status"); + if (NULL != pItem) { + service_info.__set_status(pItem->valueint); + } + pItem = cJSON_GetObjectItem(root, "role"); + if (NULL != pItem) { + service_info.__set_role(pItem->valueint); + } + pItem = cJSON_GetObjectItem(root, "serverType"); + if (NULL != pItem) { + service_info.__set_serverType(pItem->valueint); + } + pItem = cJSON_GetObjectItem(root, "heartbeatSupport"); + if (NULL != pItem) { + service_info.__set_heartbeatSupport(pItem->valueint); + } + pItem = cJSON_GetObjectItem(root, "serviceInfo"); + if (pItem) { + cJSON *svrNames = pItem; + int size = cJSON_GetArraySize(svrNames); + for (int i = 0; i < size; ++i) { + cJSON *item = cJSON_GetArrayItem(svrNames, i); + if (NULL != item) { + std::string serviceName(item->string); + NS_LOG_INFO("service name is:" << serviceName); + bool unifiedProto = + (0 != cJSON_GetObjectItem(item, "unifiedProto")->valueint); + ServiceDetail srv; + srv.__set_unifiedProto(unifiedProto); + service_info.serviceInfo[serviceName] = srv; + } + } + } + NS_LOG_INFO("node flush info: appkey:" + << service_info.appkey << " ip: " + << service_info.ip << " status:" + << service_info.status << " last update time: " + << service_info.lastUpdateTime); + return SUCCESS; +} + +void HttpService::StartService() { + + char local_ip[LOCAL_IP], local_mask[LOCAL_MASK]; + memset(local_ip, '0', LOCAL_IP); + memset(local_mask, '0', LOCAL_MASK); + + if (getIntranet(local_ip, local_mask) < 0) { + NS_LOG_ERROR("getIntranet failed"); + return; + } else { + NS_LOG_INFO( + "getIntranet ip and mask are " << local_ip << "," << local_mask); + } + + struct event_base *base; + struct evhttp *http; + base = event_base_new(); + if (!base) { + NS_LOG_ERROR("event_base_new() failed"); + return; + } + http = evhttp_new(base); + if (!http) { + NS_LOG_ERROR("evhttp_new() http server failed"); + event_base_free(base); + return; + } + if (evhttp_bind_socket(http, listen_ip.c_str(), http_port)) { + NS_LOG_ERROR("http bind socket failed"); + evhttp_free(http); + event_base_free(base); + return; + } + + evhttp_set_gencb(http, HttpHandler, this); + event_base_dispatch(base); + evhttp_free(http); + event_base_free(base); + + return; +} + +int32_t HttpService::UpdateServiceInCache(const ServicePtr &service) { + + NS_LOG_INFO("http service:update service "); + int32_t ret = DiscoveryService::GetInstance()->UpdateSrvList(service); + if (SUCCESS != ret) { + NS_LOG_ERROR("Run mns update srv list failed, ret = " << ret); + } + return ret; +} + +int32_t HttpService::GetServListAndCacheSize(ServListAndCache &list_and_cache, + const std::string &protocol, + const std::string &appkey) { + NS_LOG_INFO("http service:get service, protocol = " << protocol << " ,appkey = " << appkey); + int32_t ret = DiscoveryService::GetInstance()->GetSrvListAndCacheSize(list_and_cache, + protocol, appkey); + if (SUCCESS != ret) { + NS_LOG_ERROR("Run mns get srvlist and buffer failed, ret = " << ret); + } + return ret; +} + +int32_t HttpService::RepalceServlistAndCache(const ServicePtr &service) { + NS_LOG_INFO("http service:replace service."); + int32_t ret = DiscoveryService::GetInstance()->RepalceSrvlist(service); + if (SUCCESS != ret) { + NS_LOG_ERROR("Run mns replace srvlist and cache failed, ret = " << ret); + } + return ret; +} + +int32_t HttpService::ServiceListByProtocol(const ProtocolRequest &req, + ProtocolResponse &_return) { + NS_LOG_INFO("http service GET servicelist."); + + bool enable_swimlane2 = false; + + boost::shared_ptr service_channel = boost::make_shared(); + service_channel->SetAllChannel(false); + service_channel->SetBankboneChannel(false); + service_channel->SetOriginChannel(false); + service_channel->SetSwimlaneChannel(enable_swimlane2); + + int32_t ret = DiscoveryService::GetInstance()->DiscGetSrvList(_return + .servicelist, req,service_channel); + NS_LOG_INFO("Http ServiceListByProtocol size = " << _return.servicelist.size + ()); + _return.errcode = ret; + if (SUCCESS != ret) { + NS_LOG_ERROR("Http ServiceListByProtocol failed, and ret = " << ret); + } + return ret; +} + +void HttpService::HttpHandler(struct evhttp_request *http_request, void *info) { + + if (NULL == http_request || NULL == info) { + NS_LOG_ERROR("the http handler para is null"); + return; + } + u_char *req_buf; + req_buf = EVBUFFER_DATA(http_request->input_buffer); + const char *decode_uri = evhttp_request_uri(http_request); + char *url = evhttp_decode_uri(decode_uri); + NS_LOG_DEBUG("the remote host is: " << http_request->remote_host + << ", input url method = " << url + << ",the req data = " << req_buf); + + struct evbuffer *buf = evbuffer_new();//response buffer + if (NULL == buf) { + NS_LOG_ERROR("Failed to create response buffer"); + return; + } + + HttpService *httpService = (HttpService *) info; + int http_err_code = HTTP_OK; + if (EVHTTP_REQ_GET == http_request->type) { + http_err_code = httpService->Response2RequestByGet(url, buf); + } else if (EVHTTP_REQ_POST == http_request->type) { + http_err_code = httpService->Response2RequestByPost(url, req_buf, buf); + } + evhttp_send_reply(http_request, + http_err_code, + "decode the json data ok!", + buf); + if (NULL != buf) { + evbuffer_free(buf); + } + SAFE_FREE(url); +} + +int32_t HttpService::ServiceListActionByPost(const int service_method, + const u_char *req_buf, + struct evbuffer *buf) { + int http_err_code = HTTP_RESPONSE_OK; + ServicePtr service(new getservice_res_param_t()); + int ret_code = ParseServiceDataFromHttp((const char *) req_buf, service); + if (SUCCESS != ret_code) { + NS_LOG_ERROR("Failed to parse data, ret = " << ret_code); + evbuffer_add_printf(buf, "request param error"); + return HTTP_PARAM_ERROR; + } + + switch (service_method) { + case ADD_SERVICE: { + NS_LOG_INFO("http add method"); + break; + } + case UPDATE_SERVICE: { + if (SUCCESS != UpdateServiceInCache(service)) { + NS_LOG_ERROR("http-update in agent failed"); + http_err_code = HTTP_INNER_ERROR; + } + break; + } + case DELETE_SERVICE: { + NS_LOG_INFO("http delete method"); + http_err_code = HTTP_NOT_SUPPORT; + break; + } + case GET_SERVICE: { + ServListAndCache list_and_cache; + if (SUCCESS != GetServListAndCacheSize(list_and_cache, + service->protocol, + service->remoteAppkey)) { + NS_LOG_ERROR("http-get in agent failed"); + http_err_code = HTTP_INNER_ERROR; + } else { + std::string response = ""; + int ret = ServListAndCache2Json(list_and_cache, response); + if (SUCCESS != ret) { + NS_LOG_ERROR("ServListAndCache(response) to str failed, ret = " << ret); + http_err_code = HTTP_INNER_ERROR; + } else { + evbuffer_add_printf(buf, response.c_str()); + } + } + break; + } + case REPLACE_SERVICE: { + if (SUCCESS != RepalceServlistAndCache(service)) { + NS_LOG_ERROR("http-replace in agent failed"); + http_err_code = HTTP_INNER_ERROR; + } + break; + } + default: { + http_err_code = HTTP_NOT_SUPPORT; + NS_LOG_ERROR("unkown service method, disgardless"); + break; + } + } + return http_err_code; + +} + +int32_t HttpService::IsHealthy() { + if (IdcUtil::IsInIdcs(CXmlFile::GetStrPara(CXmlFile::LocalIp))) { + return HTTP_RESPONSE_OK; + } + return HTTP_INNER_ERROR; + +} +int32_t HttpService::EncodeHealthyInfo(std::string &res) { + + char *out; + int ret = HTTP_RESPONSE_OK; + int ret_json = -1; + cJSON *json = cJSON_CreateObject(); + if (!json) { + NS_LOG_ERROR("json is NULL, create json_object failed."); + return FAILURE; + } + ret = IsHealthy(); + cJSON_AddNumberToObject(json, "ret", ret); + cJSON_AddStringToObject(json, "retMsg", "success"); + cJSON_AddStringToObject(json, "endpoint", CXmlFile::GetAppenv()->GetStrEnv().c_str()); + out = cJSON_Print(json); + if(NULL!= out){ + res = out; + SAFE_FREE(out); + cJSON_Delete(json); + NS_LOG_INFO("EncodeHealthyInfo success = " + << res << "local ip = " << CXmlFile::GetAppenv()->GetStrEnv()); + return SUCCESS; + }else{ + cJSON_Delete(json); + res = HTTP_RESPONSE_NULL; + NS_LOG_ERROR("EncodeHealthyInfo failed = " + << res << "local ip = " + << CXmlFile::GetAppenv()->GetStrEnv()); + return FAILURE; + } +} + +//获取监控信息reqBuf无需做空判断处理 +int32_t HttpService::MonitorActionByPost(int service_method, + const u_char *req_buf, + struct evbuffer *buf) { + int http_err_code = HTTP_RESPONSE_OK; + switch (service_method) { + case GET_MONITOR_SERVICE: { + std::string response = ""; + int32_t ret = MonitorCollector::GetInstance()->GetCollectorMonitorInfo(response); + if (SUCCESS != ret) { + NS_LOG_ERROR("Get collectorMonitorInfo failed, ret = " << ret); + http_err_code = HTTP_INNER_ERROR; + } else { + evbuffer_add_printf(buf, response.c_str()); + } + break; + } + default:http_err_code = HTTP_INNER_ERROR; + break; + } + return http_err_code; +} + +/* + * response to HTTP requests + * 缺省为服务列表操作,后续扩展其它 + */ +int32_t HttpService::Response2RequestByPost(const char *url, + const u_char *req_buf, + struct evbuffer *buf) { + + int serviceMethod = GetServiceMethodFromHttp(url); + switch (serviceMethod) { + + case GET_MONITOR_SERVICE: { + return MonitorActionByPost(serviceMethod, req_buf, buf); + } + case HEALTHY_CHECK: { + return HealthyCheckByPost(serviceMethod, req_buf, buf); + } + default: { + return ServiceListActionByPost(serviceMethod, req_buf, buf); + } + } + return HTTP_RESPONSE_OK; +} + +/* + * ServListAndCache struct to Json + */ +int32_t HttpService::ServListAndCache2Json(const ServListAndCache &list_and_cache, + std::string &response) { + cJSON *json = cJSON_CreateObject(); + char *out; + if (!json) { + NS_LOG_ERROR("json is NULL, create json_object failed."); + return FAILURE; + } + cJSON_AddNumberToObject(json, "origin_servlist_size", list_and_cache.origin_servlist_size); + cJSON_AddNumberToObject(json, "filte_servlist_size", list_and_cache.filte_servlist_size); + cJSON_AddNumberToObject(json, "origin_cache_size", list_and_cache.origin_cache_size); + cJSON_AddNumberToObject(json, "filte_cache_size", list_and_cache.filte_cache_size); + int ret = Service2Json(list_and_cache.origin_servicelist, json, "origin_servicelist"); + if (SUCCESS != ret) { + NS_LOG_ERROR("Failed to change origin_servicelist to json, ret = " << ret); + cJSON_Delete(json); + return FAILURE; + } + ret = Service2Json(list_and_cache.filte_servicelist, json, "filte_servicelist"); + if (SUCCESS != ret) { + NS_LOG_ERROR("Failed to change filte_servicelist to json, ret = " << ret); + cJSON_Delete(json); + return FAILURE; + } + out = cJSON_Print(json); + response = out; + SAFE_FREE(out); + cJSON_Delete(json); + boost::trim(response); + if (response.empty()) { + NS_LOG_ERROR("json to str failed, the response json is empty."); + return FAILURE; + } + return SUCCESS; +} +/* + * SGService to json + */ +int32_t HttpService::Service2Json(const std::vector &servicelist, + cJSON *json, + const char *type) { + cJSON *all_srvlist_json = cJSON_CreateArray(); + if (!all_srvlist_json) { + NS_LOG_ERROR("all_srvlist_json is NULL, create json_object failed."); + return FAILURE; + } + for (std::vector::const_iterator iter = servicelist.begin(); + iter != servicelist.end(); ++iter) { + cJSON *item = cJSON_CreateObject(); + int ret = SGService2Json(*iter, item); + if (SUCCESS != ret) { + NS_LOG_ERROR("SGService2Json failed, ret = " << ret); + return FAILURE; + } + cJSON_AddItemToArray(all_srvlist_json, item); + } + cJSON_AddItemToObject(json, type, all_srvlist_json); + return SUCCESS; +} + +int32_t HttpService::SGService2Json(const SGService &oservice, cJSON *root) { + cJSON_AddItemToObject(root, "appkey", cJSON_CreateString(oservice.appkey.c_str())); + cJSON_AddItemToObject(root, "version", cJSON_CreateString(oservice.version.c_str())); + cJSON_AddItemToObject(root, "ip", cJSON_CreateString(oservice.ip.c_str())); + cJSON_AddNumberToObject(root, "port", oservice.port); + cJSON_AddNumberToObject(root, "weight", oservice.weight); + cJSON_AddNumberToObject(root, "status", oservice.status); + cJSON_AddNumberToObject(root, "role", oservice.role); + cJSON_AddNumberToObject(root, "env", CXmlFile::GetAppenv()->GetIntEnv()); + cJSON_AddNumberToObject(root, "lastUpdateTime", oservice.lastUpdateTime); + //后续添加,注意有可能没有 + cJSON_AddNumberToObject(root, "fweight", oservice.fweight); + cJSON_AddNumberToObject(root, "serverType", oservice.serverType); + + int32_t heartbeatSupport = oservice.heartbeatSupport; + cJSON_AddNumberToObject(root, "heartbeatSupport", heartbeatSupport); + cJSON_AddItemToObject(root, "protocol", cJSON_CreateString(oservice.protocol.c_str())); + + cJSON *item = cJSON_CreateObject(); + if (NULL == item) { + NS_LOG_ERROR("cJson failed to CreateObject. Item is serviceInfo"); + return FAILURE; + } + int ret = JsonZkMgr::cJson_AddServiceObject(oservice.serviceInfo, root, + item, std::string("serviceInfo")); + if (0 != ret) { + NS_LOG_ERROR("failed to add serviceName to root"); + return FAILURE; + } + + return SUCCESS; +} + +int32_t HttpService::GetKeyValueFromUrl(const std::string &url, + const std::string &key, + std::string &value) { + int len = url.length(); + size_t pos = url.find(key); + if (std::string::npos != pos) { + for (int i = pos + key.length(); i < len && '&' != url[i]; ++i) { + value += url[i]; + } + if (value.empty()) { + NS_LOG_DEBUG("key: " << key << " is empty."); + return FAILURE; + } + } else { + NS_LOG_DEBUG("key: " << key << " does not exist"); + return FAILURE; + } + return SUCCESS; +} + +int32_t HttpService::GetServiceParamFromUrl(const std::string &url, + ProtocolRequest ¶ms) { + NS_LOG_DEBUG("the MNS url is: " << url); + std::string tmp_url = url; + boost::trim(tmp_url); + size_t pos = tmp_url.find("/api/servicelist?"); + size_t appkey_pos = tmp_url.find("appkey="); + size_t protocol_pos = tmp_url.find("protocol="); + if (std::string::npos != pos && std::string::npos != appkey_pos + && std::string::npos != protocol_pos) { + std::string env = ""; + int ret = GetKeyValueFromUrl(tmp_url, "env=", env); + if (SUCCESS == ret) { + if (env == CXmlFile::GetAppenv()->GetStrEnv()) { + NS_LOG_DEBUG("env is " << env); + } else { + NS_LOG_ERROR("env:" << env << " is different from local env:" << CXmlFile::GetAppenv()->GetStrEnv()); + return ERR_INVALID_ENV; + } + } else { + NS_LOG_WARN("env error, ret = " << ret); + } + std::string appkey = ""; + ret = GetKeyValueFromUrl(tmp_url, "appkey=", appkey); + if (SUCCESS == ret) { + params.remoteAppkey = appkey; + } else { + NS_LOG_ERROR("appkey error, ret = " << ret); + return HTTP_PARAM_ERROR; + } + std::string protocol = ""; + ret = GetKeyValueFromUrl(tmp_url, "protocol=", protocol); + if (SUCCESS == ret) { + params.protocol = protocol; + } else { + NS_LOG_ERROR("protocol error, ret = " << ret); + return HTTP_PARAM_ERROR; + } + std::string hostname = ""; + ret = GetKeyValueFromUrl(tmp_url, "hostname=", hostname); + if (SUCCESS == ret) { + NS_LOG_INFO("hostname is " << hostname); + } else { + NS_LOG_WARN("hostname error, ret = " << ret); + } + std::string localip = ""; + ret = GetKeyValueFromUrl(tmp_url, "localip=", localip); + if (SUCCESS == ret) { + NS_LOG_INFO("localip is " << localip); + } else { + NS_LOG_WARN("localip error ,ret = " << ret); + } + } else { + NS_LOG_ERROR("params are empty."); + return HTTP_PARAM_ERROR; + } + return HTTP_OK; +} + +int32_t HttpService::Response2RequestByGet(const char *url, + struct evbuffer *buf) { + ProtocolRequest req; + int http_code = GetServiceParamFromUrl(url, req); + if (HTTP_OK != http_code) { + NS_LOG_ERROR("http response failed, err_code = " << http_code); + return http_code; + } + std::vector result; + req.__set_remoteAppkey(req.remoteAppkey); + req.__set_protocol(req.protocol); + ProtocolResponse _return; + int ret = ServiceListByProtocol(req, _return); + if (SUCCESS != ret) { + NS_LOG_ERROR("Failed to get servicelist by http, ret = " << ret); + return HTTP_INNER_ERROR; + } + std::string response = ""; + ret = ProtocolResponse2Json(_return, response); + if (SUCCESS != ret) { + NS_LOG_ERROR("Failed to ProtocolResponse2Json, ret = " << ret); + return HTTP_INNER_ERROR; + } + evbuffer_add_printf(buf, response.c_str()); + //NS_LOG_INFO("response : " << response); + return http_code; +} + +int32_t HttpService::HealthyCheckByPost(int serviceMethod, const u_char + *req_buf, struct evbuffer *buf) { + + NS_LOG_INFO("the healthy check by post"); + int http_err_code = HTTP_RESPONSE_OK; + std::string response = ""; + if (SUCCESS != EncodeHealthyInfo(response)) { + NS_LOG_ERROR("Get collectorMonitorInfo failed, ret = "); + http_err_code = HTTP_INNER_ERROR; + } else { + evbuffer_add_printf(buf, response.c_str()); + } + return http_err_code; +} + +int32_t HttpService::ProtocolResponse2Json(const ProtocolResponse &res, + std::string &response) { + cJSON *parent = cJSON_CreateObject(); + char *out; + if (NULL == parent) { + NS_LOG_ERROR("Failed to create json object:parent."); + return FAILURE; + } + cJSON *child = cJSON_CreateObject(); + if (NULL == child) { + NS_LOG_ERROR("Failed to create json object:child."); + return FAILURE; + } + cJSON_AddNumberToObject(parent, "ret", HTTP_RESPONSE_OK); + cJSON_AddStringToObject(parent, "retMsg", "success"); + int ret = Service2Json(res.servicelist, child, "serviceList"); + if (SUCCESS != ret) { + NS_LOG_ERROR("Failed to parse service, ret = " << ret); + cJSON_Delete(parent); + return FAILURE; + } + + cJSON_AddItemToObject(parent, "data", child); + out = cJSON_Print(parent); + response = out; +// NS_LOG_INFO("the response service list is "<< response); + boost::trim(response); + if (response.empty()) { + NS_LOG_ERROR("json to str failed, the response json is empty."); + SAFE_FREE(out); + cJSON_Delete(parent); + return FAILURE; + } + SAFE_FREE(out); + cJSON_Delete(parent); + return SUCCESS; +} + +//todo:monitor子方法后续细分后解析 +int32_t HttpService::DecodeMonitorUrlMethod(const std::string &url) { + NS_LOG_INFO("the monitor url is:" << url); + + return GET_MONITOR_SERVICE; + +} + +int32_t HttpService::DecodeMnsUrlMethod(const std::string &url) { + + NS_LOG_INFO("the Mns Url is:" << url); + std::string strtmp = ""; + strtmp.assign(url, strlen("/api/mns/provider/"), url.length()); + NS_LOG_INFO("find method:" << strtmp); + if (SUCCESS == strtmp.compare("add")) { + return ADD_SERVICE; + } else if (SUCCESS == strtmp.compare("delete")) { + return DELETE_SERVICE; + } else if (SUCCESS == strtmp.compare("update")) { + return UPDATE_SERVICE; + } else if (SUCCESS == strtmp.compare("get")) { + return GET_SERVICE; + } else if (SUCCESS == strtmp.compare("monitorinfo")) {//名字修改monitor + return GET_MONITOR_SERVICE; + } else if (SUCCESS == strtmp.compare("replace")) {//强制替换列表 + return REPLACE_SERVICE; + } else { + NS_LOG_ERROR("unkown http sub method"); + } + return INVALID_METHOD; + +} +int32_t HttpService::DecodeHealthyMethod(const std::string &url) { + NS_LOG_INFO("the monitor url is:" << url); + + return HEALTHY_CHECK; + +} + +int32_t HttpService::GetServiceMethodFromHttp(const char *input_method) { + if (NULL == input_method) { + NS_LOG_ERROR("the inputMethod is null"); + return INVALID_METHOD; + } + std::string input_str = input_method; + NS_LOG_INFO("Input str = " << input_str); + std::size_t pos_mns = input_str.find("/api/mns/provider/"); + if (std::string::npos != pos_mns && 0 == pos_mns) { + return DecodeMnsUrlMethod(input_str); + } + std::size_t pos_mon = input_str.find("/api/monitor"); + if (std::string::npos != pos_mon && 0 == pos_mon) { + return DecodeMonitorUrlMethod(input_str); + } + std::size_t pos_hlh = input_str.find("/api/healthy"); + if (std::string::npos != pos_hlh && 0 == pos_hlh) { + return DecodeHealthyMethod(input_str); + } + return INVALID_METHOD; +} +void HttpService::StartHttpServer() { + + NS_LOG_INFO("http server init"); + http_service_loop_ = http_service_thread_.startLoop(); + http_service_loop_->runInLoop(boost::bind(&HttpService::StartService, this)); + +} + + + + + + diff --git a/sg_agent/src/mns/http_service.h b/sg_agent/src/mns/http_service.h new file mode 100644 index 0000000..fae50a2 --- /dev/null +++ b/sg_agent/src/mns/http_service.h @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +#ifndef SG_AGENT_HTTP_SERVICE_H +#define SG_AGENT_HTTP_SERVICE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "cJSON.h" +#include "naming_service_types.h" +#include "inc_comm.h" +#include "muduo/net/EventLoop.h" +#include "muduo/net/EventLoopThread.h" +#include "boost/bind.hpp" +#include "json_data_tools.h" +#include "base_mns_consts.h" +#include "base_mns_define.h" +#include "naming_common_types.h" +#include "naming_data_types.h" + + +#define LOCAL_IP 32 +#define LOCAL_MASK 64 + +namespace meituan_mns { + +typedef boost::shared_ptr ServicePtr; + + +class HttpService { + private: + HttpService() : http_service_loop_(NULL), http_service_thread_ + (boost::function(), "sg_agent") {}; + public: + ~HttpService(); + static HttpService *GetInstance(); + + void StartService(); + void StopService() {}; + void StartHttpServer(); + + + private: + /** + * 更新缓存服务列表 + * @param service + * + * @return int32_t + * + */ + int32_t UpdateServiceInCache(const ServicePtr &service); + /** + * 从缓存获取服务列表 + * @param service + * + * @return int32_t + * + */ + int32_t GetServListAndCacheSize(ServListAndCache &list_and_cache, + const std::string &protocol, + const std::string &appkey); + /** + * 从缓存更新服务列表 + * @param service + * + * @return int32_t + * + */ + int32_t RepalceServlistAndCache(const ServicePtr &service); + /** + * 获取http请求方法类型 + * @param input_method + * + * @return int32_t + * + */ + int32_t GetServiceMethodFromHttp(const char *input_method); + /** + * 从url获取参数 + * @param url,params + * + * @return int32_t + * + */ + int32_t GetServiceParamFromUrl(const std::string &url, + ProtocolRequest ¶ms); + /** + * 从url获取剑指key + * @param url,key,value + * + * @return int32_t + * + */ + int32_t GetKeyValueFromUrl(const std::string &url, + const std::string &key, + std::string &value); + /** + * get方法响应 + * @param url,buf + * + * @return int32_t + * + */ + int32_t Response2RequestByGet(const char *url, struct evbuffer *buf); + /** + * post方法响应 + * @param url,req_buf,buf + * + * @return int32_t + * + */ + int32_t Response2RequestByPost(const char *url, const u_char *req_buf, + struct evbuffer *buf); + + int32_t Service2Json(const std::vector &servicelist, + cJSON *json, + const char *type); + + int32_t ServListAndCache2Json(const ServListAndCache &list_and_cache, + std::string &response); + + int32_t ServiceListActionByPost(const int serviceMethod, + const u_char *req_buf, + struct evbuffer *buf); + + int32_t ServiceListByProtocol(const ProtocolRequest &req, + ProtocolResponse &_return); + + int32_t SGService2Json(const SGService &oservice, cJSON *root); + + int32_t DecodeMonitorUrlMethod(const std::string &url); + + int32_t DecodeMnsUrlMethod(const std::string &url); + + int32_t DecodeHealthyMethod(const std::string &url); + + int32_t ProtocolResponse2Json(const ProtocolResponse &res, + std::string &response); + + int32_t ParseNodeData(cJSON *root, SGService &service_info); + + int32_t ParseServiceDataFromHttp(const char *post_data, ServicePtr &service); + + int32_t MonitorActionByPost(int serviceMethod, const u_char *req_buf, + struct evbuffer *buf); + int32_t HealthyCheckByPost(int serviceMethod, const u_char *req_buf, + struct evbuffer *buf); + int32_t EncodeHealthyInfo(std::string &res); + + static void HttpHandler(struct evhttp_request *http_request, void *info); + + int32_t IsHealthy(); + + static HttpService *http_service_; + + static muduo::MutexLock http_service_lock_; + + muduo::net::EventLoopThread http_service_thread_; + + muduo::net::EventLoop *http_service_loop_; + +}; + +} + +#endif //SG_AGENT_HTTP_SERVICE_H diff --git a/sg_agent/src/mns/mnsc_client.cc b/sg_agent/src/mns/mnsc_client.cc new file mode 100644 index 0000000..2743429 --- /dev/null +++ b/sg_agent/src/mns/mnsc_client.cc @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +#include "mnsc_client.h" +#include "naming_service_types.h" +#include "config_loader.h" +#include "discovery_service.h" +#include "route_rule.h" +namespace meituan_mns { + +MnscClient *MnscClient::mnsc_client_ = NULL; +muduo::MutexLock MnscClient::mnsc_client_lock_; +const int MNSC_DEFAULT_SLEEPTIME = 30000; + +MnscClient::MnscClient() : + mnsc_appkey_(CXmlFile::GetStrPara(CXmlFile::MNSCacheAppkey)), + retry_times_(CXmlFile::GetI32Para(CXmlFile::RetryTimes)), + timeout_(CXmlFile::GetI32Para(CXmlFile::MnscTimeOut)) {} + +MnscClient::~MnscClient() {} + +MnscClient *MnscClient::GetInstance() { + if (NULL == mnsc_client_) { + muduo::MutexLockGuard lock(mnsc_client_lock_); + if (NULL == mnsc_client_) { + mnsc_client_ = new MnscClient(); + } + } + return mnsc_client_; +} + +int32_t MnscClient::GetMnscThriftClient(MnscThriftClientPtr +&mnsc_thrift_client) { + std::vector service_list; + int32_t ret = GetThriftServiceList(mnsc_appkey_, service_list); + if (SUCCESS != ret) { + NS_LOG_WARN("GetThriftServiceList failed,ret = "<CreateThriftClient(service_list[rand_index].ip, + service_list[rand_index].port, + timeout_); + if (SUCCESS == ret) { + return SUCCESS; + } + rand_index = (rand_index + 1) % size; + } while(rand_index != begin_index); + + return FAILURE; +} + +int32_t MnscClient::GetMnscCache(std::vector &service_list, const GetMnsCacheParams ¶ms) { + MnscThriftClientPtr mnsc_thrift_client = + boost::make_shared >(); + int32_t ret = GetMnscThriftClient(mnsc_thrift_client); + if (SUCCESS != ret) { + NS_LOG_WARN("Failed to get mnsc thrift client."); + return ret; + } + MNSResponse mnscache_res; + try { + //调用mnscache接口 + if ("thrift" == params.protocol) { + mnsc_thrift_client->GetClient()->getMNSCache(mnscache_res, params.appkey, params.version, params.env); + } else if ("http" == params.protocol) { + mnsc_thrift_client->GetClient()->getMNSCacheHttp(mnscache_res, params.appkey, params.version, params.env); + } else { + NS_LOG_ERROR("invalid protocol: " << params.protocol); + } + //提取返回的服务列表 + if (meituan_mns::MNSC_OK == mnscache_res.code) { + service_list = mnscache_res.defaultMNSCache; + NS_LOG_DEBUG("getMNSCache ok! appkey : " << params.appkey + << ", serviceList size is : " << service_list.size() + << ", env is : " << params.env); + } else { + NS_LOG_ERROR("getMNSCache wrong errcode. appkey : " << params.appkey + << ", env is : " << params.env + << ", errCode : " << mnscache_res.code); + } + } catch (TException &e) { + NS_LOG_ERROR("getMNSCache catch error! msg: " << e.what() + << ", serviceList size is : " << service_list.size() + << ", env is : " << params.env + << ", appkey : " << params.appkey); + return ERR_MNSC_GET_MNSCACHE; + } + return mnscache_res.code; +} + +int32_t MnscClient::GetServicelistFromMnsc(std::vector &service_list, const GetMnsCacheParams ¶ms) { + + timeval tvalStart; + timeval tvalEnd; + long deltaTime; + gettimeofday(&tvalStart, NULL); + uint32_t times = 0; + int32_t ret = 0; + do { + //访问MNS_Cache + ret = GetMnscCache(service_list, params); + if (meituan_mns::MNSC_OK == ret) { + //getCache正常返回 + break; + } else if (meituan_mns::MNSC_UPDATING == ret) { + //getCache返回500, 表示MNSCache正在watcher更新, sleep重试一次 + gettimeofday(&tvalEnd, NULL); + deltaTime = (tvalEnd.tv_sec - tvalStart.tv_sec) + * 1000000L + + (tvalEnd.tv_usec - tvalStart.tv_usec); + usleep(MNSC_DEFAULT_SLEEPTIME); + } else { + //其他错误,表示MNSCache异常,重试3次, + //若都失败则退出循环,直连ZK再次getServerList + ++times; + if (times < meituan_mns::MNSC_RETRY_TIME) { + NS_LOG_WARN("getMNSCache fail , ret code : " + << ret + << ", appkey : " << params.appkey + << ", need to retry, count : " << times); + continue; + } else { + break; + } + } + } while (retry_times_ > times); + return ret; +} +int32_t MnscClient::GetThriftServiceList(const std::string &appkey, std::vector &service_list) { + boost::shared_ptr service_channel = boost::make_shared(); + service_channel->SetAllChannel(false); + service_channel->SetBankboneChannel(false); + service_channel->SetOriginChannel(false); + service_channel->SetSwimlaneChannel(false); + + ProtocolRequest req; + req.__set_localAppkey("sgAgent"); + req.__set_protocol("thrift"); + req.__set_remoteAppkey(appkey); + + int32_t ret = DiscoveryService::GetInstance()->DiscGetSrvList(service_list, req, service_channel); + if (SUCCESS != ret) { + NS_LOG_ERROR("ERR getService list failed, ret: " + << ret << ", appkey : " << appkey); + return ERR_FAILEDTOGETCONFSERVLIST; + } + RouteRule::FilterUnAlive(service_list); + if (service_list.empty()) { + NS_LOG_ERROR("ERR service list return null "); + return ERR_SERVICELIST_NULL; + } + ret = RouteRule::FilterWeight(service_list, IdcThresHold); + if (SUCCESS != ret) { + NS_LOG_DEBUG("result from IDC filte is empty"); + ret = meituan_mns::RouteRule::FilterWeight(service_list, RegionThresHold); + if (SUCCESS != ret) { + NS_LOG_WARN("result from Region filte is empty"); + } + } + return SUCCESS; +} + +} // namespace meituan_mns diff --git a/sg_agent/src/mns/mnsc_client.h b/sg_agent/src/mns/mnsc_client.h new file mode 100644 index 0000000..9d568a8 --- /dev/null +++ b/sg_agent/src/mns/mnsc_client.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +#ifndef SG_AGENT_MNSC_CLIENT_H +#define SG_AGENT_MNSC_CLIENT_H +#include "zk_invoke_param.h" +#include +#include "MNSCacheService.h" +#include "mnsc_data_types.h" +#include "thrift_client.h" +#include + +namespace meituan_mns { + + +typedef boost::shared_ptr > MnscThriftClientPtr; + +class MnscClient { + public: + MnscClient(); + ~MnscClient(); + static MnscClient* GetInstance(); + /** + * 从MNS Cache服务获取服务列表 + * @param service_list + * @param params + * @return + */ + int32_t GetServicelistFromMnsc(std::vector &service_list, + const GetMnsCacheParams& params); + + private: + /** + * MNS Cache rpc接口 + * @param service_list, params + * @return + */ + int32_t GetMnscCache(std::vector &service_list, + const GetMnsCacheParams& params); + /** + * 获取MNSC服务节点列表 + * @param service_list + * @return + */ + int32_t GetMnscServiceList(std::vector &service_list); + + + /** + * + * @return + */ + int32_t GetMnscThriftClient(MnscThriftClientPtr &mnsc_thrift_client); + + + /** + * + * @param appkey,service_list + * @return int32_t + */ + int32_t GetThriftServiceList(const std::string &appkey, std::vector &service_list); + + private: + uint32_t retry_times_; + int32_t timeout_; + std::string mnsc_appkey_; + + static MnscClient *mnsc_client_; + static muduo::MutexLock mnsc_client_lock_; + +}; + + + +} // namespace meituan_mns + +#endif //SG_AGENT_MNSC_CLIENT_H diff --git a/sg_agent/src/mns/registry_base.h b/sg_agent/src/mns/registry_base.h new file mode 100644 index 0000000..7575490 --- /dev/null +++ b/sg_agent/src/mns/registry_base.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef SRC_MNS_REGISTRY_BASE_H_ +#define SRC_MNS_REGISTRY_BASE_H_ +#include +#include +#include +#include "base_consts.h" +#include "naming_service_types.h" + +namespace meituan_mns { + +class Registry { + + public: + Registry() {} + ~Registry() {} + /** + * 提供注册操作,用于异常终止及撤销 + * @param + * + * @return + * + */ + virtual const uint32_t RegistryStart(const SGService &oService, + const int32_t ®_action)=0; + virtual const uint32_t RegistryStop(const SGService &oService)=0; + + /** + * 提供下线操作,用于异常终止及撤销 + * @param + * + * @return + * + */ + virtual const uint32_t UnRegistryStart(const SGService &oService, const int32_t ®_action)=0; + virtual const uint32_t UnRegistryStop(const SGService &oService)=0; + + private: + protected: +}; +} + +#endif // SRC_MNS_REGISTRY_BASE_H_ diff --git a/sg_agent/src/mns/registry_service.cc b/sg_agent/src/mns/registry_service.cc new file mode 100644 index 0000000..3c875c7 --- /dev/null +++ b/sg_agent/src/mns/registry_service.cc @@ -0,0 +1,689 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "registry_service.h" +#include "registry_strategy.h" +#include "naming_common_types.h" +#include "base_consts.h" +#include "base_mns_consts.h" +#include "base_errors_consts.h" +#include "log4cplus.h" +#include "zk_client_pool.h" +#include "json_data_tools.h" +#include "zk_path_tools.h" +#include + + +namespace meituan_mns { + +RegistryService *RegistryService::registry_service_ = NULL; +muduo::MutexLock RegistryService::registry_service_lock_; + +RegistryServiceBatch *RegistryServiceBatch::registry_service_batch_ = NULL; +muduo::MutexLock RegistryServiceBatch::registry_service_batch_lock_; + + + +RegistryService* RegistryService::GetInstance() { + if (NULL == registry_service_) { + muduo::MutexLockGuard lock(registry_service_lock_); + if (NULL == registry_service_) { + registry_service_ = new RegistryService(); + } + } + return registry_service_; +} + + +RegistryServiceBatch* RegistryServiceBatch::GetInstance() { + if (NULL == registry_service_batch_) { + muduo::MutexLockGuard lock(registry_service_batch_lock_); + if (NULL == registry_service_batch_) { + registry_service_batch_ = new RegistryServiceBatch(); + } + } + return registry_service_batch_; +} + +Registry* RegistryFactory::CreateRegistry(RegistryType type) { + return RegistryService::GetInstance(); + switch (CXmlFile::GetI32Para(CXmlFile::RegistryEntry)) { + case kAddReg: { + return RegistryService::GetInstance(); + } + case kBatchReg: { + return RegistryServiceBatch::GetInstance(); + } + default: { + break; + } + } + return NULL; +} + +const uint32_t RegistryService::RegistryStart(const SGService &oService, + const int32_t ®_action) { + int32_t ret = register_strategy_.IsAllowedRegistry(oService); + if (SUCCESS != ret) { + NS_LOG_ERROR("its not allowed to registry"); + return FAILURE; + } + SGServicePtr service_ptr = boost::make_shared(oService); + ret = register_strategy_.CheckAllowedProtocolRegistry(service_ptr); + if (SUCCESS != ret) { + return ret; + } + RegParamPtr regParam_ptr(new regist_req_param_t()); + regParam_ptr->sgservice = *service_ptr; + regParam_ptr->uptCmd = reg_action; + regParam_ptr->regCmd = RegistCmd::REGIST; + ret = RegistryAction(regParam_ptr,reg_action); + if (SUCCESS != ret){ + NS_LOG_ERROR("success registry, appkey: "<< service_ptr->appkey<<"; ip = " + <ip); + return FAILURE; + } + NS_LOG_INFO("success registry, appkey: "<< service_ptr->appkey<<"; ip = " + << service_ptr->ip); + return SUCCESS; +} + +const uint32_t RegistryService::UnRegistryStart(const SGService &oService, + const int32_t ®_action){ + + if (SUCCESS != register_strategy_.IsAllowedRegistry(oService)) { + NS_LOG_ERROR("its not allowed to unregistry"); + return FAILURE; + } + uint32_t round_index = 0; + srand((unsigned) time(NULL)); + SGServicePtr servicePtr(new SGService(oService)); + servicePtr->status = fb_status::DEAD; + RegParamPtr regParamPtr(new regist_req_param_t); + regParamPtr->sgservice = *servicePtr; + regParamPtr->uptCmd = reg_action; + regParamPtr->regCmd = RegistCmd::UNREGIST; + + if (SUCCESS == RegistryAction(regParamPtr,reg_action)){ + NS_LOG_INFO("success un-registry, appkey: "<appkey<<"; ip : " + <ip); + return SUCCESS; + } else{ + NS_LOG_ERROR("success un-registry, appkey: "<appkey<<"; ip : " + <ip); + return FAILURE; + } + +} + +int32_t RegistryService::RegistryServiceToZk(const SGService &oservice, + RegistCmd::type regCmd, + int uptCmd) { + int32_t ret = FAILURE; + std::string zk_provider_path= ""; + ret = agent_path_.GenRegisterZkPath(zk_provider_path, oservice.appkey, + oservice.protocol, oservice.serverType); + if (SUCCESS != ret) { + NS_LOG_INFO("_gen registry path fail! appkey = " + << oservice.appkey + << ", protocol = " << oservice.protocol + << ", serverType = " << oservice.serverType); + return ret; + } + ZkExistsRequestPtr zk_exists_req(new ZkExistsRequest()); + zk_exists_req->path = zk_provider_path; + zk_exists_req->watch = 0; + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)-> + ZkExists(zk_exists_req); + + if (ZNONODE == ret || ret == FAILURE) { + NS_LOG_INFO("appkey not exist.zkpath:" << zk_provider_path + << ", ip : " << oservice.ip + << ", port : " << oservice.port + << ", or zk handle fail ret: " << ret); + if(0 >= ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)-> + ZkPathCreateRecursivly(zk_provider_path)){ + NS_LOG_ERROR("recursivly create zk node failed,zk_path: " + << zk_provider_path); + return FAILURE; + } + } + std::string zk_path = ""; + zk_path = zk_provider_path + "/" + oservice.ip + ":" + + boost::lexical_cast(oservice.port); + + std::string strJson = ""; + zk_exists_req->path = zk_path; + zk_exists_req->watch = 0; + + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)->ZkExists(zk_exists_req); + if (ZNONODE == ret) { + ret = RegistryCreateZkNode(oservice, zk_path, regCmd, uptCmd); + if (SUCCESS != ret) { + NS_LOG_ERROR("create zk node failed,zk_path: " << zk_path); + return ret; + } + } else if (ZOK == ret) { + ret = RegistryUpdateZkNode(oservice, zk_path, regCmd, uptCmd); + if (SUCCESS != ret) { + NS_LOG_ERROR("update zk node failed,zk_path: " << zk_path); + return ret; + } + } else if (ZNOAUTH == ret) { + NS_LOG_INFO("ZNOAUTH in registerService. ret = " << ret); + return ret; + } else { + NS_LOG_INFO("ERR other error: " << ret << " in registerService"); + return ret; + } + ret = UpdateLastModifiedTime(oservice.appkey, zk_provider_path); + if (SUCCESS != ret) { + NS_LOG_ERROR("last modified time updated failed"); + return ret; + } + //todo:add the servicename registe + return SUCCESS; +} +int32_t RegistryService::RegistryServiceNameCreate(const std::string& +service_name,const std::string& path){ + int32_t ret = FAILURE; + std::string service_json = ""; + ret = JsonZkMgr::ServiceNameNode2Json(service_name, service_json); + if (0 != ret) { + return ret; + } + NS_LOG_INFO("to create serviceName when node not exit" + << ", zkPath: " << path + << ", servicename : " << service_name); + ZkCreateRequestPtr zk_create_req = boost::make_shared(); + zk_create_req->path = path; + zk_create_req->value = service_json; + zk_create_req->value_len = service_json.size(); + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)->ZkCreate(zk_create_req); + if (ZOK != ret || ret == -1) { + NS_LOG_ERROR("WARN zoo_create failed zkPath:" << path + << ", zValue:" << service_json.c_str() + << ", zValue size:" << service_json.size() + << ", ret:" << ret); + return ret; + } + return ret; +} +int32_t RegistryService::RegistryServiceNameNodeCreate(const SGService& +oservice, const std::string& service_name,const std::string& path){ + int32_t ret = SUCCESS; + std::string str_json = ""; + ServiceNode oTmp; + oTmp.serviceName = service_name; + oTmp.appkeys.insert(oservice.appkey); + oTmp.lastUpdateTime = static_cast(time(0)); + + JsonZkMgr::ServiceNode2Json(oTmp, str_json); + + NS_LOG_INFO("to regist when node not exit" + << ", serviceName: " << service_name + << ", appkey : " << oservice.appkey); + ZkCreateRequestPtr zk_create_req = boost::make_shared(); + zk_create_req->path = path; + zk_create_req->value = str_json; + zk_create_req->value_len = str_json.size(); + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)-> + ZkCreate(zk_create_req); + if (ZOK != ret || ret == -1) { + NS_LOG_WARN("WARN zoo_create failed zkPath:" << path + << ", zValue:" << str_json.c_str() + << ", zValue size:" << str_json.size() + << ", ret:" << ret); + return ret; + } + return ret; + +} +int32_t RegistryService::UpdateServiceNameNodeTime(const SGService& +oservice,const std::string& path){ + int32_t ret = SUCCESS; + int data_len = kZkContentSize; + std::string str_org_json = ""; + struct Stat stat; + + ZkGetRequestPtr zk_get_req = boost::make_shared(); + ZkGetResponsePtr zk_get_res = boost::make_shared(); + zk_get_req->path = path; + zk_get_req->watch = 0; + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)-> + ZkGet(zk_get_req, zk_get_res); + if (ZOK != ret) { + NS_LOG_WARN("zoo_get origin content fail or zk handle is null, ret: " + << ret + << ", zkPath: " << path); + return ret; + } + str_org_json = zk_get_res->buffer; + data_len = zk_get_res->buffer_len; + stat = zk_get_res->stat; + + ServiceNode org_service; + ret = JsonZkMgr::Json2ServiceNode(str_org_json, org_service); + if (ret != 0) { + NS_LOG_ERROR("Json2ServiceNode failed! strJson = " << str_org_json + << "ret = " << ret); + return ret; + } + if (org_service.appkeys.end() != org_service.appkeys.find(oservice.appkey)) {//防止重复注册 + NS_LOG_WARN("appkey already exists, don't need to register appkey:" + << oservice.appkey); + return SUCCESS; + } + //reset oService last_update_time + org_service.lastUpdateTime = static_cast(time(0)); + org_service.appkeys.insert(oservice.appkey); + + str_org_json = ""; + //NOTICE: sg2Service always return 0 + if (JsonZkMgr::ServiceNode2Json(org_service, str_org_json) < 0) { + NS_LOG_ERROR("ServiceName2Json failed"); + return -1; + } + + NS_LOG_INFO("to regist when node exists" + << ", serviceName : " << org_service.serviceName + << ", appkey : " << oservice.appkey); + ZkSetRequestPtr zk_set_req = boost::make_shared(); + zk_set_req->path = path; + zk_set_req->buffer = str_org_json; + zk_set_req->version = stat.version; //set的版本号设置为get获取的版本号,不再强制覆盖 + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)-> + ZkSet(zk_set_req); + if (ZOK != ret || ret == -1) { + NS_LOG_ERROR("ERR zoo_set failed zkPath:" + << path + << " szValue:" << str_org_json + << " szValue size:" << str_org_json.size() + << "ret:" << ret); + return ret; + } + return ret; +} +int32_t RegistryService::RegistryServiceNameToZk(const SGService &oservice, + int uptCmd) { + if (0 == oservice.serviceInfo.size()) { + NS_LOG_DEBUG("serviceinfo is empty"); + return SUCCESS; + } + for (std::map::const_iterator iter = + oservice.serviceInfo.begin(); iter != oservice.serviceInfo.end(); ++iter) { + std::string zk_service_path = ""; + std::string service_name = iter->first; + int32_t ret = agent_path_.GenServiceNameZkPathNode(zk_service_path, + service_name, oservice.appkey); + if (SUCCESS != ret) { + return ret; + } + NS_LOG_INFO("_gen serviceNamePath: " << zk_service_path); + ZkExistsRequestPtr zk_exists_req = + boost::make_shared(); + zk_exists_req->path = zk_service_path; + zk_exists_req->watch = 0; + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)-> + ZkExists(zk_exists_req); + if (ZNONODE == ret || ret == -1) { + NS_LOG_ERROR("servicename not exist.zkpath:" + << zk_service_path); + if(SUCCESS != RegistryServiceNameCreate(service_name, + zk_service_path)){ + NS_LOG_ERROR("servicename create failed, zkpath:" + << zk_service_path); + } + + } else if (ZNOAUTH == ret) { + NS_LOG_ERROR("ZNOAUTH in serviceName. ret = " << ret); + return ret; + } + std::string zkPath = ""; + ret = agent_path_.GenServiceNameZkPathNode(zkPath, service_name, + oservice.protocol, oservice.appkey); + if (SUCCESS != ret) { + return ret; + } + NS_LOG_INFO("_gen serviceNamePathNode: " << zkPath); + zk_exists_req->path = zkPath; + zk_exists_req->watch = 0; + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)-> + ZkExists(zk_exists_req); + if (ZNONODE == ret) { + if(SUCCESS != RegistryServiceNameNodeCreate(oservice,service_name, + zk_service_path)){ + NS_LOG_ERROR("servicename create failed, zkpath:" + << zk_service_path); + return FAILURE; + } + } else if (ZOK == ret) { + if(SUCCESS != UpdateServiceNameNodeTime(oservice, zk_service_path)){ + NS_LOG_ERROR("servicename create failed, zkpath:" + << zk_service_path); + return FAILURE; + } + } else if (ZNOAUTH == ret) { + NS_LOG_ERROR("ZNOAUTH in registerService. ret = " << ret); + return ret; + } else { + NS_LOG_ERROR("ERR other error: " << ret << " in registerService"); + return ret; + } + } + + return SUCCESS; +} +int32_t RegistryService::RegistryUpdateZkNode(const SGService& agent_service, + const std::string &zk_path, + RegistCmd::type regCmd, + int uptCmd) { + int32_t ret = FAILURE; + int32_t data_len = kZkContentSize; + std::string str_json = ""; + struct Stat stat; + + ZkGetRequestPtr zk_get_req(new ZkGetRequest()); + ZkGetResponsePtr zk_get_res(new ZkGetResponse()); + zk_get_req->path = zk_path; + zk_get_req->watch = 0; + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)-> + ZkGet(zk_get_req, zk_get_res); + if (ZOK != ret) { + NS_LOG_INFO("zoo_get origin content fail or zk handle is null, ret: " + << ret << ", zkPath: " << zk_path); + return ret; + } + str_json = zk_get_res->buffer; + data_len = zk_get_res->buffer_len; + stat = zk_get_res->stat; + SGService org_service; + ret = JsonZkMgr::Json2SGService(str_json, org_service); + if (ret != 0) { + NS_LOG_INFO("Json2SGService failed! strJson = " << str_json + << "ret = " << ret); + return ret; + } + if(register_strategy_.IsRepeatedRegister(org_service,agent_service)){ + NS_LOG_WARN("Repeated to register , registerinfo : appkey = " + << org_service.appkey + << ", protocol = " << org_service.protocol + << ", uptCmd : " << uptCmd + << ", env : " << org_service.envir + << ", status : " << org_service.status + << "; fweight : " << org_service.fweight + << "; protocol: " << org_service.protocol + << ", ip : " << org_service.ip); + return ERR_REPEATED_REGISTER; + } + if (UptCmd::ADD != static_cast(uptCmd)) { + if (fb_status::STOPPED == org_service.status + || fb_status::STARTING == org_service.status) { + std::string status_str = + fb_status::STOPPED == org_service.status ? "STOPPED" : "STARTING"; + NS_LOG_INFO("the zk node status is " << status_str + << ", don't change its status, " + "appkey = " + << org_service.appkey + << ", ip = " << agent_service.ip + << ", port = " + << agent_service.port); + } else { + NS_LOG_INFO("the zk node status(" << org_service.status << + ") is not equals to the one which is " + "defined by user, use the later(" + << agent_service.status << ")"); + org_service.status = agent_service.status; + } + } + + org_service.lastUpdateTime = time(0); + ResetRegistryServiceInfo(org_service, agent_service, regCmd, uptCmd); + str_json = ""; + if (JsonZkMgr::SGService2Json(org_service, + str_json, + CXmlFile::GetAppenv()->GetIntEnv()) < 0) { + NS_LOG_INFO("_SGService2Json failed"); + return FAILURE; + } + NS_LOG_INFO("to regist when node exists" + << ", uptCmd : " << uptCmd + << ", appkey : " << org_service.appkey + << ", env : " << org_service.envir + << ", local env : " << CXmlFile::GetAppenv()->GetIntEnv() + << ", status : " << org_service.status + << "; fweight : " << org_service.fweight + << "; serverType : " << org_service.serverType + << "; protocol: " << org_service.protocol + << ", ip : " << org_service.ip); + ZkSetRequestPtr zk_set_req(new ZkSetRequest()); + zk_set_req->path = zk_path; + zk_set_req->buffer = str_json; + zk_set_req->version = stat.version; + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)-> + ZkSet(zk_set_req); + if (ZOK != ret || ret == -1) { + NS_LOG_INFO("ERR zoo_set failed zkPath:" << zk_path + << " szValue:" + << str_json.c_str() + << " szValue size:" + << str_json.size() + << "ret:" << ret); + } + return ret; +} +int32_t RegistryService::RegistryCreateZkNode(const SGService& agent_service, + const std::string &zk_path, + RegistCmd::type regCmd, + int uptCmd) { + + if (RegistCmd::UNREGIST == regCmd || UptCmd::DELETE == uptCmd) { + // if the zk node don't exist, ignore unRegister + NS_LOG_INFO("ignore unRegister,zk node don't exist" + << ", zkPath: " << zk_path + << ", ip : " << agent_service.ip + << ", regCmd: " << regCmd + << ", uptCmd: " << uptCmd); + return ERR_NODE_NOTFIND; + } + int32_t ret = FAILURE; + std::string json = ""; + SGService service_tmp = const_cast(agent_service); + JsonZkMgr::SGService2Json(service_tmp, json,CXmlFile::GetAppenv() + ->GetIntEnv()); + + NS_LOG_INFO("register: create a new zk node" + << ", zkPath: " << zk_path + << ", appkey : " << service_tmp.appkey + << ", env : " << service_tmp.envir + << ", local env : " << CXmlFile::GetAppenv()->GetStrEnv() + << "; protocol : " << service_tmp.protocol + << ", ip : " << service_tmp.ip); + ZkCreateRequestPtr zk_data_create(new ZkCreateRequest()); + zk_data_create->path = zk_path; + zk_data_create->value = json; + zk_data_create->value_len = json.size(); + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex) + ->ZkCreate(zk_data_create); + if (ZOK != ret || ret == FAILURE) { + NS_LOG_INFO("WARN zoo_create failed zkPath:" << zk_path + << ", zValue:" << json.c_str() + << ", zValue size:" + << json.size() + << ", ret:" << ret); + return ret; + } + return ret; +} +int32_t RegistryService::UpdateLastModifiedTime(const std::string &appkey, + const std::string &zk_provider_path) { + int32_t ret = FAILURE; + + CProviderNode oprovider; + oprovider.appkey = appkey; + oprovider.lastModifiedTime = time(NULL); + + std::string str_json = ""; + JsonZkMgr::ProviderNode2Json(oprovider, str_json); + ZkSetRequestPtr zk_set_req = boost::shared_ptr(new ZkSetRequest()); + zk_set_req->path = zk_provider_path; + zk_set_req->buffer = str_json; + zk_set_req->version = -1; + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex) + ->ZkSet(zk_set_req); + + if (ZOK != ret || FAILURE == ret) { + NS_LOG_INFO("ERR zoo_set provider failed zkPath:" + << zk_provider_path + << " szValue:" << str_json.c_str() + << " szValue size:" << str_json.size() + << "ret: " << ret); + return ret; + } + return ret; +} +void RegistryService::ResetRegistryServiceInfo(SGService &org_service, + const SGService &sg_service, + RegistCmd::type reg_cmd, + int upt_cmd) { + if (RegistCmd::REGIST == reg_cmd) { + org_service.version = sg_service.version; + if (version_manager_.IsOldVersion(sg_service.version)){ + NS_LOG_INFO("version = " << org_service.version + << ", need to clear serviceInfo"); + org_service.heartbeatSupport = HeartbeatUnSupport; + org_service.serviceInfo.clear(); + } else{ + org_service.heartbeatSupport = sg_service.heartbeatSupport; + ReEditServiceName(org_service, sg_service, upt_cmd); + } + } + org_service.appkey = sg_service.appkey; + org_service.ip = sg_service.ip; + org_service.port = sg_service.port; +} +int32_t RegistryService::ReEditServiceName(SGService &desService, + const SGService &srcService, + int uptCmd) { + switch (uptCmd) { + case UptCmd::RESET:desService.serviceInfo = srcService.serviceInfo; + break; + case UptCmd::ADD: + for (std::map::const_iterator iter = + srcService.serviceInfo.begin(); + iter != srcService.serviceInfo.end(); + ++iter) { + desService.serviceInfo[iter->first] = iter->second; + } + break; + case UptCmd::DELETE: + for (std::map::const_iterator iter = + srcService.serviceInfo.begin(); + iter != srcService.serviceInfo.end(); + ++iter) { + desService.serviceInfo.erase(iter->first); + } + break; + default: NS_LOG_INFO("unknown uptCmd: " << uptCmd); + return FAILURE; + } + return SUCCESS; +} +int32_t RegistryService::RegistryAction(RegParamPtr reg_service, + const int32_t ®_action) { + + switch (CXmlFile::GetI32Para(CXmlFile::RegistryCenter)){ + case kRegistryZk:{ + return RegistryActionToZk(reg_service,reg_action); + } + case kRegistryCache:{ + return RegistryActionToCache(); + } + case kRegistryMixer:{ + return RegistryActionToMixer(); + } + default:{ + NS_LOG_WARN("unsupported registry action "<::const_iterator + iter = reg_service->sgservice.serviceInfo.begin(); + iter != reg_service->sgservice.serviceInfo.end(); ++iter) { + service_name += iter->first + " "; + unified_protocol += iter->second.unifiedProto + " "; + } + NS_LOG_INFO("to register service to ZK" + << ", appkey : " << reg_service->sgservice.appkey + << ", ip : " << reg_service->sgservice.ip + << ", version : " << reg_service->sgservice.version + << ", port : " << reg_service->sgservice.port + << ", status : " << reg_service->sgservice.status + << "; fweight : " << reg_service->sgservice.fweight + << "; protocol: " << reg_service->sgservice.protocol + << "; serverType : " << reg_service->sgservice.serverType + << "; unifiedProto : " << unified_protocol + << "; regCmd : " << reg_action); + int loop_times = 0; + do { + int32_t ret = RegistryServiceToZk(reg_service->sgservice, + reg_service->regCmd, + reg_service->uptCmd); + if (SUCCESS == ret || ERR_ILLEGAL_REGISTE == ret || ERR_NODE_NOTFIND == ret) { + return ret; + } else { + NS_LOG_INFO("retry to registry , appkey is : " << reg_service->sgservice.appkey); + if (loop_times > retry_times_) { + NS_LOG_INFO("register service to ZK fail! loop_times > reg_retry_, loop_times is : " + << loop_times + << ", appkey : " << reg_service->sgservice.appkey + << ", ip : " << reg_service->sgservice.ip + << ", port : " << reg_service->sgservice.port + << ", env : " << reg_service->sgservice.envir + << ", local env : " << CXmlFile::GetAppenv()->GetStrEnv() + << ", status : " << reg_service->sgservice.status + << "; fweight : " << reg_service->sgservice.fweight + << "; serverType : " << reg_service->sgservice.serverType + << "; protocol: " << reg_service->sgservice.protocol + << ", default retry times is : " << retry_times_); + return ERR_REGIST_SERVICE_ZK_FAIL; + } + } + } while (retry_times_ > loop_times++); +} + +int32_t RegistryService::RegistryActionToCache(){ + + return 0; +} + +int32_t RegistryService::RegistryActionToMixer(){ + + return 0; +} + +} diff --git a/sg_agent/src/mns/registry_service.h b/sg_agent/src/mns/registry_service.h new file mode 100644 index 0000000..1995e56 --- /dev/null +++ b/sg_agent/src/mns/registry_service.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef SRC_MNS_REGISTRY_SERVICE_H_ +#define SRC_MNS_REGISTRY_SERVICE_H_ + +#include "registry_base.h" +#include "naming_data_types.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "config_loader.h" +#include "version_manager.h" +#include "registry_strategy.h" +namespace meituan_mns { +class RegistryFactory { + + public: + + /** + *注册创建实现 + *@param type 注册的类型:增量注册、批量注册 + * + *@return 注册实体类型 + * + **/ + Registry* CreateRegistry(RegistryType type); + + RegistryFactory() {} + ~RegistryFactory() {} + + private: + protected: +}; + +class RegistryService : public Registry { + + public: + typedef boost::shared_ptr SGServicePtr; + typedef boost::shared_ptr RegParamPtr; + + static RegistryService* GetInstance(); + + ~RegistryService(){} + + void RegistryHealthycheck() {} + /** + *注册实现 + *@param + * + *@return int + * + **/ + const uint32_t RegistryStart(const SGService &oService, + const int32_t ®_action); + const uint32_t RegistryStop(const SGService &oService) {} + + /** + *服务下线实现 + *@param + * + *@return int + * + **/ + const uint32_t UnRegistryStart(const SGService &oService, + const int32_t ®_action); + const uint32_t UnRegistryStop(const SGService &oService) {} + + private: + + RegistryService(){}; + /** + *实际注册流程处理 + *@param + * + *@return void type + * + **/ + int32_t RegistryAction(RegParamPtr reg_service, const int32_t ®_action); + + int32_t RegistryActionToZk(RegParamPtr reg_service, const int32_t ®_action); + + int32_t RegistryActionToCache(); + + int32_t RegistryActionToMixer(); + + /** + *写入方式取决注册中心类型,使用zookeeper + *@param oservice,regCmd,uptCmd + * + *@return uint32_t type + * + **/ + int32_t RegistryServiceToZk(const SGService &oservice, + RegistCmd::type regCmd = RegistCmd::REGIST, + int uptCmd = UptCmd::RESET); + + /** + *重新处理serviceinfo数据,如servicename + *@param org_service,sg_service,regCmd + * + *@return void + * + **/ + void ResetRegistryServiceInfo(SGService &org_service, + const SGService &sg_service, + RegistCmd::type regCmd, int upt_cmd); + /** + *更新节点最后更改的时间 + *@param appkey,zk_provider_path,json + * + *@return int + * + **/ + int32_t UpdateLastModifiedTime(const std::string &appkey, + const std::string &zk_provider_path); + /** + *创建节点 + *@param agent_service,zk_path,json,regCmd,uptCmd + * + *@return int + * + **/ + int32_t RegistryCreateZkNode(const SGService& agent_service, + const std::string &zk_path, + RegistCmd::type regCmd, int uptCmd); + /** + *创建servicename + *@param oservice,uptCmd + * + *@return int + * + **/ + int32_t RegistryServiceNameToZk(const SGService &oservice, + int uptCmd); + /** + *更新节点数据 + *@param agent_service,zk_path,json,regCmd,uptCmd + * + *@return int + * + **/ + int32_t RegistryUpdateZkNode(const SGService& agent_service, + const std::string &zk_path, + RegistCmd::type regCmd, int uptCmd); + /** + *重新编辑servicename数据 + *@param agent_service,zk_path,json,regCmd,uptCmd + * + *@return int + * + **/ + int32_t ReEditServiceName(SGService &desService, + const SGService &srcService, + int uptCmd); + + int32_t RegistryServiceNameCreate(const std::string& + service_name,const std::string& path); + + int32_t RegistryServiceNameNodeCreate(const SGService& + oservice, const std::string& service_name,const std::string& path); + + int32_t UpdateServiceNameNodeTime(const SGService& + oservice,const std::string& path); + + private: + + static RegistryService* registry_service_; + static muduo::MutexLock registry_service_lock_; + + VersionManager version_manager_; + + AgentZkPath agent_path_; + + RegistryStrategy register_strategy_; + + protected: + +}; +class RegistryServiceBatch : public Registry { + public: + RegistryServiceBatch() {} + ~RegistryServiceBatch() {} + static RegistryServiceBatch* GetInstance(); + /** + *注册实现 + *@param oService,reg_action + * + *@return int + * + **/ + const uint32_t RegistryStart(const SGService &oService, + const int32_t ®_action) {} + const uint32_t RegistryStop(const SGService &oService) {} + + const uint32_t UnRegistryStart(const SGService &oService, + const int32_t ®_action) {} + const uint32_t UnRegistryStop(const SGService &oService) {} + + private: + static RegistryServiceBatch * registry_service_batch_; + static muduo::MutexLock registry_service_batch_lock_; + + RegistryStrategy register_strategy_; + AgentZkPath agent_path_; + protected: +}; + +} + +#endif // namespace meituan_mns + diff --git a/sg_agent/src/mns/registry_strategy.cc b/sg_agent/src/mns/registry_strategy.cc new file mode 100644 index 0000000..3c3f0e7 --- /dev/null +++ b/sg_agent/src/mns/registry_strategy.cc @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "inc_comm.h" +#include "mnsc_client.h" +#include "base_errors_consts.h" +#include "config_loader.h" +#include "route_info.h" +#include "registry_strategy.h" +#include "base_consts.h" +#include "base_mns_consts.h" +#include "zk_client_pool.h" +#include + + +namespace meituan_mns { + + +int32_t RegistryStrategy::CheckArgs(const SGService &oservice) { + std::string appkey = oservice.appkey; + if (appkey.empty()) { + NS_LOG_ERROR("fail to register, because the appkey is empty."); + return ERR_EMPTY_APPKEY; + } else if (!IsAppkeyLegal(appkey)) { + NS_LOG_ERROR("Invalid appkey in regist, appkey = " << appkey); + return ERR_INVALIDAPPKEY; + } + + if (!(0 <= oservice.weight && 100 >= oservice.weight)) { + NS_LOG_ERROR("invalid weight: " << oservice.weight + << ", appkey: " << oservice.appkey + << ", ip: " << oservice.ip + << ", port: " << oservice.port); + return ERR_INVALID_WEIGHT; + } + + if (!(0.0001 <= oservice.fweight && 100.0 - oservice.fweight >= 0.1)) { + NS_LOG_ERROR("invalid fweight: " << oservice.fweight + << ", appkey: " << oservice.appkey + << ", ip: " << oservice.ip + << ", port: " << oservice.port); + return ERR_INVALID_WEIGHT; + } + + if (!IsIpAndPortLegal(oservice.ip, oservice.port)) { + NS_LOG_ERROR("invalid port: " << oservice.port + << ", appkey: " << oservice.appkey + << ", ip: " << oservice.ip + << ", weight: " << oservice.weight); + return ERR_INVALID_PORT; + } + return SUCCESS; +} + +bool RegistryStrategy::IsAllowMacRegistry(const SGService &oservice) { + NS_LOG_INFO("RegistryStrategy the registry appkey is = " + << oservice.appkey << ";env = " + << CXmlFile::GetAppenv()->GetTypeEnv()); + + if (PPE != CXmlFile::GetAppenv()->GetTypeEnv() && + TEST != CXmlFile::GetAppenv()->GetTypeEnv()) { + return true; + } + if (!whitelist_manager_.IsMacRegisterAppkey(oservice.appkey)) { + return true; + } + std::vector > + ::const_iterator iter = CXmlFile::GetRegisterIdc()->begin(); + for (; CXmlFile::GetRegisterIdc()->end() != iter; ++iter) { + if ((*iter)->IsSameIdc(oservice.ip)) { + return true; + } + } + return false; +} + +int32_t RegistryStrategy::CheckAllowedProtocolRegistry(SGServicePtr &oservice) { + if (oservice->protocol.empty()) { + if (THRIFT_TYPE == oservice->serverType) { + oservice->protocol = "thrift"; + } else if (HTTP_TYPE == oservice->serverType) { + oservice->protocol = "http"; + } else { + NS_LOG_ERROR("Appkey: " << oservice->appkey + << " serverType: " << oservice->serverType + << " is wrong!"); + return FAILURE; + } + NS_LOG_WARN("the original protocol defined by user is empty, " + "now identify the protocol=" + << oservice->protocol + << " based on serverType=" + << oservice->serverType); + } + return SUCCESS; + +} +int32_t RegistryStrategy::IsAllowedRegistry(const SGService &oService) { + int32_t ret = CheckArgs(oService); + if (SUCCESS != ret) { + NS_LOG_INFO("its not allowed to registry"); + return ret; + } + if (!IsAllowMacRegistry(oService)) { + NS_LOG_INFO("hotel appkey and the ip is not in the special idc," + " not allow to register service to ZK , appkey = " + << oService.appkey + << "; version = " << oService.version + << "; ip = " << oService.ip + << "; port = " << oService.port + << "; weight = " << oService.weight + << "; status = " << oService.status + << "; role = " << oService.role + << "; envir = " << oService.envir + << "; fweight = " << oService.fweight + << "; lastUpdateTime = " << oService.lastUpdateTime + << "; protocol = " << oService.protocol + << "; serverType = " << oService.serverType); + + return FAILURE; + } + if (!RegistryFilterCheck(oService)) { + NS_LOG_ERROR("appkey is not legal to regist in this ip, appkey = " + << oService.appkey); + return ERR_ILLEGAL_REGISTE; + } + return ret; +} + +bool RegistryStrategy::RegistryFilterCheck(const SGService &oservice){ + if (whitelist_manager_.IsAppkeyInRegistUnlimitWhitList(oservice.appkey)) { + NS_LOG_INFO("appkey: " << oservice.appkey + << " is in regist unlimit white list"); + return true; + } + if (IsLimitOnZk(oservice)) { + return CheckLegalOnOps(oservice); + } + return true; + +} + +bool RegistryStrategy::CheckLegalOnOps(const SGService &service) { + std::ifstream fi(kServiceAppkeyPath.c_str()); + if (!fi.is_open()) { + NS_LOG_INFO("faild to open file: " << kServiceAppkeyPath); + fi.close(); + return true; + } + + std::string appkey; + while (std::getline(fi, appkey)) { + NS_LOG_INFO("appkey: " << appkey); + if (appkey == service.appkey) { + fi.close(); + return true; + } + } + + fi.close(); + NS_LOG_INFO(service.appkey << " is not in appkeys"); + return false; + +} +bool RegistryStrategy::IsLimitOnZk(const SGService &service) { + bool res = false; + std::string zk_desc_path = ""; + int ret = agent_path_.GenDescZkPath(zk_desc_path, service.appkey); + + std::string str_json = ""; + ZkExistsRequestPtr zk_exists_req(new ZkExistsRequest()); + zk_exists_req->path = zk_desc_path; + zk_exists_req->watch = 0; + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)-> + ZkExists(zk_exists_req); + + if (ZNONODE == ret || ret == -1) { + NS_LOG_ERROR("appkey desc is not exists, appkey = " + << service.appkey + << ", env = " << CXmlFile::GetAppenv()->GetStrEnv()); + return false; //默认反馈合法 + }else if (ZOK == ret) { // 节点存在, 不需要进行合法验证 + int datalen = kZkContentSize; + struct Stat stat; + ZkGetRequestPtr zk_get_req = boost::shared_ptr(new ZkGetRequest()); + ZkGetResponsePtr zk_get_res = boost::shared_ptr(new ZkGetResponse()); + zk_get_req->path = zk_desc_path; + zk_get_req->watch = 0; + ret = ZkClientPool::GetInstance()->GetZkClientForHash(kZkClientIndex)-> + ZkGet(zk_get_req, zk_get_res); + if (ZOK != ret) { + NS_LOG_INFO("zoo_get origin content fail or zk handle is null, ret: " + << ret + << ", zkPath: " << zk_desc_path); + return ret; + } + str_json = zk_get_res->buffer; + datalen = zk_get_res->buffer_len; + stat = zk_get_res->stat; + + cJSON *root = cJSON_Parse(str_json.c_str()); + if (NULL == root) { + NS_LOG_ERROR("failed to parse json: " << str_json); + return false; + } + + cJSON *pItem = cJSON_GetObjectItem(root, "regLimit"); + if (pItem) { + int reg_limit = pItem->valueint; + if (reg_limit == REG_LIMIT_LEGAL) { + res = true; + } + } + cJSON_Delete(root); + } + NS_LOG_INFO("check appkey: " << service.appkey << " is reglimit: " << res); + return res; +} +// 去除lastupdatetime的判断 +bool RegistryStrategy::IsRepeatedRegister(const SGService& orgservice, + const SGService& zkservice) { + if (!(orgservice.appkey == zkservice.appkey)) + return false; + if (!(orgservice.version == zkservice.version)) + return false; + if (!(orgservice.ip == zkservice.ip)) + return false; + if (!(orgservice.port == zkservice.port)) + return false; + if (!(orgservice.weight == zkservice.weight)) + return false; + if (!(orgservice.status == zkservice.status)) + return false; + if (!(orgservice.role == zkservice.role)) + return false; + if (!(orgservice.envir == zkservice.envir)) + return false; + if (!(orgservice.fweight == zkservice.fweight)) + return false; + if (!(orgservice.serverType == zkservice.serverType)) + return false; + if (!(orgservice.protocol == zkservice.protocol)) + return false; + if (!(orgservice.serviceInfo == zkservice.serviceInfo)) + return false; + if (!(orgservice.heartbeatSupport == zkservice.heartbeatSupport)) + return false; + return true; +} + +} diff --git a/sg_agent/src/mns/registry_strategy.h b/sg_agent/src/mns/registry_strategy.h new file mode 100644 index 0000000..f7b90c8 --- /dev/null +++ b/sg_agent/src/mns/registry_strategy.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef SRC_MNS_REGISTRY_STRATEGY_H_ +#define SRC_MNS_REGISTRY_STRATEGY_H_ + +#include "ServiceAgent.h" +#include "naming_service_types.h" +#include "route_base.h" +#include "version_manager.h" +#include "whitelist_manager.h" + +namespace meituan_mns { + +typedef boost::shared_ptr SGServicePtr; + +class RegistryStrategy { + + public: + RegistryStrategy() {} + ~RegistryStrategy() {} + + /** + * 通过注册合法检测 + * @param oservice + * + * @return uint + * + */ + int32_t IsAllowedRegistry(const SGService &oservice); + + /** + * + * @param orgservice + * @param zkservice + * @return + */ + bool IsRepeatedRegister(const SGService& orgservice, + const SGService& zkservice); + + /** + * 注册协议检测 + * @param oservice + * + * @return uint + * + */ + int32_t CheckAllowedProtocolRegistry(SGServicePtr &oservice); + + private: + /** + * 注册参数合法检测 + * @param 注册参数SGService oservice + * + * @return uint + * + */ + int32_t CheckArgs(const SGService &oservice); + /** + * + * @param oservice + * @return + */ + bool IsAllowMacRegistry(const SGService &oservice); + + /** + * + * @param oservice + * @return + */ + bool RegistryFilterCheck(const SGService &oservice); + /** + * + * @param service + * @return + */ + bool IsLimitOnZk(const SGService &service); + /** + * + * @param service + * @return + */ + bool CheckLegalOnOps(const SGService &service); + + protected: + + private: + WhiteListManager whitelist_manager_; + AgentZkPath agent_path_; +}; +} // namespace meituan_mns + +#endif // SRC_MNS_REGISTRY_STRATEGY_H_ diff --git a/sg_agent/src/mns/service_channels.cc b/sg_agent/src/mns/service_channels.cc new file mode 100644 index 0000000..9c31b6f --- /dev/null +++ b/sg_agent/src/mns/service_channels.cc @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "service_channels.h" +namespace meituan_mns { +ServiceChannels::ServiceChannels() : is_filter_bankbone_channel(0), is_filter_swimlane_channel(0), + is_all_channels(0), is_origin_cache(0){ + +} + +} \ No newline at end of file diff --git a/sg_agent/src/mns/service_channels.h b/sg_agent/src/mns/service_channels.h new file mode 100644 index 0000000..ae179fa --- /dev/null +++ b/sg_agent/src/mns/service_channels.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_SERVICE_CHANNELS_H +#define OCTO_OPEN_SOURCE_SERVICE_CHANNELS_H + +namespace meituan_mns { +class ServiceChannels { + + public: + + ServiceChannels(); + ~ServiceChannels() {}; + /** + * Set服务列表归属的channel标识 + * @param + * + * @return void + * + */ + void SetBankboneChannel(bool type) { is_filter_bankbone_channel = type; }; + void SetSwimlaneChannel(bool type) { is_filter_swimlane_channel = type; }; + void SetAllChannel(bool type) { is_all_channels = type; }; + void SetOriginChannel(bool type) { is_origin_cache = type; }; + + /** + * Get服务列表归属的channel标识 + * @param + * + * @return void + * + */ + bool GetBankboneChannel() { return is_filter_bankbone_channel; }; + bool GetSwimlaneChannel() { return is_filter_swimlane_channel; }; + bool GetAllChannel() { return is_all_channels; }; + bool GetOriginChannel() { return is_origin_cache; }; + + private: + bool is_filter_bankbone_channel; + bool is_filter_swimlane_channel; + bool is_all_channels; + bool is_origin_cache; + + protected: + +}; + +} // namespace meituan_mns + + + + +#endif //OCTO_OPEN_SOURCE_SERVICE_CHANNELS_H diff --git a/sg_agent/src/mns/zk_client.cc b/sg_agent/src/mns/zk_client.cc new file mode 100644 index 0000000..7dbe6fe --- /dev/null +++ b/sg_agent/src/mns/zk_client.cc @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "zk_client.h" +#include "inc_comm.h" +#include "base_consts.h" + +using namespace meituan_mns; + +const int kZkContentSize = 1024; +const int MAX_BUF_SIZE = 1024; + +ZkClient *ZkClient::zk_client_ = NULL; + +ZkClient::ZkClient() : zk_server_(""), + zk_timeout_(0), + rand_try_times_(0), + zk_retrytimes_(0), + zk_handle_(NULL) { + +} + +ZkClient::~ZkClient() { + ZkClose(); +} + +void ZkClient::Destroy() { + SAFE_DELETE(zk_client_); +} + +int ZkClient::ZkInit(ZkClient *zk_client, const std::string &zk_server, const int zk_timeout, const int zk_retrytimes) { + zk_client_ = zk_client; + zk_server_ = zk_server; + zk_timeout_ = zk_timeout; + zk_retrytimes_ = zk_retrytimes; + zoo_set_debug_level(ZOO_LOG_LEVEL_WARN); + + int ret = Connect2Zk(); + return ret; +} + +int ZkClient::Connect2Zk() { + //close old zk_connect before establish zk-connection + ZkClose(); + + int count = 0; + //避免跟zookeeper的自定义的状态重合 + int state = 888; + //默认初始值 + int delay_time = 1; + do { + NS_LOG_WARN("start to connect ZK, count : " << count); + if (zk_handle_ == NULL) { + RandSleep(); + zk_handle_ = zookeeper_init(zk_server_.c_str(), NULL, zk_timeout_, 0, NULL, 0); + if (zk_handle_ == NULL || errno == EINVAL) { + NS_LOG_ERROR("zookeeper_init failed. retrying in 1 second. " + "serverList: " << zk_server_ + << ", errno = " << errno + << ", timeout = " << zk_timeout_ + << ", count = " << count); + } else { + NS_LOG_INFO("zookeeper_init success. serverList: " << zk_server_); + } + } + //established,sleep 1s + sleep(delay_time); + delay_time = delay_time * 2; + + //check状态 + state = zoo_state(zk_handle_); + if (state == ZOO_CONNECTING_STATE) { + //sleep 5ms,then check zk_status + usleep(5000); + state = zoo_state(zk_handle_); + } + } while (state != ZOO_CONNECTED_STATE && count++ < zk_retrytimes_ ); + + if (state != ZOO_CONNECTED_STATE) { + NS_LOG_ERROR("zookeeper_init failed, please check zk_server. state = " << state); + } + + return state == ZOO_CONNECTED_STATE ? 0 : -2; +} + +int ZkClient::ZkClose() { + int ret = 0; + if (NULL != zk_handle_) { + ret = zookeeper_close(zk_handle_); + if (0 != ret) { + NS_LOG_ERROR("Failed to close zk connection! ret = " << ret ); + } + zk_handle_ = NULL; + } + return ret; +} + +int ZkClient::CheckZkConn() { + int count = 0; + int ret = 0; + int state = zoo_state(zk_handle_); + do { + if (ZOO_CONNECTED_STATE == state) { + break; + } else if (ZOO_CONNECTING_STATE == state) { + //if connection is establishing, sleep 50ms, then check + NS_LOG_WARN("WARN zk connection: ZOO_CONNECTING_STATE!"); + usleep(50000); + } else { + NS_LOG_ERROR("ERR zk connection lost! zk state = " << state); + ret = -1; + } + state = zoo_state(zk_handle_); + count++; + } while (state != ZOO_CONNECTED_STATE && count < zk_retrytimes_); + + return ret; +} + +void ZkClient::ConnWatcher(zhandle_t *zh, int type, int state, + const char *zk_path, void *watcher_ctx) { + if (ZOO_CONNECTED_STATE == state) { + NS_LOG_INFO("connWatcher() ZOO_CONNECTED_STATE = " << state + << ", type " << type); + } else if (ZOO_AUTH_FAILED_STATE == state) { + NS_LOG_ERROR("connWatcher() ZOO_AUTH_FAILED_STATE = " << state + << ", type " << type); + } else if (ZOO_EXPIRED_SESSION_STATE == state) { + NS_LOG_ERROR("connWatcher() ZOO_EXPIRED_SESSION_STATE = " << state + << ", type " << type); + zk_client_->Reconnect2Zk(); + } else if (ZOO_CONNECTING_STATE == state) { + NS_LOG_ERROR("connWatcher() ZOO_CONNECTING_STATE = " << state + << ", type " << type); + } else if (ZOO_ASSOCIATING_STATE == state) { + NS_LOG_ERROR("connWatcher() ZOO_ASSOCIATING_STATE = " << state + << ", type " << type); + } +} + +int ZkClient::Reconnect2Zk() { + int retry_time = 0; + int ret = 0; + while (0 != CheckZkConn() && zk_retrytimes_ > retry_time++) { + RandSleep(); + ret = Connect2Zk(); + if (0 != ret) { + NS_LOG_ERROR("Failed to connect zk! retry_time = " << retry_time); + } + } + return ret; +} + +void ZkClient::RandSleep() { + srand(time(0)); + unsigned int rand_usleep_time = 1000; + rand_try_times_ = rand_try_times_ > 3 ? 0 : rand_try_times_; + switch (rand_try_times_++) { + case 0 : { + rand_usleep_time *= rand() % 10; + break; + } + case 1 : { + rand_usleep_time *= rand() % 20; + break; + } + case 2 : { + rand_usleep_time *= rand() % 30; + } + default : { + rand_usleep_time *= rand() % 50; + } + } + usleep(rand_usleep_time); +} + +int ZkClient::ZkGet(const ZkGetRequestPtr &request_ptr, ZkGetResponsePtr &response_ptr) { + if (0 != CheckZkConn()) { + return ERR_ZK_CONNECTION_LOSS; + } + int retry = 0; + int ret = 0; + struct Stat stat; + int buffer_len = kZkContentSize; + boost::shared_array buff_ptr(new char[buffer_len]); + while (zk_retrytimes_ > retry++) { + ret = zoo_get(zk_handle_, request_ptr->path.c_str(), request_ptr->watch, buff_ptr.get(), &buffer_len, &stat); + if (ZOK != ret) { + NS_LOG_ERROR("Failed to zoo get, zk_path: " << request_ptr->path + << ", buffer_len: " << buffer_len + << ", ret = " << ret); + return ret; + } + if (buffer_len != stat.dataLength && 0 != stat.dataLength) { + NS_LOG_INFO("new larger buffer's size to get zk_get node"); + buff_ptr = boost::shared_array(new char[stat.dataLength]); + buffer_len = stat.dataLength; + continue; + } + break; + } + response_ptr->buffer.assign(buff_ptr.get(), buffer_len); + response_ptr->buffer_len = buffer_len; + response_ptr->stat = stat; + return ret; +} + + +int ZkClient::ZkWgetChildren(const ZkWGetChildrenRequestPtr &request_ptr, ZkWGetChildrenResponsePtr &response_ptr) { + if (0 != CheckZkConn()) { + return ERR_ZK_CONNECTION_LOSS; + } + struct String_vector stat; + stat.count = 0; + stat.data = 0; + int ret = zoo_wget_children(zk_handle_, (request_ptr->path).c_str(), request_ptr->watch, + request_ptr->watcherCtx, &stat); + if (ZOK == ret) { + response_ptr->count = stat.count; + for (int i = 0; i < stat.count; i++) { + std::string data = stat.data[i]; + response_ptr->data.push_back(data); + } + } + return ret; +} + +int ZkClient::ZkWget(const ZkWGetRequestPtr &request_ptr, ZkWGetResponsePtr &response_ptr) { + if (0 != CheckZkConn()) { + return ERR_ZK_CONNECTION_LOSS; + } + + int retry = 0; + int ret = 0; + struct Stat stat; + int buffer_len = kZkContentSize; + boost::shared_array buff_ptr(new char[buffer_len]); + while (zk_retrytimes_ > retry++) { + ret = zoo_wget(zk_handle_, (request_ptr->path).c_str(), request_ptr->watch, request_ptr->watcherCtx, + buff_ptr.get(), &buffer_len, &stat); + if (ZOK != ret) { + return ret; + } + + if (buffer_len != stat.dataLength && stat.dataLength != 0) { + NS_LOG_INFO("buffer's size is not enough to put zk_wget node"); + buff_ptr = boost::shared_array(new char[stat.dataLength]); + buffer_len = stat.dataLength; + continue; + } + break; + } + response_ptr->buffer.assign(buff_ptr.get(), buffer_len); + response_ptr->buffer_len = buffer_len; + response_ptr->stat = stat; + return ret; +} + +int ZkClient::ZkCreate(const ZkCreateRequestPtr &request_ptr) { + if (0 != CheckZkConn()) { + return ERR_ZK_CONNECTION_LOSS; + } + char path_buffer[MAX_BUF_SIZE] = {0}; + int path_buffer_len = MAX_BUF_SIZE; + int ret = zoo_create(zk_handle_, + request_ptr->path.c_str(), + request_ptr->value.c_str(), + request_ptr->value_len, + &ZOO_OPEN_ACL_UNSAFE /* use ACL of parent */, + 0 /* persistent node*/, + path_buffer, + path_buffer_len); + NS_LOG_INFO("zoo_create ret = " + << ret + << ", path = " + << request_ptr->path); + return ret; +} + +int ZkClient::ZkSet(const ZkSetRequestPtr &request_ptr) { + if (0 != CheckZkConn()) { + return ERR_ZK_CONNECTION_LOSS; + } + int ret = zoo_set(zk_handle_, + request_ptr->path.c_str(), + request_ptr->buffer.c_str(), + static_cast(request_ptr->buffer.size()), + request_ptr->version); + NS_LOG_INFO("zoo_set ret = " + << ret + << ", path = " + << request_ptr->path); + return ret; +} + +int ZkClient::ZkExists(const ZkExistsRequestPtr &request_ptr) { + if (0 != CheckZkConn()) { + return ERR_ZK_CONNECTION_LOSS; + } + struct Stat stat; + int ret = zoo_exists(zk_handle_, + request_ptr->path.c_str(), + request_ptr->watch, + &stat); + NS_LOG_INFO("zoo_exists ret = " + << ret + << ", path = " + << request_ptr->path); + return ret; +} +int ZkClient::ZkPathCreateRecursivly(std::string &zk_path) { + if (0 != CheckZkConn()) { + return ERR_ZK_CONNECTION_LOSS; + } + int32_t ret = FAILURE; + boost::trim(zk_path); + ZkExistsRequestPtr zk_exists_req(new ZkExistsRequest()); + zk_exists_req->watch = 0; + + ZkCreateRequestPtr zk_data_create(new ZkCreateRequest()); + zk_data_create->path = zk_path; + zk_data_create->value = "test zk path create"; + zk_data_create->value_len = strlen(zk_data_create->value.c_str()); + std::vector path_list; + int32_t path_len = SplitStringIntoVector(zk_path.c_str(), "/", path_list); + if(0 >= path_len || path_len >kMaxZkPathDepth){ + NS_LOG_INFO("create path failed, zk_path: "<< zk_path + <<"; path_len:"<path = create_path; + zk_data_create->path = create_path; + NS_LOG_INFO("create_path zk_path: "<< create_path); + struct Stat stat; + if(ZNONODE == zoo_exists(zk_handle_, + zk_exists_req->path.c_str(), + zk_exists_req->watch, + &stat)){ + + if(ZOK == zoo_create(zk_handle_, + zk_data_create->path.c_str(), + zk_data_create->value.c_str(), + zk_data_create->value_len, + &ZOO_OPEN_ACL_UNSAFE /* use ACL of parent */, + 0 /* persistent node*/, + path_buffer, + path_buffer_len)){ + create_path_tmp = create_path; + NS_LOG_INFO("zoo_create ret = " + << ret + << ", create_path = " + << create_path<<"; create_path_tmp:"< +#include "cJSON.h" +} +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "base_errors_consts.h" +#include "zk_invoke_param.h" + +namespace meituan_mns { + +class ZkClient { + public: + ZkClient(); + ~ZkClient(); + //destroy object + void Destroy(); + + /** + * @param server : ip:port list + * @param zk_timeout : zookeeper_init rcv_timeout + * @param zk_retrytimes : times of zk retry-connection + * @return + */ + int ZkInit(ZkClient *zk_client, const std::string &server, const int zk_timeout, const int zk_retrytimes); + + /** + * @param request_ptr : zoo_get params + * @param response_ptr : result + * @return + */ + int ZkGet(const ZkGetRequestPtr &request_ptr, ZkGetResponsePtr &response_ptr); + + /** + * @param request_ptr : zoo_wget_children params + * @param response_ptr + * @return + */ + int ZkWgetChildren(const ZkWGetChildrenRequestPtr &request_ptr, ZkWGetChildrenResponsePtr &response_ptr); + + /** + * @param request_ptr : zk_wget params + * @param response_ptr + * @return + */ + int ZkWget(const ZkWGetRequestPtr &request_ptr, ZkWGetResponsePtr &response_ptr); + + /** + * @param request_ptr : zk_create params + * @return + */ + int ZkCreate(const ZkCreateRequestPtr &request_ptr); + + /** + *创建节点 + *@param agent_service,zk_path,json,regCmd,uptCmd + * + *@return int + * + **/ + int32_t ZkPathCreateRecursivly(std::string &zk_path); + + /** + * @param request_ptr : zk_set params + * @return + */ + int ZkSet(const ZkSetRequestPtr &request_ptr); + + /** + * @param request_ptr : zk_exists params + * @return + */ + int ZkExists(const ZkExistsRequestPtr &request_ptr); + + private: + int Connect2Zk(); + int CheckZkConn(); + int Reconnect2Zk(); + int ZkClose(); + + static void ConnWatcher(zhandle_t *zh, int type, int state, + const char *zk_path, void *watcher_ctx); + void RandSleep(); + + static ZkClient *zk_client_; + + zhandle_t *zk_handle_; + std::string zk_server_; + int zk_timeout_; + int zk_retrytimes_; + unsigned int rand_try_times_; + +}; + +} // namespace meituan_mns + +#endif //OCTO_OPEN_SOURCE_ZK_CLIENT_H diff --git a/sg_agent/src/mns/zk_client_pool.cc b/sg_agent/src/mns/zk_client_pool.cc new file mode 100644 index 0000000..557fb44 --- /dev/null +++ b/sg_agent/src/mns/zk_client_pool.cc @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "zk_client_pool.h" +#include "inc_comm.h" +#include "log4cplus.h" + +namespace meituan_mns { +muduo::MutexLock ZkClientPool::zk_client_mutex_; +ZkClientPool *ZkClientPool::zk_client_instance_ = NULL; + +const int kMaxZkClientNums = 10; + +ZkClientPool::ZkClientPool() : started_(false), + next_(0), + zk_client_nums_(0) { + +} +ZkClientPool *ZkClientPool::GetInstance() { + + if (NULL == zk_client_instance_) { + muduo::MutexLockGuard lock(zk_client_mutex_); + if (NULL == zk_client_instance_) { + zk_client_instance_ = new ZkClientPool(); + } + } + return zk_client_instance_; +} + +ZkClientPool::~ZkClientPool() { + assert(started_); + for (int i = 0; i < zk_client_pools_.size(); ++i) { + SAFE_DELETE(zk_client_pools_[i]); + } +} + +int ZkClientPool::Init(const std::string &server, const int zk_client_nums, + const int zk_timeout, const int zk_retrytimes) { + //assert(!started_); + if (server.empty()) { + NS_LOG_ERROR("zk_server list is empty."); + return -1; + } + zk_client_nums_ = zk_client_nums > kMaxZkClientNums ? + kMaxZkClientNums : zk_client_nums; + for (int i = 0; i < zk_client_nums_; ++i) { + ZkClient *zk_client = new ZkClient(); + int ret = zk_client->ZkInit(zk_client, server, zk_timeout, zk_retrytimes); + if (0 != ret) { + NS_LOG_ERROR("failed to init zk."); + continue; + } + zk_client_pools_.push_back(zk_client); + } + if (zk_client_pools_.empty()) { + NS_LOG_ERROR("zk_client_pools is empty, server = " + << server << " , zk_client num = " + << zk_client_nums); + return -1; + } + started_ = true; + return 0; +} + +ZkClient *ZkClientPool::GetZkClient() { + assert(started_); + ZkClient *zk_client = NULL; + if (!zk_client_pools_.empty()) { + zk_client = zk_client_pools_[next_]; + ++next_; + next_ = static_cast(next_) >= zk_client_pools_.size() ? 0 : next_; + } + return zk_client; +} + +ZkClient *ZkClientPool::GetZkClientForHash(size_t hash_code) { + assert(started_); + ZkClient *zk_client = NULL; + if (!zk_client_pools_.empty()) { + zk_client = zk_client_pools_[hash_code % zk_client_pools_.size()]; + } + return zk_client; +} +} // namespace meituan_mns diff --git a/sg_agent/src/mns/zk_client_pool.h b/sg_agent/src/mns/zk_client_pool.h new file mode 100644 index 0000000..d1aa271 --- /dev/null +++ b/sg_agent/src/mns/zk_client_pool.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_ZK_CLIENT_POOL_H +#define OCTO_OPEN_SOURCE_ZK_CLIENT_POOL_H +#include +#include "zk_client.h" + +namespace meituan_mns { +class ZkClientPool { + public: + + static ZkClientPool *GetInstance(); + /** + * @param server : ip:port list + * @param zk_client_num < 10 + * @param zk_timeout : zookeeper_init rcv_timeout + * @param zk_retrytimes : times of zk retry-connection + * @return + */ + int Init(const std::string &server, const int zk_client_nums, + const int zk_timeout, const int zk_retrytimes); + + ZkClient *GetZkClient(); + + ZkClient *GetZkClientForHash(size_t hash_cade); + + bool started() const { return started_; } + + private: + ZkClientPool(); + ~ZkClientPool(); + bool started_; + int zk_client_nums_; + int next_; + std::vector zk_client_pools_; + + static ZkClientPool *zk_client_instance_; + static muduo::MutexLock zk_client_mutex_; + +}; + +} // namespace meituan_mns +#endif //OCTO_OPEN_SOURCE_ZK_CLIENT_POOL_H diff --git a/sg_agent/src/mns/zk_invoke_param.h b/sg_agent/src/mns/zk_invoke_param.h new file mode 100644 index 0000000..0e4320f --- /dev/null +++ b/sg_agent/src/mns/zk_invoke_param.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_ZK_PARAM_H +#define OCTO_OPEN_SOURCE_ZK_PARAM_H +#include +#include +#include "naming_service_types.h" +#include "unified_protocol_types.h" + +extern "C" { +#include +#include "cJSON.h" +} +#include +#include +namespace meituan_mns { +typedef struct ZkGetRequest { + std::string path; + int watch; + ZkGetRequest() : path(""), watch(0) {} +} ZkGetRequest; + +typedef boost::shared_ptr ZkGetRequestPtr; + +typedef struct ZkGetResponse { + std::string buffer; + int buffer_len; + struct Stat stat; + ZkGetResponse() : buffer(""), buffer_len(0) {} +} ZkGetResponse; + +typedef boost::shared_ptr ZkGetResponsePtr; + +typedef struct ZkWGetRequest { + std::string path; + watcher_fn watch; + void *watcherCtx; +} ZkWGetRequest; + +typedef boost::shared_ptr ZkWGetRequestPtr; + +typedef struct ZkWGetResponse { + std::string buffer; + int buffer_len; + struct Stat stat; +} ZkWGetResponse; + +typedef boost::shared_ptr ZkWGetResponsePtr; + +typedef struct ZkWGetChildrenRequest { + std::string path; + watcher_fn watch; + void *watcherCtx; +} ZkWGetChildrenRequest; + +typedef boost::shared_ptr ZkWGetChildrenRequestPtr; + +typedef struct ZkWGetChildrenResponse { + int count; + std::vector data; +} ZkWGetChildrenResponse; + +typedef boost::shared_ptr ZkWGetChildrenResponsePtr; + +typedef struct ZkCreateRequest { + std::string path; + std::string value; + int value_len; +} ZkCreateRequest; + +typedef boost::shared_ptr ZkCreateRequestPtr; + +typedef struct ZkSetRequest { + std::string path; + std::string buffer; + int version; +} ZkSetRequest; + +typedef boost::shared_ptr ZkSetRequestPtr; + +typedef struct ZkExistsRequest { + std::string path; + int watch; +} ZkExistsRequest; + +typedef boost::shared_ptr ZkExistsRequestPtr; + +typedef struct ZkCreateInvokeParams { + ZkCreateRequest zk_create_request; + int zk_create_response; +} ZkCreateInvokeParams; + +typedef struct ZkGetInvokeParams { + ZkGetRequest zk_get_request; + ZkGetResponse zk_get_response; +} ZkGetInvokeParams; + +typedef struct GetMnsCacheParams { + std::string appkey; + std::string version; + std::string env; + std::string protocol; +} GetMnsCacheParams; + + +typedef struct SubGetServiceParams { + ZkWGetChildrenResponsePtr wg_child_params; + int32_t index; + std::string provider_path; + std::string remote_appkey; +} SubGetServiceParams; + +typedef struct SubGetServiceRes { + std::vector srvlist; + bool is_ok; + SubGetServiceRes() : is_ok(true) {} +} SubGetServiceRes; +typedef boost::shared_ptr SubGetServiceResPtr; +} +#endif // OCTO_OPEN_SOURCE_ZK_PARAM_H diff --git a/sg_agent/src/remote/monitor/monitor_collector.cc b/sg_agent/src/remote/monitor/monitor_collector.cc new file mode 100644 index 0000000..0ab966c --- /dev/null +++ b/sg_agent/src/remote/monitor/monitor_collector.cc @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "monitor_collector.h" +#include "base_consts.h" + +using namespace meituan_mns; + + +MonitorCollector *MonitorCollector::monitor_collector_ = NULL; +muduo::MutexLock MonitorCollector::monitor_collector_lock_; + +MonitorCollector *MonitorCollector::GetInstance() { + if (NULL == monitor_collector_) { + muduo::MutexLockGuard lock(monitor_collector_lock_); + if (NULL == monitor_collector_) { + monitor_collector_ = new MonitorCollector(); + } + } + return monitor_collector_; +} + +float MonitorCollector::CalcuProcCpuUtil(const int& pid) { + + float proc_cpu_util = 0.0; + unsigned long total_cpu_delta = GetTotalCpuTime() - cpu_jiff_value_.total_cpu_delta; + unsigned long proc_cpu_delta = GetProcCpuTime(pid) - cpu_jiff_value_.proc_cpu_delta; + NS_LOG_INFO("proc_cpu_delta: " << proc_cpu_delta << "total_cpu_delta: " << total_cpu_delta); + std::string test_cpu = ""; + if (0 != total_cpu_delta) { + proc_cpu_util = (float) (100 * sysconf(_SC_NPROCESSORS_CONF) * proc_cpu_delta) / (float) total_cpu_delta; + cpu_jiff_value_.total_cpu_delta = GetTotalCpuTime(); + cpu_jiff_value_.proc_cpu_delta = GetProcCpuTime(pid); + NS_LOG_INFO("the sg_agent proc cpu util: " << proc_cpu_util); + } else { + NS_LOG_ERROR("it is first to calcu proc cpu util,value is empty"); + } + + NS_LOG_INFO("the sg_agent proc cpu util: " << Round(proc_cpu_util, 2)); + return Round(proc_cpu_util, 2); +} +int MonitorCollector::DoInitMonitorInfo() { + + if (!has_init_) { + metric_value_[PID_ITEM] = "sg_agent.pid"; + metric_value_[VMRSS_ITEM] = "sg_agent.vmRss"; + metric_value_[VERSION_ITEM] = "sg_agent.version"; + metric_value_[CPU_ITEM] = "sg_agent.cpu"; + metric_value_[FILECONFIG_ITEM] = "sg_agent.fileConfigQueueLen"; + metric_value_[KVCONFIG_ITEM] = "sg_agent.kvConfigQueueLen"; + metric_value_[COMMON_LOG_ITEM] = "sg_agent.logQueueLen"; + metric_value_[ROUTE_LIST_ITEM] = "sg_agent.routeListQueueLen"; + metric_value_[SERVICE_LIST_ITEM] = "sg_agent.serviceListQueueLen"; + metric_value_[MODULE_INVOKER_ITEM] = "sg_agent.invokerQueueLen"; + metric_value_[REGISTER_ITEM] = "sg_agent.registerQueueLen"; + metric_value_[MCC_FCONFIG_ALLREQ_ITEM] = "sg_agent.mccFileConfigAllReq"; + metric_value_[MCC_FCONFIG_SUCCESSREQ_ITEM] = "sg_agent.mccFileConfigSuccessReq"; + metric_value_[MCC_CONFIG_ALLREQ_ITEM] = "sg_agent.mccAllReq"; + metric_value_[MCC_CONFIG_SUCCESSREQ_ITEM] = "sg_agent.mccSucessReq"; + metric_value_[MNSC_ALLREQ_ITEM] = "sg_agent.mnscAllReq"; + metric_value_[MNSC_SUCCESSREQ_ITEM] = "sg_agent.mnscSuccessReq"; + cpu_jiff_value_.proc_cpu_delta = GetProcCpuTime(getpid()); + cpu_jiff_value_.total_cpu_delta = GetTotalCpuTime(); + + GetEndPoint(end_point_); + has_init_ = true; + } + return SUCCESS; +} +int MonitorCollector::GetCollectorMonitorInfo(std::string &mInfo) { + + DoInitMonitorInfo(); + + char *out; + cJSON *json = cJSON_CreateObject(); + if (!json) { + NS_LOG_ERROR("json is NULL, create json_object failed."); + return FAILURE; + } + cJSON *all_info_json = cJSON_CreateArray(); + if (!all_info_json) { + NS_LOG_ERROR("all_srvlist_json is NULL, create json_object failed."); + cJSON_AddNumberToObject(json, "ret", HTTP_INNER_ERROR); + mInfo = cJSON_Print(json); + cJSON_Delete(json); + return FAILURE; + } + cJSON_AddNumberToObject(json, "ret", HTTP_RESPONSE_OK); + cJSON_AddStringToObject(json, "retMsg", "success"); + + //CountRequest::GetInstance()->GetReqData(monitor_data_); + for (int iter = 0; iter <= MAX_MONITOER_ITEM; iter++) { + CollectorInfo2Json(json, all_info_json, iter); + } + cJSON_AddItemToObject(json, "data", all_info_json); + out = cJSON_Print(json); + mInfo = out; + SAFE_FREE(out); + cJSON_Delete(json); + NS_LOG_INFO("CollectorInfo2Json success"); + + return SUCCESS; +} +int64_t MonitorCollector::GetTimeStamp() { + + timeval cur_time; + gettimeofday(&cur_time, NULL); + + return ((int64_t) cur_time.tv_sec); + +} +void MonitorCollector::GetEndPoint(std::string &end_point) { + + char host_name[256] = {0}; + gethostname(host_name, sizeof(host_name)); + std::string host_name_str(host_name); + NS_LOG_INFO("end point" << host_name_str); + end_point = (std::string::npos != host_name_str.find(".octo.com") + || std::string::npos != host_name_str.find(".office.mos")) ? host_name_str.substr(0, host_name_str.find(".")) + : host_name_str; + if (end_point.empty() || "unknown" == end_point) { + NS_LOG_WARN("fail to init monitor endpoint"); + } +} +int MonitorCollector::CollectorInfo2Json(cJSON *json, cJSON *json_arrary, int type) { + + if (NULL == json || NULL == json_arrary) { + NS_LOG_ERROR("the json object is null"); + return FAILURE; + } + std::string mon_info = ""; + cJSON *root; + char *out; + root = cJSON_CreateObject(); + if (NULL == root) { + NS_LOG_ERROR("the create json object is failed"); + return FAILURE; + } + cJSON_AddStringToObject(root, "endpoint", end_point_.c_str()); + cJSON_AddStringToObject(root, "metric", metric_value_.at(type).c_str()); + cJSON_AddNumberToObject(root, "timestamp", GetTimeStamp()); + cJSON_AddNumberToObject(root, "step", 60); + SetValueByType(root, type); + cJSON_AddStringToObject(root, "counterType", "GAUGE"); + cJSON_AddStringToObject(root, "tags", "sg_agent"); + out = cJSON_Print(root); + mon_info = out; + SAFE_FREE(out); + cJSON_AddItemToArray(json_arrary, root); + + return SUCCESS; + +} +void MonitorCollector::SetValueByType(cJSON *root, int type) { + + pid_t sg_pid = getpid(); + switch (type) { + case PID_ITEM: { + cJSON_AddNumberToObject(root, "value", getpid()); + break; + } + case VMRSS_ITEM: { + cJSON_AddNumberToObject(root, "value", GetProcMemUtil(sg_pid)); + break; + } + case VERSION_ITEM: { + cJSON_AddStringToObject(root, "value", CXmlFile::GetStrPara + (CXmlFile::AgentVersion).c_str()); + break; + } + case CPU_ITEM: { + cJSON_AddNumberToObject(root, "value", CalcuProcCpuUtil(sg_pid)); + break; + } + case FILECONFIG_ITEM: { + cJSON_AddNumberToObject(root, "value", FalconMgr::GetFileConfigQueueSize()); + break; + } + case KVCONFIG_ITEM: { + cJSON_AddNumberToObject(root, "value", FalconMgr::GetKvConfigQueueSize()); + break; + } + case COMMON_LOG_ITEM: { + cJSON_AddNumberToObject(root, "value", FalconMgr::GetCommonLogQueueSize()); + break; + } + case ROUTE_LIST_ITEM: { + cJSON_AddNumberToObject(root, "value", FalconMgr::GetRouteListQueueSize()); + break; + } + case SERVICE_LIST_ITEM: { + cJSON_AddNumberToObject(root, "value", FalconMgr::GetServiceListQueueSize()); + break; + } + case MODULE_INVOKER_ITEM: { + cJSON_AddNumberToObject(root, "value", FalconMgr::GetModuleInvokerQueueSize()); + break; + } + case REGISTER_ITEM: { + cJSON_AddNumberToObject(root, "value", FalconMgr::GetRegisteQueueSize()); + break; + } + case MCC_FCONFIG_ALLREQ_ITEM: { + cJSON_AddNumberToObject(root, "value", monitor_data_.at("allfconfig")); + break; + } + case MCC_FCONFIG_SUCCESSREQ_ITEM: { + cJSON_AddNumberToObject(root, "value", monitor_data_.at("fconfig")); + break; + } + case MCC_CONFIG_ALLREQ_ITEM: { + cJSON_AddNumberToObject(root, "value", monitor_data_.at("allconfig")); + break; + } + case MCC_CONFIG_SUCCESSREQ_ITEM: { + cJSON_AddNumberToObject(root, "value", monitor_data_.at("config")); + break; + } + case MNSC_ALLREQ_ITEM: { + cJSON_AddNumberToObject(root, "value", monitor_data_.at("allmnsc")); + break; + } + case MNSC_SUCCESSREQ_ITEM: { + cJSON_AddNumberToObject(root, "value", monitor_data_.at("mnsc")); + break; + } + default: { + NS_LOG_INFO("unkown collector type"); + } + } +} + diff --git a/sg_agent/src/remote/monitor/monitor_collector.h b/sg_agent/src/remote/monitor/monitor_collector.h new file mode 100644 index 0000000..32b4d23 --- /dev/null +++ b/sg_agent/src/remote/monitor/monitor_collector.h @@ -0,0 +1,76 @@ +/** + * xxx is + * Copyright (C) 20xx THL A29 Limited, a xxx company. All rights reserved. + * + * Licensed under the xxx + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#ifndef OCTO_SRC_MONITOR_COLLECTOR_H +#define OCTO_SRC_MONITOR_COLLECTOR_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cJSON.h" +#include "config_loader.h" +#include "falcon_mgr.h" +#include "inc_comm.h" + + +namespace meituan_mns { + +typedef struct cpu_util{ + + unsigned long total_cpu_delta; + unsigned long proc_cpu_delta; + cpu_util(){total_cpu_delta = 0.0;proc_cpu_delta = 0.0;}; +}cpu_util_t; + +class MonitorCollector { + + private: + MonitorCollector() : has_init_(false), + end_point_(""), + agent_pid_(""), + monitor_data_(boost::unordered_map()) {}; + public: + ~MonitorCollector() {}; + static MonitorCollector *GetInstance(); + int DoInitMonitorInfo(); + int GetCollectorMonitorInfo(std::string &mInfo); + int CollectorInfo2Json(cJSON *json, cJSON *json_arrary, int type); + float CalcuProcCpuUtil(const int& pid); + + private: + void SetValueByType(cJSON *root,int type); + void GetEndPoint(std::string &value); + int64_t GetTimeStamp(); + + + static MonitorCollector *monitor_collector_; + static muduo::MutexLock monitor_collector_lock_; + std::map metric_value_; + bool has_init_; + std::string end_point_; + std::string agent_pid_; + cpu_util_t cpu_jiff_value_; + boost::unordered_map monitor_data_; +}; + +} +#endif //OCTO_SRC_MONITOR_COLLECTOR_H diff --git a/sg_agent/src/rule/route_base.cc b/sg_agent/src/rule/route_base.cc new file mode 100644 index 0000000..a22f475 --- /dev/null +++ b/sg_agent/src/rule/route_base.cc @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "route_base.h" +#include "../comm/inc_comm.h" + +namespace meituan_mns { + +void IDC::CalculateIpMask() { + int_mask_ = ConvertMaskToInt(); + ip_mask_value_ = int_mask_ & GetIp4Value(ip_); +} + +bool IDC::IsSameIdc(const std::string &ip) { + return ip_mask_value_ == (int_mask_ & GetIp4Value(ip)); +} + +int32_t IDC::ConvertMaskToInt() { + std::vector vnum; + SplitStringIntoVector(mask_.c_str(), ".", vnum); + if (4 != vnum.size()) { + return FAILURE; + } + + int32_t iMask = 0; + for (int i = 0; i < 4; ++i) { + iMask += (atoi(vnum[i].c_str()) << ((3 - i) * 8)); + } + return iMask; +} + +int32_t IDC::GetIp4Value(const std::string &ip) { + std::vector vcIp; + SplitStringIntoVector(ip.c_str(), ".", vcIp); + if (4 != vcIp.size()) { + return FAILURE; + } + int address = 0; + int filter_num = 0xFF; + for (int i = 0; i < 4; i++) { + int pos = i * 8; + int vIp = atoi(vcIp[3 - i].c_str()); + address |= ((vIp << pos) & (filter_num << pos)); + } + return address; +} + +void IDC::SetRegion(const std::string &val) { + region_ = val; +} +std::string IDC::GetRegion() const { + return region_; +} + +void IDC::SetIdc(const std::string &val) { + idc_ = val; +} +std::string IDC::GetIdc() const { + return idc_; +} + +void IDC::SetCenter(const std::string &val) { + center_ = val; +} +std::string IDC::GetCenter() const { + return center_; +} + +void IDC::SetIp(const std::string &val) { + ip_ = val; +} +std::string IDC::GetIp() const { + return ip_; +} + +void IDC::SetMask(const std::string &val) { + mask_ = val; +} +std::string IDC::GetMask() const { + return mask_; +} + +} diff --git a/sg_agent/src/rule/route_base.h b/sg_agent/src/rule/route_base.h new file mode 100644 index 0000000..84bf0c6 --- /dev/null +++ b/sg_agent/src/rule/route_base.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef PROJECT_ROUTE_BASE_H +#define PROJECT_ROUTE_BASE_H +#include +#include +namespace meituan_mns { + +class IDC { + public: + void CalculateIpMask(void); + + IDC() : region_(""), + idc_(""), + center_ (""), + ip_ (""), + mask_(""), + int_mask_(0), + ip_mask_value_(0) {} + + void SetRegion(const std::string &val); + std::string GetRegion(void) const; + + void SetIdc(const std::string &val); + std::string GetIdc(void) const; + + void SetCenter(const std::string &val); + std::string GetCenter(void) const; + + void SetIp(const std::string &val); + std::string GetIp(void) const; + + void SetMask(const std::string &val); + std::string GetMask(void) const; + + bool IsSameIdc(const std::string &ip); + + private: + int32_t ConvertMaskToInt(void); + int32_t GetIp4Value(const std::string &ip); + + private: + std::string region_; + std::string idc_; + std::string center_; + std::string ip_; + std::string mask_; + + int32_t int_mask_; + int32_t ip_mask_value_; + +}; +} + +#endif //PROJECT_ROUTE_BASE_H diff --git a/sg_agent/src/rule/route_info.cc b/sg_agent/src/rule/route_info.cc new file mode 100644 index 0000000..ac088b6 --- /dev/null +++ b/sg_agent/src/rule/route_info.cc @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "route_info.h" +#include "comm/tinyxml2.h" +#include "log4cplus.h" +#include "comm/inc_comm.h" +#include +namespace meituan_mns { + + +bool IdcUtil::IsSameIdc(const boost::shared_ptr &idc1, const boost::shared_ptr &idc2) { + return idc1->GetIdc() == idc2->GetIdc(); +} + +bool IdcUtil::IsSameCenter(const boost::shared_ptr &idc1, const boost::shared_ptr &idc2) { + // exclude NOCENTER + // NOCENTER不算做一个中心来处理 + return ("NOCENTER" != idc1->GetCenter()) && (idc1->GetCenter() == idc2->GetCenter()); +} +bool IdcUtil::IsInIdcs(const std::string &ip){ + + NS_LOG_INFO("the local ip = "<< ip); + + boost::shared_ptr local_idc = IdcUtil::GetIdc(ip); + if (NULL == local_idc.get()) { + NS_LOG_ERROR("fail to the idc info of local ip = " << ip); + return false; + } + if (local_idc->GetIdc().empty()) { + return false; + } + return true; +} +boost::shared_ptr IdcUtil::GetIdc(const std::string &ip) { + + boost::shared_ptr > > idcs_tmp; + idcs_tmp = CXmlFile::GetIdc(); + for (std::vector >::const_iterator iter = idcs_tmp->begin(); + idcs_tmp->end() != iter; ++iter) { + if ((*iter)->IsSameIdc(ip)) { + return *iter; + } + } + return boost::make_shared(); +} + +std::string IdcUtil::GetSameIdcZk(const std::string &zk_host, + const std::string &ip) { + std::vector vec_str; + int32_t ret = SplitStringIntoVector(zk_host.c_str(), "," , vec_str); + if (0 >= ret) { + NS_LOG_ERROR("failed to split zk_host to vector, zk_host: " << zk_host); + return zk_host; + } + + boost::shared_ptr ip_idc = GetIdc(ip); + + std::vector vec_res; + if (NULL != ip_idc.get()) { + for (std::vector::const_iterator iter = vec_str.begin(); + iter != vec_str.end(); ++iter) { + + boost::shared_ptr item_idc = GetIdc(*iter); + if (IsSameIdc(item_idc, ip_idc)) { + vec_res.push_back(*iter); + } + } + } else { + NS_LOG_ERROR("fail to get the idc info of ip = " << ip); + } + + std::string res; + if (vec_res.empty()) { + res = zk_host; + } else { + res = vec_res[0]; + for (std::vector::const_iterator iter = vec_res.begin() + 1; + iter != vec_res.end(); ++iter) { + res += "," + *iter; + } + } + return res; +} + +} diff --git a/sg_agent/src/rule/route_info.h b/sg_agent/src/rule/route_info.h new file mode 100644 index 0000000..bebc8ff --- /dev/null +++ b/sg_agent/src/rule/route_info.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef PROJECT_ROUTE_INFO_H +#define PROJECT_ROUTE_INFO_H +#include +#include +#include +#include +#include "route_base.h" +#include "../comm/inc_comm.h" +#include +#include "../mns/config_loader.h" + +namespace meituan_mns { + +class IdcUtil { + public: + static boost::shared_ptr GetIdc(const std::string &ip); + /** + * + * @param idc1 + * @param idc2 + * @return + */ + static bool IsSameIdc(const boost::shared_ptr &idc1, + const boost::shared_ptr &idc2); + /** + * + * @param idc1 + * @param idc2 + * @return + */ + static bool IsSameCenter(const boost::shared_ptr &idc1, + const boost::shared_ptr &idc2); + + static bool IsInIdcs(const std::string &ip); + + /** + * + * @param zk_host + * @param ip + * @return + */ + static std::string GetSameIdcZk(const std::string &zk_host, + const std::string &ip); + + +}; + +} + + + +#endif //PROJECT_ROUTE_INFO_H diff --git a/sg_agent/src/rule/route_rule.cc b/sg_agent/src/rule/route_rule.cc new file mode 100644 index 0000000..6a1c56d --- /dev/null +++ b/sg_agent/src/rule/route_rule.cc @@ -0,0 +1,622 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include "boost/lambda/lambda.hpp" +#include "route_rule.h" +#include + +#include "../gen-cpp/naming_common_types.h" + +namespace meituan_mns { + + +const static std::string LIMIT_KEY = "route_limit"; +const static std::string LIMIT_VALUE = "1"; +const static std::string UNLIMIT_VALUE = "0"; + +// 启用本机房过滤的权重 +const static double SameRegionMod = 0.001; +const static double DiffRegionMod = 0.000001; +const static double DoublePrecision = 0.000001; + +bool RouteRule::IsMatchWeight(const SGService &service, + double thresholdWeight) { + if (thresholdWeight - service.fweight >= DoublePrecision) { + NS_LOG_DEBUG("filterWeight is 0, appkey = " + << service.appkey + << " status : " << service.status + << " role : " << service.role + << " ip : " << service.ip.c_str()); + return true; + } + return false; +} + +int32_t RouteRule::FilterWeight(std::vector &serviceList, + double thresholdWeight) { + std::vector serviceList_tmp; + serviceList_tmp = serviceList; + + //删除weight = 0 的节点 + serviceList_tmp.erase(std::remove_if(serviceList_tmp.begin(),serviceList_tmp.end(), + boost::bind(&RouteRule::IsMatchWeight,_1,thresholdWeight)), + serviceList_tmp.end()); + + if (serviceList_tmp.size() != serviceList.size() + && serviceList_tmp.size() != 0) { + serviceList = serviceList_tmp; + return 0; + } + + // 表示过滤后的结果为空, 保留原值 + return -1; +} + +bool RouteRule::IsHost(const SGService &service, bool *alive_flag) { + if (0 != service.role) { + NS_LOG_DEBUG("filterBackup, appkey = " << service.appkey + << " status : " << service.status + << " role : " << service.role + << " ip : " << service.ip.c_str()); + return true; + } + if (!(*alive_flag) && fb_status::ALIVE == service.status) { + *alive_flag = true; + } + return false; +} + +int32_t RouteRule::FilterBackup(std::vector &serviceList) { + std::vector serviceList_tmp = serviceList; + bool is_master_alive = false; + serviceList.erase(std::remove_if(serviceList.begin(), + serviceList.end(), + boost::bind(&RouteRule::IsHost, _1, + &is_master_alive)), + serviceList.end()); + + //如果tmp中节点信息与原来节点数不同,且至少存在一个alive节点 + //则进行copy更新serviceList; + //如果tmp节点数为0了, 或者没有alive节点 + //则返回原来所有节点,包括备份节点 + if (serviceList.empty() || !is_master_alive) { + //所有主节点不可用是小概率case,因此代码低概率执行,避免memory copy + serviceList = serviceList_tmp; + } + + return 0; +} + +bool RouteRule::IsUnAliveService(const SGService &service) { + if (service.status != fb_status::ALIVE) { + NS_LOG_INFO("filterUnAlive servicee is not alive, appkey = " + << service.appkey + << " status : " + << service.status + << " role : " + << service.role + << " ip : " + << service.ip.c_str()); + return true; + } + return false; +} + +int32_t RouteRule::FilterUnAlive(std::vector &serviceList) { + serviceList.erase(std::remove_if(serviceList.begin(), serviceList.end(), + boost::bind(&RouteRule::IsUnAliveService, _1)), + serviceList.end()); + + return 0; +} + +bool RouteRule::HasAliveNode(std::vector &serviceList) { + for (std::vector::iterator iter = serviceList.begin(); + iter != serviceList.end(); ++iter) { + if (fb_status::ALIVE == iter->status) { + return true; + } + } + return false; +} + +/* + * 对于192.168.0.196:*这类host,过滤带port的host + */ +bool RouteRule::RegexFilterPort(const std::string ®ex_ip, const std::string &local_ip) { + NS_LOG_DEBUG("RegexFilterPort input param: regex_ip: " << regex_ip << " localIp: " << local_ip); + //对于ip地址第4位以及端口进行切分,例如: 196:8890 + std::vector regex_ip_vec; + SplitStringIntoVector(regex_ip.c_str(), ":", regex_ip_vec); + + if (2 != regex_ip_vec.size()) { + NS_LOG_WARN("regex_ip =" << regex_ip << "is error"); + return false; + } + + std::vector local_ip_vec; + SplitStringIntoVector(local_ip.c_str(), ":", local_ip_vec); + + if (RegexFilterIp(regex_ip_vec[0], local_ip_vec[0])) { + if ("*" == regex_ip_vec[1] || "*\"" == regex_ip_vec[1] || regex_ip_vec[1] + == local_ip_vec[1]) { + NS_LOG_INFO("filter ip OK, filter port OK!"); + return true; + } + } + + return false; +} + +bool RouteRule::IsMatchIdcRule(SGService &service, + boost::shared_ptr local_idc) { + + return !IdcUtil::IsSameIdc(local_idc, IdcUtil::GetIdc(service.ip)); +} + +/** + * 同机房优先规则处理流程 + */ +int32_t RouteRule::FilterSameIdc(std::vector &serviceList, + boost::shared_ptr local_idc, + bool routeLimit) { + if (routeLimit) { + serviceList.erase(std::remove_if(serviceList.begin(),serviceList.end(), + boost::bind(&RouteRule::IsMatchIdcRule, + _1, local_idc)), + serviceList.end()); + } else { + std::vector::iterator iter = serviceList.begin(); + for (; serviceList.end() != iter; ++iter) { + boost::shared_ptr idc_item = IdcUtil::GetIdc(iter->ip); + //idc_item 智能指针的判断合法性,没有意义 + if (IdcUtil::IsSameIdc(local_idc, idc_item)) { + continue; + }else if (local_idc->GetRegion() == idc_item->GetRegion()) { + iter->fweight *= SameRegionMod; + } else { + iter->fweight *= DiffRegionMod; + } + } + } +} + +bool RouteRule::IsMatchCenterRule(SGService &service, + boost::shared_ptr local_idc) { + + return !IdcUtil::IsSameCenter(local_idc, IdcUtil::GetIdc(service.ip)); +} + + +int32_t RouteRule::FilterSameCenter(std::vector &serviceList, + boost::shared_ptr local_idc, + bool routeLimit) { + if (routeLimit) { + serviceList.erase(std::remove_if(serviceList.begin(),serviceList.end(), + boost::bind(&RouteRule::IsMatchCenterRule, + _1, local_idc)), + serviceList.end()); + } else { + std::vector::iterator iter = serviceList.begin(); + for (; serviceList.end() != iter; ++iter) { + boost::shared_ptr idc_item = IdcUtil::GetIdc(iter->ip); + //idc_item 智能指针的判断合法性,没有意义 + if (IdcUtil::IsSameCenter(local_idc, idc_item)) { + continue; + } else if (local_idc->GetRegion() == idc_item->GetRegion()) { + iter->fweight *= SameRegionMod; + } else { + iter->fweight *= DiffRegionMod; + } + } + } +} + +bool RouteRule::IsMatchRegionRule(SGService &service, + boost::shared_ptr local_idc) { + boost::shared_ptr idc_item = IdcUtil::GetIdc(service.ip); + return local_idc->GetRegion() != idc_item->GetRegion(); +} + + +int32_t RouteRule::FilterSameRegion(std::vector &serviceList, + boost::shared_ptr local_idc, + bool routeLimit) { + if (routeLimit) { + serviceList.erase(std::remove_if(serviceList.begin(),serviceList.end(), + boost::bind(&RouteRule::IsMatchRegionRule, + _1, local_idc)), + serviceList.end()); + } else { + std::vector::iterator iter = serviceList.begin(); + for (; serviceList.end() != iter; ++iter) { + boost::shared_ptr idc_item = IdcUtil::GetIdc(iter->ip); + //无需idc_item 智能指针的判断合法性,没有意义 + if (local_idc->GetRegion() == idc_item->GetRegion()) { + continue; + } else { + iter->fweight *= DiffRegionMod; + } + } + } +} + +bool RouteRule::FilterHost(const std::string ®ex_ip, + const std::string &local_ip) { + NS_LOG_DEBUG("FilterHost input param: re_ip: " << regex_ip + << " localIp: " << local_ip); + //首先判断host格式是否为,192.168.1.196:8890 + std::vector re_ip_vec; + SplitStringIntoVector(regex_ip.c_str(), ":", re_ip_vec); + + //对于格式为, ip:port的host,单独过滤下port + if (2 == re_ip_vec.size()) { + if (RegexFilterPort(regex_ip, local_ip)) { + NS_LOG_DEBUG("RegexFilterPort OK! filter host is: " << regex_ip + << " local host is: " + << local_ip); + return true; + } + } else { + if (RegexFilterIp(regex_ip, local_ip)) { + NS_LOG_DEBUG("RegexFilterIp OK! filter IP is: " << regex_ip + << " local IP is: " + << local_ip); + return true; + } + } + + return false; +} + +bool RouteRule::RegexFilterIp(const std::string &reIp, const std::string &localIp) { + //对于格式仅为IP的,分组ip中带*号的ip进行过滤 + std::vector vecLocal; + SplitStringIntoVector(localIp.c_str(), ".", vecLocal); + + std::vector vecRe; + SplitStringIntoVector(reIp.c_str(), ".", vecRe); + + if (vecRe.size() == 1) { + if (vecRe[0] == "\"*\"" or vecRe[0] == "*" or vecRe[0] == "\"*") + return true; + } else if (vecRe.size() == 2) { + if ((((vecRe[0] == "\"*") or (vecRe[0] == "*")) + and (vecRe[1] == "*" or vecRe[1] == "*\"")) + or ((vecRe[0] == vecLocal[0]) + and ((vecRe[1] == "*\"") or (vecRe[1] == "*")))) + return true; + } else if (vecRe.size() == 3) { + if (((vecRe[2] == "*\"" or vecRe[2] == "*") + and (vecRe[0] == vecLocal[0]) + and (vecRe[1] == vecLocal[1])) + or ((vecRe[2] == "*\"" or vecRe[2] == "*") + and (vecRe[0] == vecLocal[0]) + and (vecRe[1] == "*")) + or ((vecRe[2] == "*\"" or vecRe[2] == "*") + and (vecRe[0] == "*" or vecRe[0] == "\"*") + and (vecRe[1] == "*"))) + return true; + } else if (vecRe.size() == 4) { + if (((vecRe[3] == "*\"" or vecRe[3] == "*" + or vecRe[3] == vecLocal[3]) + and (vecRe[0] == vecLocal[0]) + and (vecRe[1] == vecLocal[1]) + and (vecRe[2] == vecLocal[2])) + or ((vecRe[3] == "*\"" or vecRe[3] == "*" + or vecRe[3] == vecLocal[3]) + and (vecRe[0] == vecLocal[0]) + and (vecRe[1] == vecLocal[1]) + and (vecRe[2] == "*")) + or ((vecRe[3] == "*\"" or vecRe[3] == "*" + or vecRe[3] == vecLocal[3]) + and (vecRe[0] == vecLocal[0]) + and (vecRe[1] == "*") + and (vecRe[2] == "*")) + or ((vecRe[3] == "*\"" or vecRe[3] == "*" + or vecRe[3] == vecLocal[3]) + and ((vecRe[0] == "*" or vecRe[0] == "\"*")) + and (vecRe[1] == "*") + and (vecRe[2] == "*"))) + return true; + } else { + NS_LOG_WARN("route consumer ip is: " << reIp.c_str() + << ", localIp is: " + << localIp.c_str()); + return false; + } + + return false; +} + +//consume列表过滤服务分组 +bool RouteRule::IsMatchConsumer(const CRouteData &route, + const std::string &local_ip) { + + //一期实现基于localIp过滤consume,appkey过滤暂时不考虑 + std::vector ips = route.consumer.ips; + for (std::vector::const_iterator iter = ips.begin(); + ips.end() != iter; ++iter) { + if ((*iter == local_ip) || FilterHost(*iter, local_ip)) { + NS_LOG_DEBUG("filterConsumer use ip = " << *iter); + return true; + } + } + + return false; +} + +//provide列表过滤服务分组 +bool RouteRule::FilterProvider(const CRouteData &route, const SGService &oservice) { + + //自定义分组,通过ip:port格式比对 + std::string ip_port_str = "\"" + oservice.ip + + ":" + boost::lexical_cast(oservice.port) + "\""; + + for (std::vector::const_iterator iter = route.provider.begin(); + route.provider.end() != iter; ++iter) { + if ((*iter == ip_port_str) || FilterHost(*iter, ip_port_str)) { + return true; + } + } + return false; +} + +/* + * 根据服务分组列表,过滤服务列表 + * */ +int32_t RouteRule::FilterRoute(std::vector &services, + const std::vector &sorted_routes, + const std::string &ip, + const bool route_flag, + const bool open_auto_route ){ + std::vector::const_iterator iter = sorted_routes.begin(); + std::vector::const_iterator end_iter = sorted_routes.end(); + //获取sg_agent的IP,用于过滤consumer, 初始化时已经获取到IP + std::string local_ip = "\"" + ip + "\""; + std::vector not_exclusive_routes = sorted_routes; + if (route_flag) { + NS_LOG_DEBUG("active original routes'size = " << sorted_routes.size()); + std::vector exclusive_routes; + + GetExclusiveRoute(not_exclusive_routes, exclusive_routes, true); + + bool is_local_ip_in_exclusive_routes = IsMatchRoutesConsumer( + exclusive_routes, local_ip); + if (!is_local_ip_in_exclusive_routes) { + FilterProvidersByExclusiveRoutes(services, exclusive_routes); + } + + iter = is_local_ip_in_exclusive_routes ? + sorted_routes.begin() : not_exclusive_routes.begin(); + end_iter = is_local_ip_in_exclusive_routes ? + sorted_routes.end() : not_exclusive_routes.end(); + } + + boost::shared_ptr local_idc = IdcUtil::GetIdc(ip); + //遍历服务分组列表,按照优先级从高到低依次遍历 + for (; iter != end_iter; ++iter) { + bool routeLimit = IsRouteLimit(*iter); + // 如果符合本机房过滤的条件, 进行本机房过滤 + switch (iter->category) { + case 1: + if (open_auto_route) { + FilterSameIdc(services, local_idc, routeLimit); + } + return SUCCESS; + case 3: + if (open_auto_route) { + FilterSameCenter(services, local_idc, routeLimit); + } + return SUCCESS; + case 5:{ + if (open_auto_route) { + FilterSameRegion(services, local_idc, routeLimit); + } + return SUCCESS; + } + case 4: + default: + + // 先匹配comsumer:如果consumer都没匹配到,则应用下一条route规则 + // 否则应用该规则, 不论结果是否为空, 都跳出循环 + if (!IsMatchConsumer(*iter, local_ip)) { + break; + } + NS_LOG_DEBUG("filter route OK! using route name is : " + << iter->name + << ", priority is : " << iter->priority); + + std::vector serviceList_tmp; + //再过滤provide,如果为空则返回所有service + for (std::vector::iterator vec = services.begin(); + vec != services.end(); ++vec) { + //如果route中匹配到,则添加此provider到tmp + if (FilterProvider(*iter, *vec)) { + SGService service_tmp = *vec; + serviceList_tmp.push_back(service_tmp); + } else { + if (!routeLimit) { + SGService service_tmp = *vec; + service_tmp.weight = 0; + service_tmp.fweight *= SameRegionMod; + serviceList_tmp.push_back(service_tmp); + } + } + } + + services = serviceList_tmp; + return SUCCESS; + } + } + + return SUCCESS; +} + +bool RouteRule::IsAliveRoute(const CRouteData &route) { + return 1 != route.status; +} + +/* + * 根据服务分组优先级排序,并且过滤掉下线状态的服务分组 + * */ +int32_t RouteRule::SortRouteList(std::vector &routeList) { + if (routeList.empty()) { + NS_LOG_WARN("routeList is empty"); + return -1; + } + //首先过滤掉status!=1的分组 + routeList.erase(std::remove_if(routeList.begin(),routeList.end(), + boost::bind(&RouteRule::IsAliveRoute,_1)), + routeList.end()); + + if (routeList.size() == 0) { + return -1; + } + + //对routList按照优先级逆序排列 + std::sort(routeList.begin(), routeList.end(), CompRouterData); + + return 0; +} + +std::string RouteRule::GetValue(std::string src, std::string key, + std::string sp, std::string sp2) { + if (src.empty() || key.empty() || sp.empty() || sp2.empty()) { + return ""; + } + + std::vector kvs; + //split(kvs, src, boost::is_any_of(sp)); + int32_t ret = SplitStringIntoVector(src.c_str(), sp.c_str(), kvs); + if (0 == ret) { + return ""; + } + + std::vector kv; + for (std::vector::iterator iter = kvs.begin(); + iter != kvs.end(); ++iter) { + kv.clear(); + //split(kv, *iter, boost::is_any_of(sp2)); + ret = SplitStringIntoVector(iter->c_str(), sp2.c_str(), kv); + if (kv.size() == 2 && key == kv[0]) { + return kv[1]; + } + } + + return ""; +} + +/** + * 检测是否需要保留过滤掉的结果 + */ +bool RouteRule::IsRouteLimit(const CRouteData &routeData) { + //当配置route_limit=1, 返回true; 否则返回alse + if (!(routeData.reserved).empty()) { + //解析reserved内容 + std::string value = GetValue(routeData.reserved, LIMIT_KEY, "|", ":"); + if (LIMIT_VALUE == value) { + return true; + } + } + return false; +} + +bool RouteRule::IsMatchServiceName(const SGService &service, + const std::string &serviceName) { + return service.serviceInfo.end() == service.serviceInfo.find(serviceName); +} + +int32_t RouteRule::FilterServiceName(std::vector &serviceList, + std::string serviceName) { + serviceList.erase(std::remove_if(serviceList.begin(), serviceList.end(), + boost::bind(&RouteRule::IsMatchServiceName, + _1, serviceName)), + serviceList.end()); + return 0; +} + +int32_t RouteRule::SyncFweight(std::vector &services) { + for (std::vector::iterator iter = services.begin(); + iter != services.end(); ++iter) { + if (0 == iter->fweight) { + iter->fweight = iter->weight; + } + } + return 0; +} + +bool RouteRule::IsMatchRoute(const CRouteData &route, + bool is_update_routes, + std::vector *exclusive_routes) { + if (4 == route.category) { + exclusive_routes->push_back(route); + if (is_update_routes) { + return true; + } + } + return false; +} + +void RouteRule::GetExclusiveRoute(std::vector &routes, + std::vector &exclusive_routes, + bool is_update_routes) { + routes.erase(std::remove_if(routes.begin(), routes.end(), + boost::bind(&RouteRule::IsMatchRoute, _1, + is_update_routes,&exclusive_routes)), + routes.end()); +} + + +bool RouteRule::IsMatchExclusiveService(const SGService &service, + const CRouteData &route) { + if (FilterProvider(route, service)) { + NS_LOG_DEBUG("delete ip = " << service.ip << " port = " << service.port + << "from the service list"); + return true; + } + return false; +} +void RouteRule::FilterProvidersByExclusiveRoutes(std::vector &services, + const std::vector &exclusive_routes) { + // delete service node while it is match the exclusive_routes + for (std::vector::const_iterator route_iter = exclusive_routes.begin(); + exclusive_routes.end() != route_iter; ++route_iter) { + services.erase(std::remove_if(services.begin(), services.end(), + boost::bind(&RouteRule::IsMatchExclusiveService, + _1, *route_iter)), + services.end()); + } +} +bool RouteRule::IsMatchRoutesConsumer(const std::vector &routes, + const std::string &ip) { + for (std::vector::const_iterator iter = routes.begin(); + routes.end() != iter; ++iter) { + if (IsMatchConsumer(*iter, ip)) { + return true; + } + } + return false; +} + +} //namespace diff --git a/sg_agent/src/rule/route_rule.h b/sg_agent/src/rule/route_rule.h new file mode 100644 index 0000000..41ef29c --- /dev/null +++ b/sg_agent/src/rule/route_rule.h @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef __sgagent_filter_H__ +#define __sgagent_filter_H__ + +#include +#include +#include +#include "route_info.h" +#include "../gen-cpp/naming_service_types.h" +#include + +namespace meituan_mns { + +// routeData排序比较函数,基于priority大小 +static bool CompRouterData(const CRouteData &r1, + const CRouteData &r2) { + return r1.priority > r2.priority; +} + +class RouteRule { + public: + /** + * 过滤掉权重为零的服务节点 + * @param serviceList + * @param thresholdWeight + * @return + */ + static int32_t FilterWeight(std::vector &serviceList, + double thresholdWeight = 0); + + /** + * 根据服务分组优先级排序,并且过滤掉下线状态的服务分组 + * @param routeList + * @return + */ + static int32_t SortRouteList(std::vector &routeList); + + /** + * 过滤服务分组,根据服务分组信息过滤返回的服务列表 + * @param serviceList + * @param sorted_routes + * @param ip + * @param route_flag + * @param open_auto_route + * @return + */ + static int32_t FilterRoute(std::vector &serviceList, + const std::vector &sorted_routes, + const std::string &ip, + const bool route_flag, + const bool open_auto_route = true); + + /** + * 过滤backup节点,正常情况只返回nomal角色的服务列表, + * 只有所有服务不可用时,才返回backup节点 + */ + static int32_t FilterBackup(std::vector &serviceList); + + /** + * 过滤非ALIVE节点 + */ + static int32_t FilterUnAlive(std::vector &serviceList); + + /** + * 检测是否有alive状态服务 + */ + static bool HasAliveNode(std::vector &serviceList); + + /** + * 过滤非ALIVE节点 + */ + static int32_t FilterServiceName(std::vector &serviceList, + std::string serviceName); + + /** + * 获取CRoute的reserved扩展字段route_enforce值 + * reserved格式k1:v1|k2:v2..., 此处K为“route_enforce", 0:空返回全部, 1:空返回空 + */ + static std::string GetValue(std::string src, std::string key, + std::string sp, std::string sp2); + + /** + * + * @param routes + * @param ip + * @return + */ + static bool IsMatchRoutesConsumer(const std::vector &routes, + const std::string &ip); + /** + * 从routes中过滤排他性路由分组,category=4 + * @param routes + * @param exclusive_routes + * @param is_update_routes true: 将会更新routes + */ + static void GetExclusiveRoute(std::vector &routes, + std::vector &exclusive_routes, + bool is_update_routes); + + /** + * delete the service node while it is match the exclusive_routes + * @param serivces + * @param exclusive_routes + */ + static void FilterProvidersByExclusiveRoutes(std::vector &serivces, + const std::vector &exclusive_routes); + +/** + * 同步fweight,将空fweight置为weight值 + */ + static int32_t SyncFweight(std::vector &service); + private: + //是否可用节点 + static bool IsUnAliveService(const SGService &service); + //主备机 + static bool IsHost(const SGService &service, bool *alive_flag); + //权重是否符合 + static bool IsMatchWeight(const SGService &service, double thresholdWeight); + //路由规则是否启用 + static bool IsAliveRoute(const CRouteData &route); + //匹配servicenane + static bool IsMatchServiceName(const SGService &service, + const std::string &serviceName); + //过滤route + static bool IsMatchRoute(const CRouteData &route, + bool is_update_routes, + std::vector *exclusive_routes); + //强制路由过滤 + static bool IsMatchExclusiveService(const SGService &service, + const CRouteData &route); + /** + * 通过IP信息过滤服务消费者 + * @param route + * @param local_ip + * @return + */ + static bool IsMatchConsumer(const CRouteData &route, + const std::string &local_ip); + /** + * 通过服务分组过滤服务提供列表 + * @param route + * @param oservice + * @return + */ + static bool FilterProvider(const CRouteData &route, + const SGService &oservice); + /** + * 对ip:port主机进行过滤,判断是否匹配上服务分组列表中的ip:port信息 + * @param regex_ip + * @param local_ip + * @return + */ + static bool FilterHost(const std::string ®ex_ip, + const std::string &local_ip); + /** + * + * @param regex_ip + * @param local_ip + * @return + */ + static bool RegexFilterIp(const std::string ®ex_ip, + const std::string &local_ip); + /** + * + * @param regex_ip + * @param local_ip + * @return + */ + static bool RegexFilterPort(const std::string ®ex_ip, + const std::string &local_ip); + /** + * + * @param route_limit + * @param is_idc + * @param is_region + * @return + */ + static int32_t FilterIdcOrCenter(std::vector &, const std::string &, + bool route_limit, bool is_idc, bool is_region); + + /** + * 检测是否需要保留过滤掉的结果 + * true: 强制过滤, 不保留; false: 保留 + */ + static bool IsRouteLimit(const CRouteData &routeData); + + /** + * 应用同机房路由规则 + * 如果开启强制路由,只保留同idc节点;未开启对非idc节点进行权重降级 + */ + static int32_t FilterSameIdc(std::vector &serviceList, + boost::shared_ptr local_idc, bool routeLimit); + /** + * + * @param service + * @param local_idc + * @return + */ + static bool IsMatchIdcRule(SGService &service, boost::shared_ptr local_idc); + + /** + * 应用同中心路由规则 + * 如果开启强制路由,只保留同中心节点;未开启对跨中心节点进行权重降级 + */ + static int32_t FilterSameCenter(std::vector &serviceList, + boost::shared_ptr local_idc, bool routeLimit); + + static bool IsMatchCenterRule(SGService &service, boost::shared_ptr local_idc); + /** + * 应用同机房路由规则 + * 如果开启强制路由,只保留同城节点;未开启对跨城节点进行权重降级 + */ + static int32_t FilterSameRegion(std::vector &serviceList, + boost::shared_ptr local_idc, bool routeLimit); + + /** + * + * @param service + * @param local_idc + * @return + */ + static bool IsMatchRegionRule(SGService &service, boost::shared_ptr local_idc); +}; + +} // namespace + + +#endif + diff --git a/sg_agent/src/tool/README_BUILD.md b/sg_agent/src/tool/README_BUILD.md new file mode 100644 index 0000000..8015abe --- /dev/null +++ b/sg_agent/src/tool/README_BUILD.md @@ -0,0 +1,30 @@ +## 如何快速构建? + + (1)第三方依赖: + + * 日志系统:log4cplus + + * 网络库:Cthrift/libevent/Muduo + + * rpc:thrift(版本0.8.0) + + * zookeeper client:libzookeeper_mt(多线程版本) + + * rpc:thrift(版本0.8.0) + + * 工具类:boost. + + +(2)步骤: + + a.进入源码目录 + + b.执行sh src/tool/build_agent.sh + + c.生成的可执行文件在src目录的bin目录下 + + + + + + \ No newline at end of file diff --git a/sg_agent/src/tool/build_agent.sh b/sg_agent/src/tool/build_agent.sh new file mode 100644 index 0000000..b0870b1 --- /dev/null +++ b/sg_agent/src/tool/build_agent.sh @@ -0,0 +1,7 @@ +#!/bin/sh +sh src/tool/clear4git.sh +cmake src/CMakeLists.txt +cd src +make -j8 +make install + diff --git a/sg_agent/src/tool/build_unittest.sh b/sg_agent/src/tool/build_unittest.sh new file mode 100644 index 0000000..e038de8 --- /dev/null +++ b/sg_agent/src/tool/build_unittest.sh @@ -0,0 +1,6 @@ +#!/bin/sh +#sh tool/clear4git.sh +cmake -DCMAKE_BUILD_TYPE=debug src/CMakeLists.txt +cd src/test +make -j8 +make install diff --git a/sg_agent/src/tool/clear4git.sh b/sg_agent/src/tool/clear4git.sh new file mode 100755 index 0000000..2dde0fb --- /dev/null +++ b/sg_agent/src/tool/clear4git.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +for module_path in src/mns src/test src/util + do + for file_path in cmake_install.cmake CMakeCache.txt CMakeFiles Makefile install_manifest.txt + do + rm -rf ${module_path}/${file_path} + done; + done; + +#rm -rf sg_agent/build/ sg_agent/agent_bin/ sg_agent/lib/ sg_agent/bin/ + +find src/ -name .*.sw* -exec rm -rf {} \; diff --git a/sg_agent/src/tool/run_sgagent b/sg_agent/src/tool/run_sgagent new file mode 100755 index 0000000..a93b580 --- /dev/null +++ b/sg_agent/src/tool/run_sgagent @@ -0,0 +1,15 @@ +#!/bin/sh +LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/meituan/apps/sg_agent/libs +export LD_LIBRARY_PATH + +ulimit -n 1000000 +ulimit -c 100000000 + +cd /opt/meituan/apps/sg_agent + +#reboot sg_agent +NUM=`ps -ef |grep -v grep | grep -c /opt/meituan/apps/sg_agent/sg_agent` +if [ $NUM -lt 1 ] +then + exec setuidgid octo /opt/meituan/apps/sg_agent/sg_agent > /dev/null 2>&1 +fi diff --git a/sg_agent/src/tool/svc.sh b/sg_agent/src/tool/svc.sh new file mode 100755 index 0000000..487a6d6 --- /dev/null +++ b/sg_agent/src/tool/svc.sh @@ -0,0 +1,14 @@ +#!/bin/sh +DIR=`pwd` +BIN=$DIR"/sg_agent" + +for pid in $(ps -ef | grep $BIN | grep -v grep | awk '{print $2}') +do + kill $pid +done + +folder="/opt/meituan/apps/sg_agent/sg_agent_bak" +if [ ! -x "$folder" ]; then + mkdir "$folder" +fi + diff --git a/sg_agent/src/util/base_consts.h b/sg_agent/src/util/base_consts.h new file mode 100644 index 0000000..a4fe91c --- /dev/null +++ b/sg_agent/src/util/base_consts.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_BASE_CONSTS_H +#define OCTO_OPEN_SOURCE_BASE_CONSTS_H +#include +#include +namespace meituan_mns { +const std::string SG_AGENT_CONF = "/octo/nameservice/sg_agent/sg_agent_env.xml"; +const std::string AGENT_MUTABLE_CONF = "/octo/ns/sg_agent/sg_agent_mutable.xml"; +const std::string AGENT_WHITELIST_CONF = "/octo/ns/sg_agent/sg_agent_whitelist.xml"; +const std::string AGENT_SWITCH_FILE = "/octo/ns/sg_agent/agent_switch.xml"; +const std::string APPENV_FILE = "/data/webapps/octo.cfg"; +const std::string kStrIDCFileFullPath = "/octo/ns/sg_agent/idc.xml"; +const std::string kServiceAppkeyPath = "/data/webapps/appkeys"; + +const std::string AGENT_CONF_PATH = "/octo/ns/sg_agent/"; +const std::string IDC_FILE_NAME = "idc.xml"; + +const int32_t kMaxRegistryThreads = 4; +const int32_t kMaxDiscThreads = 1; + +const int32_t kRegistryThreads = 0; +const int32_t kNodeIp = 1; +const int32_t kClientNum = 2; +const int32_t kClientThreads = 3; +const int32_t kPullThreads = 4; +const int32_t kDispatchThreads = 5; +const int32_t kFastGetThreads = 6; +const int32_t kUnifiedAppkey = 7; +const int32_t kUnifiedMtthrift = 8; +const int32_t kNodeEnv = 9; +const int32_t kRegistryType = 10; +const int32_t kZkTimeout = 11; +const int32_t kRetryTimes = 12; +const int32_t kRegisryCenterType =13; +const int32_t kCacheDiscSwitch = 14; +const int32_t kZkClientNum = 15; + +const int32_t kZkClientIndex = 0; +static const int32_t HeartbeatUnSupport = 0; +static const int32_t DefaultRetry = 5; + +const int32_t kConfigInitRetryTimes = 3; + +const int32_t kDiscZookeeper = 1; +const int32_t kDiscCached = 2; +const int32_t kDiscMixer = 3; +const int32_t kExtendCenter = 4; + +const int32_t kRegistryZk = 0; +const int32_t kRegistryCache = 1; +const int32_t kRegistryMixer = 2; + +const int32_t retry_times_ = 3; +const int32_t kRetrySleepTime = 50000; +const int32_t kDefaultWeight = 10; +const int32_t kDefaultFweight = 10.0; +const std::string kDefaultStrProtocol = "thrift"; + +const int32_t MTCONFIG_OK = 200; +const int32_t MTCONFIG_NOT_CHANGE = 302; + +const int32_t MNSC_OK = 200; +const int MNSC_UPDATING = 500; +const int MNSC_RETRY_TIME = 3; + +const int32_t DEFAULT_EXTIME = 300; +const int32_t kMaxZkPathDepth = 8; + +const int32_t kInt32EnvTest = 1; +const int32_t kInt32EnvStage = 2; +const int32_t kInt32EnvProd = 3; + +//上报监控item +const int PID_ITEM = 0; +const int VMRSS_ITEM = 1; +const int VERSION_ITEM = 2; +const int CPU_ITEM = 3; +const int FILECONFIG_ITEM = 4; +const int KVCONFIG_ITEM = 5; +const int COMMON_LOG_ITEM = 6; +const int ROUTE_LIST_ITEM = 7; +const int SERVICE_LIST_ITEM = 8; +const int MODULE_INVOKER_ITEM = 9; +const int REGISTER_ITEM = 10; +const int MCC_FCONFIG_ALLREQ_ITEM = 11; +const int MCC_FCONFIG_SUCCESSREQ_ITEM = 12; +const int MCC_CONFIG_ALLREQ_ITEM = 13; +const int MCC_CONFIG_SUCCESSREQ_ITEM = 14; +const int MNSC_ALLREQ_ITEM = 15; +const int MNSC_SUCCESSREQ_ITEM = 16; +const int MAX_MONITOER_ITEM = 16; +const int DEFAULT_PROTOCOL_SCANTIME = 20; +const int DEFAULT_PROTOCOL_MAX_UPDATETIME = 60; // 1min + +//http +const std::string HTTP_RESPONSE_NULL = "nothing availble http description msg"; +const std::string listen_ip = "0.0.0.0"; + +const int http_port = 5267; +const int INVALID_METHOD = -1; +const int ADD_SERVICE = 0; +const int UPDATE_SERVICE = 1; +const int DELETE_SERVICE = 2; +const int GET_SERVICE = 3; +const int GET_MONITOR_SERVICE = 4; +const int REPLACE_SERVICE = 5; +const int HTTP_MNS_URL = 6; +const int HTTP_MONITOR_URL = 7; +const int HEALTHY_CHECK = 8; +const unsigned int kThreadTime = 20*1000;//20ms + + +// 地域过滤阈值 +const double RegionThresHold = 0.0001; +// IDC过滤阈值 +const double IdcThresHold = 0.1; + +const int HealthCheckInterval = 60;//60s +const int HealthCheckMaxInterval = 5*60; //5min + +enum RegistryType{ + kAddReg = 0, + kBatchReg, + kExtendReg +}; + + +enum RegistryActionType { + REGIST = 0, + UNREGIST = 1 +}; + + + +} + + + + +#endif //OCTO_OPEN_SOURCE_BASE_CONSTS_H diff --git a/sg_agent/src/util/base_errors_consts.h b/sg_agent/src/util/base_errors_consts.h new file mode 100644 index 0000000..b599eea --- /dev/null +++ b/sg_agent/src/util/base_errors_consts.h @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_BASE_ERRORS_CONSTS_H +#define OCTO_OPEN_SOURCE_BASE_ERRORS_CONSTS_H +namespace meituan_mns { +const uint32_t SUCCESS = 0; +const uint32_t FAILURE = -1; + +/** + * buffer_mgr: -01 00 xxx + */ +#define ERR_BUFFERMGR_EMPTYUPDATEFUNC -100001 +#define ERR_BUFFERMGR_EMPTYKEY -100002 +#define ERR_BUFFERMGR_EMPTYVALUE -100003 +#define ERR_BUFFERMGR_BUFHEAD_NULL -100004 +/** + * mqservice: -01 01 xxx + */ +#define ERR_MQSVC_FIALEDTORCVMSG -101001 +#define ERR_MQ_FULL -101008 +#define ERR_DISK_WRITE -101009 //磁盘写出错 + + +/** + * env: -0102xxx + */ +#define ERR_NOTGETIP -102001 +#define ERR_OFFLINE -102002 +#define ERR_NOTGETHOST -102003 +#define ERR_NEEDNOT2STAGE -102004 +#define ERR_FAILDTOSAVEXML -102005 +#define ERR_FAILDTOLOADXML -102006 +#define ERR_NOTMNSPATH -102007 +#define ERR_NOSGAGENTMUTABLECONF -102008 +#define ERR_NOSGAGENTCONF -102009 +#define ERR_INVALID_ENV -102010 +#define ERR_FAILDMKDIRWORKER -102011 + +/** + * comm: -0103xxx + */ +#define ERR_COMM_NOTGETIP -103001 + +/** + * sg_agent: 不分类错误码, -02 20 xxx + */ +#define ERR_CREATEPTHREAD_FAILED -220001 +#define ERR_LOCCONF_MQ_RES_ERR -220002 +#define ERR_GETROUTELIST_FROMWORKER_NULL -220003 +#define ERR_GETSERVICELIST_FROMWORKER_NULL -220004 +#define ERR_SETMSG -220005 +#define ERR_SERVICE_REQMQ_INIT -220006 +#define ERR_SERVICE_RESMQ_INIT -220007 +#define ERR_ROUTE_REQMQ_INIT -220008 +#define ERR_ROUTE_RESMQ_INIT -220009 +#define ERR_LOCCONF_REQMQ_INIT -220010 +#define ERR_LOCCONF_RESMQ_INIT -220011 +#define ERR_REGIST_REQMQ_INIT -220012 +#define ERR_LOGCOLLECTOR_INIT -220013 +#define ERR_INVOKECOLLECTOR_INIT -220014 +#define ERR_REGIST_REQMQ_NULL -220015 +#define ERR_LOGCOLLECTOR_REQMQ_NULL -220016 +#define ERR_INVOKECOLLECTOR_REQMQ_NULL -220017 +#define ERR_LOCCONF_REQMQ_NULL -220018 +#define ERR_LOCCONF_RESMQ_NULL -220019 +#define ERR_ROUTE_REQMQ_NULL -220020 +#define ERR_ROUTE_RESMQ_NULL -220021 +#define ERR_SERVICE_REQMQ_NULL -220022 +#define ERR_SERVICE_RESMQ_NULL -220023 +#define ERR_LOCCONF_BUFFER_NULL -220024 +#define ERR_ROUTE_BUFFER_NULL -220025 +#define ERR_SERVICE_BUFFER_NULL -220026 +#define ERR_LOGSERIALIZATION -220027 +#define ERR_INVOKESERIALIZATION -220028 +#define ERR_REGISTSERIALIZATION -220029 +#define ERR_LOCCONFSERIALIZATION -220030 +#define ERR_ROUTESERIALIZATION -220031 +#define ERR_SERVICESERIALIZATION -220032 +#define ERR_LOCCONFDESERIALIZATION -220033 +#define ERR_ROUTEDESERIALIZATION -220034 +#define ERR_SERVICEDESERIALIZATION -220035 +#define ERR_LOCCONF_KEYSET_NULL -220036 +#define ERR_SERVICE_KEYSET_NULL -220037 +#define ERR_ROUTE_KEYSET_NULL -220038 +#define ERR_MQCONTENT_TOOLONG -220039 +#define ERR_INVALIDAPPKEY -220040 +#define ERR_EMPTY_APPKEY -220041 +#define ERR_FAILEDGETLOCALIP -220042 +#define ERR_INVALID_WEIGHT -220043 +#define ERR_FAILEDSENDMSG -220044 +#define ERR_PARAMNOTCOMPLETE -220045 +#define ERR_COMMONLOGCOLLECTOR_REQMQ_NULL -220046 +#define ERR_GETMQ_TIMEOUT -220047 +#define ERR_INVALID_PORT -220048 +#define ERR_SERVICENAME_REQMQ_INIT -220049 +#define ERR_SERVICENAME_RESMQ_INIT -220050 +#define ERR_SERVICENAME_BUFFER_NULL -220051 +#define ERR_SERVICENAME_REQMQ_NULL -220052 +#define ERR_SERVICENAME_RESMQ_NULL -220053 +#define ERR_SERVICENAME_KEYSET_NULL -220054 +#define ERR_ILLEGAL_REGISTE -220055 +#define ERR_INVALID_PROTOCOL -220056 + +//-201xxx预留给CONFIG +#define ERR_FAILEDTOINITMEMMGR -201001 +#define ERR_CONFIG_REQMQ_NULL -201002 +#define ERR_CONFIGDESERIALIZATION -201003 +#define ERR_SET_NOTGETRESFROMMQ -201004 // MQ中未获取结果, 超时或者worker处理失败 +#define ERR_GET_NOTGETRESFROMMQ -201005 // MQ中未获取结果, 超时或者worker处理失败 +#define ERR_UPDATE_NOTGETRESFROMMQ -201006 // MQ中未获取结果, 超时或者worker处理失败 +#define ERR_FAILED_SENDMQ -201007 // 发送消息到MQ失败 +#define ERR_CANNOTSET -201008 // 由于buffer没有对应的conf值, 不能做setConfig操作 +#define ERR_SGAGENT_UNKNOW_ERROR -201009 +#define ERR_GETCONFIG_TIMEOUT -201010 // 获取结果超时 +#define ERR_CREATECONNECTION -201011 // 建立连接失败 +#define ERR_FAILEDTOGETCONFSERVLIST -201012 // 获取serviceList失败 +#define ERR_CONFSERVLIST_EMPTY -201013 // 建立serviceList为空 +#define ERR_CONFSERV_CONNFAILED -201014 // 建立连接失败 +#define ERR_GETMERGEDATA_TEXCEPTION -201015 // 获取conf失败 +#define ERR_GETFILECONF_TEXCEPTION -201016 // 获取文件配置失败 +#define ERR_SYNCRELATION_TEXCEPTION -201017 // 同步配置主机失败 +#define ERR_SETDATA_TEXCEPTION -201018 // 设置配置失败 +#define ERR_CONFIG_FROMFILE -201119 +#define ERR_CONFIG_EMPTYPATH -201120 +#define ERR_CONFIG_EMPTYFILE -201121 +#define ERR_CONFIG_OPENFILE_FAILED -201122 +#define ERR_CONFIG_OPENFUNC_NOT -201123 +#define ERR_CONFIG_MKDIR -201124 +#define ERR_CONFIG_PARAM_APPKEYMISS -201125 +#define ERR_CONFIG_PARAM_ENVMISS -201126 +#define ERR_CONFIG_PARAM_PATHMISS -201127 +#define ERR_CONFIG_PATH_EMPTY -201128 +#define ERR_CONFIG_FILE_EMPTY -201129 +#define ERR_CONFIG_LOAD_CONF_FAIL -201130 +#define ERR_CONFIG_TASKSIZE_OVERLOAD -201132 +#define ERR_CONFIG_INVILIDCMD -201133 + +// -2011xx for file config +#define ERR_FILECONFIG_REQMQ_INIT -201100 +#define ERR_FILECONFIG_RESMQ_INIT -201101 +#define ERR_FILECONFIG_REQMQ_NULL -201102 +#define ERR_FILECONFIG_MQ_RES_ERR -201103 +#define ERR_FILECONFIG_BUFFER_NULL -201104 +#define ERR_FILECONFIG_SERIALIZATION -201105 +#define ERR_FILECONFIG_DESERIALIZATION -201106 +#define ERR_FILECONFIG_KEYSET_NULL -201107 +#define ERR_FILECONFIG_MD5_WRONG -201108 +#define ERR_FILECONFIG_MD5_SAME -201108 +#define ERR_FILECONFIG_FROMFILE -201109 + +//预留给MtConfig Server错误码 +#define ERR_NO_CHANGE -201302 +#define ERR_UNKNOE_ERROR -201500 +#define ERR_PARAM_ERROR -201501 +#define ERR_NODE_NOT_EXIST -201502 +#define ERR_NOT_EXIST_VERSION -201503 +#define ERR_DEPRECATED_VERSION -201504 +//-203xxx for HLB +#define ERR_HLB_MQ_RES_ERR -203050 +#define ERR_HLB_REQMQ_INIT -203051 +#define ERR_HLB_RESMQ_INIT -203052 +#define ERR_HLB_REQMQ_NULL -203053 +#define ERR_HLB_RESMQ_NULL -203055 +#define ERR_HLB_BUFFER_NULL -203056 +#define ERR_HLB_SERIALIZATION -203057 +#define ERR_HLB_DESERIALIZATION -203058 +#define ERR_HLB_KEYSET_NULL -203059 +//-204xxx for appkey +#define ERR_APPKEY_MQ_RES_ERR -204050 +#define ERR_APPKEY_REQMQ_INIT -204051 +#define ERR_APPKEY_RESMQ_INIT -204052 +#define ERR_APPKEY_REQMQ_NULL -204053 +#define ERR_APPKEY_RESMQ_NULL -204055 +#define ERR_APPKEY_BUFFER_NULL -204056 +#define ERR_APPKEY_SERIALIZATION -204057 +#define ERR_APPKEY_DESERIALIZATION -204058 +#define ERR_APPKEY_KEYSET_NULL -204059 +//-205xxx for AUTH +#define ERR_AUTH_MQ_RES_ERR -205050 +#define ERR_AUTH_REQMQ_INIT -205051 +#define ERR_AUTH_RESMQ_INIT -205052 +#define ERR_AUTH_REQMQ_NULL -205053 +#define ERR_AUTH_RESMQ_NULL -205054 +#define ERR_AUTH_BUFFER_NULL -205055 +#define ERR_AUTH_SERIALIZATION -205056 +#define ERR_AUTH_DESERIALIZATION -205058 +#define ERR_AUTH_KEYSET_NULL -205059 +//-2 06 xxx for http-properties +#define ERR_PROPERTIES_MQ_RES_ERR -206050 +#define ERR_PROPERTIES_REQMQ_INIT -206051 +#define ERR_PROPERTIES_RESMQ_INIT -206052 +#define ERR_PROPERTIES_REQMQ_NULL -206053 +#define ERR_PROPERTIES_RESMQ_NULL -206054 +#define ERR_PROPERTIES_BUFFER_NULL -206055 +#define ERR_PROPERTIES_SERIALIZATION -206056 +#define ERR_PROPERTIES_DESERIALIZATION -206058 +#define ERR_PROPERTIES_KEYSET_NULL -206059 +//-2 07 xxx for quota +#define ERR_QUOTA_MQ_RES_ERR -207050 +#define ERR_QUOTA_REQMQ_INIT -207051 +#define ERR_QUOTA_RESMQ_INIT -207052 +#define ERR_QUOTA_REQMQ_NULL -207053 +#define ERR_QUOTA_RESMQ_NULL -207054 +#define ERR_QUOTA_BUFFER_NULL -207055 +#define ERR_QUOTA_SERIALIZATION -207056 +#define ERR_QUOTA_DESERIALIZATION -207057 +#define ERR_QUOTA_KEYSET_NULL -207058 +#define ERR_QUOTA_PARAM_INVALID -207059 +#define ERR_QUOTA_NOTOPEN -207060 + + +// -202xxx预留给client SDK使用 +// -2020xx预留给不分类错误码 +// -2021xs预留给MtConfig SDK +#define ERR_FAILEDOPENCONNECTION -202101 +#define ERR_FAILEDCLOSECONNECTION -202102 +#define ERR_FAILEDTOKOWNONLINEOFFLINE -202103 +#define ERR_JSONPARSE -202104 + +/** +* @Brief: sg_agent_worker: -03 00 xxx +*/ +//-3 00 xxx for 通用错误码 +#define ERR_CHECK_CONNECTION -300001 +#define ERR_CREATE_CONNECTION -300002 +#define ERR_CLOSE_CONNECTION -300003 +#define ERR_GET_HANDLER_INFO_FAIL -300004 +#define ERR_GET_HANDLER_FAIL -300005 +#define ERR_SERVICELIST_NULL -300006 +#define ERR_SERVICELIST_FAIL -300007 +#define ERR_REQMQ_INIT -300008 +#define ERR_RESMQ_INIT -300009 +#define ERR_WORKER_CREATEPTHREAD_FAILED -300010 +#define ERR_APPKEY_INVALID -300011 +#define ERR_JSON_TO_DATA_FAIL -300012 +#define ERR_DATA_TO_JSON_FAIL -300013 +#define ERR_MQ_CONTENT_TOO_LONG -300014 +#define ERR_CONFIG_PARAM_MISS -300015 + +//-3 01 xxx for zk +#define ERR_ZK_LIST_SAME_BUFFER -301001 +#define ERR_GET_ZK_HANDLER_FAIL -301002 +#define ERR_ZK_CONNECTION_LOSS -301003 +#define ERR_ZK_EVENTLOOP_TIMEOUT -301004 + +//-3 02 xxx for serviceList +#define ERR_REGIST_SERVICE_ZK_FAIL -302001 +#define ERR_NODE_LOST -302002 +#define ERR_REPEATED_REGISTER -302003 +//-3 03 xxx for mnsc +#define ERR_MNSC_GET_MNSCACHE -303001 +#define ERR_MNSC_GET_APPKEYLIST -303002 +//-3 04 xxx for appkeylist +//-3 05 xxx for AUTH +#define ERR_AUTH_ROLE_WRONG -305001 +//-3 06 xxx for http-properties +//-3 07 xxx for quota +//-3 08 xxx for logCollector +#define ERR_SEND_MODULE_FAIL -308003 +#define ERR_SEND_LOGS_FAIL -308004 +#define ERR_SEND_COMMONLOGS_FAIL -308005 +//-3 09 xxx for CONFIG + +//http return code +#define HTTP_RESPONSE_OK 200 +#define HTTP_PARAM_ERROR 400 +#define HTTP_INNER_ERROR 501 +#define HTTP_NOT_SUPPORT 404 + + +// zookeeper 自身errorcode, 该错误码已经用于thrift的API。【NOTE】不再允许对该错误码做任何变更 +#define ERR_NODE_NOTFIND -101 +#define ERR_INVALID_PARAM 400 + +} + +#endif //OCTO_OPEN_SOURCE_BASE_ERRORS_CONSTS_H diff --git a/sg_agent/src/util/base_mns_consts.h b/sg_agent/src/util/base_mns_consts.h new file mode 100644 index 0000000..7c7aba8 --- /dev/null +++ b/sg_agent/src/util/base_mns_consts.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_BASE_MNS_CONSTS_H +#define OCTO_OPEN_SOURCE_BASE_MNS_CONSTS_H + +namespace meituan_mns { +const int kMaxBuffSize = 1024; +const int kZkContentSize = 1024; +//协议类型 +const int THRIFT_TYPE = 0; +const int HTTP_TYPE = 1; + +const int REG_LIMIT_LEGAL = 1; + +const int DEFAULT_SLEEPTIME = 10000; + +const int DEFAULT_SPIN_NUM = 10; +} +#endif //OCTO_OPEN_SOURCE_BASE_MNS_CONSTS_H diff --git a/sg_agent/src/util/base_mns_define.h b/sg_agent/src/util/base_mns_define.h new file mode 100644 index 0000000..fc24871 --- /dev/null +++ b/sg_agent/src/util/base_mns_define.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef SG_AGENT_MNS_COMM_H +#define SG_AGENT_MNS_COMM_H + +namespace meituan_mns { +struct ServListAndCache { + int origin_servlist_size; + int filte_servlist_size; + int origin_cache_size; + int filte_cache_size; + std::vector origin_servicelist; + std::vector filte_servicelist; + ServListAndCache() : + origin_servlist_size(0), + filte_servlist_size(0), + origin_cache_size(0), + filte_cache_size(0), + origin_servicelist(std::vector()), + filte_servicelist(std::vector()){} +}; +struct SgCollectorMonitorInfo { + int pid; + int vmRss; + int cpu; + int zkConnections; + int mtConfigConnections; + int logCollectorConnections; + int fileConfigQueueLen; + int kvConfigQueueLen; + int serviceListQueueLen; + int routeListQueueLen; + int serviceNameQueueLen; + int commonLogQueueLen; + int moduleInvokerQueueLen; + int registeQueueSizeLen; + std::string extend; + SgCollectorMonitorInfo(): + pid(0), + vmRss(0), + cpu(0), + zkConnections(0), + mtConfigConnections(0), + logCollectorConnections(0), + fileConfigQueueLen(0), + kvConfigQueueLen(0), + serviceListQueueLen(0), + routeListQueueLen(0), + serviceNameQueueLen(0), + commonLogQueueLen(0), + moduleInvokerQueueLen(0), + registeQueueSizeLen(0), + extend("") {} +}; +} + +#endif //SG_AGENT_MNS_COMM_H diff --git a/sg_agent/src/util/falcon_mgr.cc b/sg_agent/src/util/falcon_mgr.cc new file mode 100644 index 0000000..97817aa --- /dev/null +++ b/sg_agent/src/util/falcon_mgr.cc @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "falcon_mgr.h" +#include "log4cplus.h" + +namespace meituan_mns { +muduo::detail::AtomicIntegerT FalconMgr::registeQueueSize; +muduo::detail::AtomicIntegerT FalconMgr::fileConfigQueueSize; +muduo::detail::AtomicIntegerT FalconMgr::kvConfigQueueSize; +muduo::detail::AtomicIntegerT FalconMgr::serviceListQueueSize; +muduo::detail::AtomicIntegerT FalconMgr::routeListQueueSize; +muduo::detail::AtomicIntegerT FalconMgr::serviceNameQueueSize; +muduo::detail::AtomicIntegerT FalconMgr::commonLogQueueSize; +muduo::detail::AtomicIntegerT FalconMgr::moduleInvokerQueueSize; + +muduo::detail::AtomicIntegerT FalconMgr::routeBufferSize;; +muduo::detail::AtomicIntegerT FalconMgr::serviceBufferSize;; +muduo::detail::AtomicIntegerT FalconMgr::filtedServiceBufferSize;; +muduo::detail::AtomicIntegerT FalconMgr::serviceNameBufferSize;; + +muduo::detail::AtomicIntegerT FalconMgr::serviceListReqCount; +muduo::detail::AtomicIntegerT FalconMgr::serviceListReqTime; +muduo::detail::AtomicIntegerT FalconMgr::serviceListReqFailedCount; +muduo::detail::AtomicIntegerT FalconMgr::serviceListReqCountStat; +muduo::detail::AtomicIntegerT FalconMgr::serviceListReqTimeStat; +muduo::detail::AtomicIntegerT FalconMgr::serviceListReqFailedCountStat; +double FalconMgr::serviceListReqSuccessPercent; +double FalconMgr::serviceListReqCost; + +void FalconMgr::Init() { + SetRegisteQueueSize(0); + SetFileConfigQueueSize(0); + SetKvConfigQueueSize(0); + SetServiceListQueueSize(0); + SetRouteListQueueSize(0); + SetServiceNameQueueSize(0); + + SetRouteBufferSize(0); + SetServiceBufferSize(0); + SetFiltedServiceBufferSize(0); + SetServiceNameBufferSize(0); +} + +long FalconMgr::GetRegisteQueueSize() { + return registeQueueSize.get(); +} + +void FalconMgr::SetRegisteQueueSize(const long size) { + registeQueueSize.getAndSet(size); +} + +long FalconMgr::GetFileConfigQueueSize() { + return fileConfigQueueSize.get(); +} + +void FalconMgr::SetFileConfigQueueSize(const long size) { + fileConfigQueueSize.getAndSet(size); +} + +long FalconMgr::GetKvConfigQueueSize() { + return kvConfigQueueSize.get(); +} + +void FalconMgr::SetKvConfigQueueSize(const long size) { + kvConfigQueueSize.getAndSet(size); +} + +long FalconMgr::GetServiceListQueueSize() { + return serviceListQueueSize.get(); +} + +void FalconMgr::SetServiceListQueueSize(const long size) { + serviceListQueueSize.getAndSet(size); +} + +long FalconMgr::GetRouteListQueueSize() { + return routeListQueueSize.get(); +} + +void FalconMgr::SetRouteListQueueSize(const long size) { + routeListQueueSize.getAndSet(size); +} + +long FalconMgr::GetServiceNameQueueSize() { + return serviceNameQueueSize.get(); +} + +void FalconMgr::SetServiceNameQueueSize(const long size) { + serviceNameQueueSize.getAndSet(size); +} + +long FalconMgr::GetCommonLogQueueSize() { + return commonLogQueueSize.get(); +} + +void FalconMgr::SetCommonLogQueueSize(const long size) { + commonLogQueueSize.getAndSet(size); +} + +long FalconMgr::GetModuleInvokerQueueSize() { + return moduleInvokerQueueSize.get(); +} + +void FalconMgr::SetModuleInvokerQueueSize(const long size) { + moduleInvokerQueueSize.getAndSet(size); +} + +void FalconMgr::GetQueueSizeRes(std::map *mq) { + mq->insert(std::pair + (FileConfigQueue, GetFileConfigQueueSize())); + mq->insert(std::pair + (KVConfigQueue, GetKvConfigQueueSize())); + mq->insert(std::pair + (ServiceListQueue, GetServiceListQueueSize())); + mq->insert(std::pair + (RouteListQueue, GetRouteListQueueSize())); + mq->insert(std::pair + (ServiceNameQueue, GetServiceNameQueueSize())); + mq->insert(std::pair + (CommonLogQueue, GetCommonLogQueueSize())); + mq->insert(std::pair + (ModuleInvokerQueue, GetModuleInvokerQueueSize())); + mq->insert(std::pair + (RegisteQueueSize, GetRegisteQueueSize())); +} + +int FalconMgr::GetRouteBufferSize() { + return routeBufferSize.get(); +} + +void FalconMgr::SetRouteBufferSize(const int size) { + routeBufferSize.getAndSet(size); +} + +int FalconMgr::GetServiceBufferSize() { + return serviceBufferSize.get(); +} + +void FalconMgr::SetServiceBufferSize(const int size) { + serviceBufferSize.getAndSet(size); +} + +int FalconMgr::GetFiltedServiceBufferSize() { + return filtedServiceBufferSize.get(); +} + +void FalconMgr::SetFiltedServiceBufferSize(const int size) { + filtedServiceBufferSize.getAndSet(size); +} + +int FalconMgr::GetServiceNameBufferSize() { + return serviceNameBufferSize.get(); +} + +void FalconMgr::SetServiceNameBufferSize(const int size) { + serviceNameBufferSize.getAndSet(size); +} + +void FalconMgr::GetBufferSizeRes(std::map *mp) { + mp->insert(std::pair + (RouteBuffer, GetRouteBufferSize())); + mp->insert(std::pair + (ServiceBuffer, GetServiceBufferSize())); + mp->insert(std::pair + (FiltedServiceBuffer, GetFiltedServiceBufferSize())); + mp->insert(std::pair + (ServiceNameBuffer, GetServiceNameBufferSize())); +} + +int FalconMgr::GetServiceListReqCount() { + return serviceListReqCount.get(); +} + +void FalconMgr::AddServiceListReqCount(const int size) { + serviceListReqCount.getAndAdd(size); +} + +int FalconMgr::GetServiceListReqTime() { + return serviceListReqTime.get(); +} + +void FalconMgr::AddServiceListReqTime(const int size) { + serviceListReqTime.getAndAdd(size); +} + +int FalconMgr::GetServiceListReqFailedCount() { + return serviceListReqFailedCount.get(); +} + +void FalconMgr::AddServiceListReqFailedCount(const int size) { + serviceListReqFailedCount.getAndAdd(size); +} + +int FalconMgr::GetServiceListReqCountStat() { + return serviceListReqCountStat.get(); +} + +void FalconMgr::SetServiceListReqCountStat(const int size) { + serviceListReqCountStat.getAndSet(size); +} + +int FalconMgr::GetServiceListReqTimeStat() { + return serviceListReqTimeStat.get(); +} + +void FalconMgr::SetServiceListReqTimeStat(const int size) { + serviceListReqTimeStat.getAndSet(size); +} + +int FalconMgr::GetServiceListReqFailedCountStat() { + return serviceListReqFailedCountStat.get(); +} + +void FalconMgr::SetServiceListReqFailedCountStat(const int size) { + serviceListReqFailedCountStat.getAndSet(size); +} + +double FalconMgr::GetServiceListReqSuccessPercent() { + return serviceListReqSuccessPercent; +} + +void FalconMgr::SetServiceListReqSuccessPercent(const double size) { + serviceListReqSuccessPercent = size; +} + +double FalconMgr::GetServiceListReqCost() { + return serviceListReqCost; +} + +void FalconMgr::SetServiceListReqCost(const double size) { + serviceListReqCost = size; +} + +void FalconMgr::SetServiceListReqRes() { + SetServiceListReqCountStat(GetServiceListReqCount()); + SetServiceListReqTimeStat(GetServiceListReqTime()); + SetServiceListReqFailedCountStat(GetServiceListReqFailedCount()); + SetServiceListReqSuccessPercent((GetServiceListReqCountStat() + - GetServiceListReqFailedCountStat()) / GetServiceListReqCountStat()); + SetServiceListReqCost(GetServiceListReqTimeStat() + / GetServiceListReqCountStat()); + serviceListReqCount.getAndSet(0); + serviceListReqTime.getAndSet(0); + serviceListReqFailedCount.getAndSet(0); + NS_LOG_INFO("count: " << serviceListReqCountStat.get() + << "; time: " << serviceListReqTimeStat.get() + << "; failed count: " + << serviceListReqFailedCountStat.get() + << "; success percent: " << serviceListReqSuccessPercent + << "; cost: " << serviceListReqCost); +} + +void FalconMgr::GetServiceListReqRes(std::map *mp) { + mp->insert(std::pair + (Count, (double) GetServiceListReqCountStat())); + mp->insert(std::pair + (Time, (double) GetServiceListReqTimeStat())); + mp->insert(std::pair + (FailedCount, (double) GetServiceListReqFailedCountStat())); + mp->insert(std::pair + (SuccessPercent, (double) GetServiceListReqSuccessPercent())); + mp->insert(std::pair + (Cost, (double) GetServiceListReqCost())); +} + +} diff --git a/sg_agent/src/util/falcon_mgr.h b/sg_agent/src/util/falcon_mgr.h new file mode 100644 index 0000000..1484469 --- /dev/null +++ b/sg_agent/src/util/falcon_mgr.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +namespace meituan_mns { +enum EventLoopQueue { + FileConfigQueue, + KVConfigQueue, + ServiceListQueue, + RouteListQueue, + ServiceNameQueue, + CommonLogQueue, + ModuleInvokerQueue, + RegisteQueueSize, +}; + +enum BufferSize { + RouteBuffer, + ServiceBuffer, + FiltedServiceBuffer, + ServiceNameBuffer, +}; + +enum ServiceListReq { + Count, + Time, + FailedCount, + SuccessPercent, + Cost, +}; + +class FalconMgr { + public: + static void Init(); + static long GetRegisteQueueSize(); + static void SetRegisteQueueSize(const long size); + static long GetFileConfigQueueSize(); + static void SetFileConfigQueueSize(const long size); + static long GetKvConfigQueueSize(); + static void SetKvConfigQueueSize(const long size); + static long GetServiceListQueueSize(); + static void SetServiceListQueueSize(const long size); + static long GetRouteListQueueSize(); + static void SetRouteListQueueSize(const long size); + static long GetServiceNameQueueSize(); + static void SetServiceNameQueueSize(const long size); + static long GetCommonLogQueueSize(); + static void SetCommonLogQueueSize(const long size); + static long GetModuleInvokerQueueSize(); + static void SetModuleInvokerQueueSize(const long size); + static void GetQueueSizeRes(std::map *mq); + + static int GetRouteBufferSize(); + static void SetRouteBufferSize(const int size); + static int GetServiceBufferSize(); + static void SetServiceBufferSize(const int size); + static int GetFiltedServiceBufferSize(); + static void SetFiltedServiceBufferSize(const int size); + static int GetServiceNameBufferSize(); + static void SetServiceNameBufferSize(const int size); + static void GetBufferSizeRes(std::map *mp); + + static int GetServiceListReqCount(); + static void AddServiceListReqCount(const int size = 1); + static int GetServiceListReqTime(); + static void AddServiceListReqTime(const int size); + static int GetServiceListReqFailedCount(); + static void AddServiceListReqFailedCount(const int size = 1); + static int GetServiceListReqCountStat(); + static void SetServiceListReqCountStat(const int size); + static int GetServiceListReqTimeStat(); + static void SetServiceListReqTimeStat(const int size); + static int GetServiceListReqFailedCountStat(); + static void SetServiceListReqFailedCountStat(const int size); + static double GetServiceListReqSuccessPercent(); + static void SetServiceListReqSuccessPercent(const double size); + static double GetServiceListReqCost(); + static void SetServiceListReqCost(const double size); + static void SetServiceListReqRes(); + static void GetServiceListReqRes(std::map *mp); + + private: + static muduo::detail::AtomicIntegerT registeQueueSize; + static muduo::detail::AtomicIntegerT fileConfigQueueSize; + static muduo::detail::AtomicIntegerT kvConfigQueueSize; + static muduo::detail::AtomicIntegerT serviceListQueueSize; + static muduo::detail::AtomicIntegerT routeListQueueSize; + static muduo::detail::AtomicIntegerT serviceNameQueueSize; + static muduo::detail::AtomicIntegerT commonLogQueueSize; + static muduo::detail::AtomicIntegerT moduleInvokerQueueSize; + + // buffer key size + static muduo::detail::AtomicIntegerT routeBufferSize; + static muduo::detail::AtomicIntegerT serviceBufferSize; + static muduo::detail::AtomicIntegerT filtedServiceBufferSize; + static muduo::detail::AtomicIntegerT serviceNameBufferSize; + + // req count + static muduo::detail::AtomicIntegerT serviceListReqCount; + static muduo::detail::AtomicIntegerT serviceListReqTime; + static muduo::detail::AtomicIntegerT serviceListReqFailedCount; + static muduo::detail::AtomicIntegerT serviceListReqCountStat; + static muduo::detail::AtomicIntegerT serviceListReqTimeStat; + static muduo::detail::AtomicIntegerT serviceListReqFailedCountStat; + static double serviceListReqSuccessPercent; + static double serviceListReqCost; +}; + +} diff --git a/sg_agent/src/util/json_data_tools.cc b/sg_agent/src/util/json_data_tools.cc new file mode 100644 index 0000000..f976646 --- /dev/null +++ b/sg_agent/src/util/json_data_tools.cc @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include + +#include "json_data_tools.h" +#include "comm/inc_comm.h" + +namespace meituan_mns { + +#define CHECK_JSON(args) \ + if(!((args.c_str()[0] == '{' && args.c_str()[args.size() - 1] == '}') || (args.c_str()[0] == '[' && args.c_str()[args.size() -1] == ']')))\ + { NS_LOG_ERROR( "json formate not correct, should start with { and end with }");return -1;}\ + +int JsonZkMgr::ProviderNode2Json(const CProviderNode &oprovider, std::string &strJson) { + cJSON *root; + char *out; + root = cJSON_CreateObject(); + cJSON_AddItemToObject(root, "appkey", cJSON_CreateString(oprovider.appkey.c_str())); + cJSON_AddNumberToObject(root, "lastUpdateTime", oprovider.lastModifiedTime); + + out = cJSON_Print(root); + strJson = out; + + SAFE_FREE(out); + cJSON_Delete(root); + + return 0; +} + +int JsonZkMgr::ServiceNameNode2Json( + const std::string &serviceName, + std::string &strJson) { + cJSON *root; + char *out; + root = cJSON_CreateObject(); + if (NULL == root) { + NS_LOG_ERROR("failed to cJSON Create Object"); + return 0; + } + + cJSON_AddItemToObject(root, "serviceName", cJSON_CreateString(serviceName.c_str())); + cJSON_AddNumberToObject(root, "lastUpdateTime", time(0)); + + out = cJSON_Print(root); + strJson = out; + + SAFE_FREE(out); + cJSON_Delete(root); + + return 0; +} + +int JsonZkMgr::Json2ProviderNode(const std::string &strJson, + unsigned long mtime, + unsigned long version, + unsigned long cversion, + CProviderNode &oprovider) { + CHECK_JSON(strJson) + cJSON *root = cJSON_Parse(strJson.c_str()); + if (NULL == root) { + return ERR_JSON_TO_DATA_FAIL; + } + cJSON *pProviderAppkeyItem = cJSON_GetObjectItem(root, "appkey"); + if (NULL != pProviderAppkeyItem) { + oprovider.appkey = pProviderAppkeyItem->valuestring; + } else { + NS_LOG_WARN("the provider node appkey is null"); + } + oprovider.mtime = mtime; + oprovider.cversion = cversion; + oprovider.version = version; + cJSON *pModifiedTimeItem = cJSON_GetObjectItem(root, "lastUpdateTime"); + if (NULL != pModifiedTimeItem) { + oprovider.lastModifiedTime = pModifiedTimeItem->valueint; + } else { + NS_LOG_WARN("the provider node lastUpdateTime is null"); + } + + cJSON_Delete(root); + return 0; +} + +int JsonZkMgr::Json2RouteNode(const std::string &strJson, + unsigned long mtime, + unsigned long version, + unsigned long cversion, + CRouteNode &oroute) { + CHECK_JSON(strJson) + cJSON *root = cJSON_Parse(strJson.c_str()); + if (NULL == root) { + return ERR_JSON_TO_DATA_FAIL; + } + cJSON *pAppkeyItem = cJSON_GetObjectItem(root, "appkey"); + if (NULL != pAppkeyItem) { + oroute.appkey = pAppkeyItem->valuestring; + } else { + NS_LOG_WARN("the route node appkey is null"); + } + oroute.mtime = mtime; + oroute.cversion = cversion; + oroute.version = version; + cJSON *pModifiedTimeItem = cJSON_GetObjectItem(root, "lastUpdateTime"); + + if (NULL != pModifiedTimeItem) { + oroute.lastModifiedTime = pModifiedTimeItem->valueint; + } else { + NS_LOG_WARN("the route node lastModifiedTime is null"); + } + cJSON_Delete(root); + return 0; +} + +int JsonZkMgr::SGService2Json(const SGService &oservice, std::string &strJson, const int env_int) { + cJSON *root; + char *out; + root = cJSON_CreateObject(); + if (NULL == root) { + NS_LOG_ERROR("failed to create root Object"); + return FAILURE; + } + + cJSON_AddItemToObject(root, "appkey", cJSON_CreateString(oservice.appkey.c_str())); + cJSON_AddItemToObject(root, "version", cJSON_CreateString(oservice.version.c_str())); + cJSON_AddItemToObject(root, "ip", cJSON_CreateString(oservice.ip.c_str())); + cJSON_AddNumberToObject(root, "port", oservice.port); + cJSON_AddNumberToObject(root, "weight", oservice.weight); + cJSON_AddNumberToObject(root, "status", oservice.status); + cJSON_AddNumberToObject(root, "role", oservice.role); + cJSON_AddNumberToObject(root, "env", env_int); + cJSON_AddNumberToObject(root, "lastUpdateTime", oservice.lastUpdateTime); + cJSON_AddNumberToObject(root, "fweight", oservice.fweight); + cJSON_AddNumberToObject(root, "serverType", oservice.serverType); + cJSON_AddNumberToObject(root, "warmup", oservice.warmup); + + int32_t heartbeatSupport = oservice.heartbeatSupport; + cJSON_AddNumberToObject(root, "heartbeatSupport", heartbeatSupport); + cJSON_AddItemToObject(root, "protocol", cJSON_CreateString(oservice.protocol.c_str())); + + cJSON *item = cJSON_CreateObject(); + if (NULL == item) { + NS_LOG_ERROR("cJson failed to CreateObject. Item is serviceInfo"); + return FAILURE; + } + int ret = cJson_AddServiceObject(oservice.serviceInfo, root, + item, std::string("serviceInfo")); + if (0 != ret) { + NS_LOG_ERROR("failed to add serviceName to root"); + return FAILURE; + } + + + //cJSON_AddItemToObject(root, "unifiedProto", cJSON_CreateBool(oservice.unifiedProto)); + + out = cJSON_Print(root); + strJson = out; + NS_LOG_INFO("out: " << strJson); + + SAFE_FREE(out); + cJSON_Delete(root); + + return SUCCESS; +} + +int JsonZkMgr::ServiceNode2Json(const ServiceNode &oservice, std::string &strJson) { + cJSON *root; + char *out; + root = cJSON_CreateObject(); + if (NULL == root) { + NS_LOG_ERROR("failed to create root Object"); + return -1; + } + + cJSON_AddItemToObject(root, "serviceName", cJSON_CreateString(oservice.serviceName.c_str())); + cJSON_AddNumberToObject(root, "lastUpdateTime", oservice.lastUpdateTime); + + cJSON *arrayItem = cJSON_CreateArray(); + int ret = cJson_AddStringArray(oservice.appkeys, root, + arrayItem, std::string("appkey")); + if (0 != ret) { + NS_LOG_ERROR("failed to add appkey to root"); + return -1; + } + + out = cJSON_Print(root); + strJson = out; + NS_LOG_INFO("out: " << strJson); + + SAFE_FREE(out); + cJSON_Delete(root); + + return 0; +} + +int JsonZkMgr::Json2ServiceNode(const std::string &strJson, + ServiceNode &oservice) { + cJSON *root = cJSON_Parse(strJson.c_str()); + if (NULL == root) { + return ERR_JSON_TO_DATA_FAIL; + } + + cJSON *pItem = cJSON_GetObjectItem(root, "serviceName"); + if (pItem) { + oservice.serviceName = pItem->valuestring; + } + pItem = cJSON_GetObjectItem(root, "lastUpdateTime"); + if (pItem) { + oservice.lastUpdateTime = pItem->valueint; + } + pItem = cJSON_GetObjectItem(root, "appkey"); + if (pItem) { + cJSON *appkeys = pItem; + //解析serviceName + std::string name; + int nCount = cJSON_GetArraySize(appkeys); + for (int i = 0; i < nCount; i++) { + cJSON *pAppkeyItem = cJSON_GetArrayItem(appkeys, i); + if (NULL != pAppkeyItem) { + name = pAppkeyItem->valuestring; + oservice.appkeys.insert(name); + } else { + NS_LOG_WARN("json2service node, the appkey is null"); + } + } + } + + cJSON_Delete(root); + return 0; +} +int JsonZkMgr::Json2RouteData(const std::string &strJson, CRouteData &orouteData) { + cJSON *root = cJSON_Parse(strJson.c_str()); + if (NULL == root) { + return ERR_JSON_TO_DATA_FAIL; + } + + cJSON *pItem = cJSON_GetObjectItem(root, "id"); + if (pItem) { + orouteData.id = pItem->valuestring; + } + pItem = cJSON_GetObjectItem(root, "name"); + if (pItem) { + orouteData.name = pItem->valuestring; + } + pItem = cJSON_GetObjectItem(root, "appkey"); + if (pItem) { + orouteData.appkey = pItem->valuestring; + } + pItem = cJSON_GetObjectItem(root, "env"); + if (pItem) { + orouteData.env = pItem->valueint; + } + pItem = cJSON_GetObjectItem(root, "category"); + if (pItem) { + orouteData.category = pItem->valueint; + } + pItem = cJSON_GetObjectItem(root, "priority"); + if (pItem) { + orouteData.priority = pItem->valueint; + } + pItem = cJSON_GetObjectItem(root, "status"); + if (pItem) { + orouteData.status = pItem->valueint; + } + pItem = cJSON_GetObjectItem(root, "updateTime"); + if (pItem) { + orouteData.updateTime = pItem->valueint; + } + pItem = cJSON_GetObjectItem(root, "createTime"); + if (pItem) { + orouteData.createTime = pItem->valueint; + } + pItem = cJSON_GetObjectItem(root, "reserved"); + if (pItem) { + orouteData.reserved = pItem->valuestring; + } + + //解析consumer + int i = 0; + int nCount = 0; + cJSON *consumer = cJSON_GetObjectItem(root, "consumer"); + if (consumer) { + cJSON *ips = cJSON_GetObjectItem(consumer, "ips"); + cJSON *appkeys = cJSON_GetObjectItem(consumer, "appkeys"); + //解析consumer ips + std::vector ipList; + std::string oip; + nCount = cJSON_GetArraySize(ips); + for (i = 0; i < nCount; i++) { + cJSON *item = cJSON_GetArrayItem(ips, i); + char *ip = cJSON_Print(item); + oip = ip; + ipList.push_back(oip); + SAFE_FREE(ip); + } + + //解析consumer appkeys + std::vector appkeyList; + std::string oappkey; + nCount = cJSON_GetArraySize(appkeys); + for (i = 0; i < nCount; i++) { + cJSON *item = cJSON_GetArrayItem(appkeys, i); + char *appkey = cJSON_Print(item); + oappkey = appkey; + appkeyList.push_back(oappkey); + SAFE_FREE(appkey); + + } + //组装解析consumer + Consumer newConsumer; + newConsumer.ips = ipList; + newConsumer.appkeys = appkeyList; + orouteData.consumer = newConsumer; + } + + //解析provider + std::vector pList; + std::string oprovider; + cJSON *provider = cJSON_GetObjectItem(root, "provider"); + nCount = cJSON_GetArraySize(provider); + for (i = 0; i < nCount; i++) { + cJSON *item = cJSON_GetArrayItem(provider, i); + char *ip = cJSON_Print(item); + oprovider = ip; + pList.push_back(oprovider); + SAFE_FREE(ip); + } + orouteData.provider = pList; + + cJSON_Delete(root); + return 0; +} + +int JsonZkMgr::Json2SGService(const std::string &strJson, SGService &oservice) { + cJSON *root = cJSON_Parse(strJson.c_str()); + if (NULL == root) { + return ERR_JSON_TO_DATA_FAIL; + } + + cJSON *pItem = cJSON_GetObjectItem(root, "appkey"); + if (pItem) { + oservice.appkey = pItem->valuestring; + } + pItem = cJSON_GetObjectItem(root, "version"); + if (pItem) { + oservice.version = pItem->valuestring; + } + pItem = cJSON_GetObjectItem(root, "ip"); + if (pItem) { + oservice.ip = pItem->valuestring; + } + pItem = cJSON_GetObjectItem(root, "port"); + if (pItem) { + oservice.port = pItem->valueint; + } + pItem = cJSON_GetObjectItem(root, "weight"); + if (pItem) { + oservice.weight = pItem->valueint; + } + pItem = cJSON_GetObjectItem(root, "status"); + if (pItem) { + oservice.status = pItem->valueint; + } + pItem = cJSON_GetObjectItem(root, "role"); + if (pItem) { + oservice.role = pItem->valueint; + } + pItem = cJSON_GetObjectItem(root, "env"); + if (pItem) { + oservice.envir = pItem->valueint; + } + pItem = cJSON_GetObjectItem(root, "lastUpdateTime"); + if (pItem) { + oservice.lastUpdateTime = pItem->valueint; + } + pItem = cJSON_GetObjectItem(root, "heartbeatSupport"); + if (pItem) { + oservice.heartbeatSupport = static_cast(pItem->valueint); + } + + //后续添加字段 + pItem = cJSON_GetObjectItem(root, "fweight"); + if (pItem) { + oservice.fweight = pItem->valuedouble; + } + + pItem = cJSON_GetObjectItem(root, "serverType"); + if (pItem) { + oservice.serverType = pItem->valueint; + } + + pItem = cJSON_GetObjectItem(root, "warmup"); + if (pItem) { + oservice.serverType = pItem->valueint; + } + + pItem = cJSON_GetObjectItem(root, "protocol"); + if (pItem) { + oservice.protocol = pItem->valuestring; + } + pItem = cJSON_GetObjectItem(root, "serviceInfo"); + if (pItem) { + cJSON *svrNames = pItem; + for (int i = 0; i < cJSON_GetArraySize(svrNames); ++i) { + cJSON *item = cJSON_GetArrayItem(svrNames, i); + if (NULL != item) { + std::string serviceName(item->string); + cJSON *pUnifiedItem = cJSON_GetObjectItem(item, "unifiedProto"); + if (NULL != pUnifiedItem) { + bool unifiedProto = (0 != pUnifiedItem->valueint); + ServiceDetail srv; + srv.unifiedProto = unifiedProto; + oservice.serviceInfo[serviceName] = srv; + } else { + NS_LOG_WARN("service info unifiedProto is null"); + } + } + } + } + cJSON_Delete(root); + return 0; +} + +int JsonZkMgr::cJson_AddStringArray(const std::set &vecSvrName, + cJSON *root, cJSON *item, + const std::string &itemName) { + if (NULL == item) { + NS_LOG_ERROR("failed to cJson_CreateArray"); + return -1; + } + for (std::set::iterator iter = vecSvrName.begin(); + iter != vecSvrName.end(); ++iter) { + const char *ptr = (*iter).c_str(); + cJSON_AddItemToArray(item, cJSON_CreateString(ptr)); + } + cJSON_AddItemToObject(root, itemName.c_str(), + item); + return 0; +} + +int JsonZkMgr::cJson_AddServiceObject(const std::map &vecSvrName, + cJSON *root, cJSON *item, + const std::string &itemName) { + if (NULL == item) { + NS_LOG_ERROR("failed to cJSON_CreateObject"); + return -1; + } + for (std::map::const_iterator iter = vecSvrName.begin(); + iter != vecSvrName.end(); ++iter) { + cJSON *ele = cJSON_CreateObject(); + cJSON_AddNumberToObject(ele, "unifiedProto", + iter->second.unifiedProto); + + cJSON_AddItemToObject(item, iter->first.c_str(), + ele); + } + cJSON_AddItemToObject(root, itemName.c_str(), + item); + return 0; +} + + +cJSON *JsonZkMgr::GetObjectItem(cJSON *item, const char *name) { + cJSON *pItem = cJSON_GetObjectItem(item, name); + if (!pItem) { + NS_LOG_ERROR("failed to get item " << name); + } + return pItem; +} +} // namespace meituan_mns diff --git a/sg_agent/src/util/json_data_tools.h b/sg_agent/src/util/json_data_tools.h new file mode 100644 index 0000000..62f5437 --- /dev/null +++ b/sg_agent/src/util/json_data_tools.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_JSONDATAMGR_H +#define OCTO_OPEN_SOURCE_JSONDATAMGR_H + +#include +#include +#include +#include +#include "naming_service_types.h" + +extern "C" { +#include "comm/cJSON.h" +} +using namespace __gnu_cxx; +namespace meituan_mns { +class JsonZkMgr { + public: + + static int ProviderNode2Json(const CProviderNode &oprovider, + std::string &strJson); + static int ServiceNameNode2Json(const std::string &serviceName, + std::string &strJson); + static int Json2ProviderNode( + const std::string &strJson, + unsigned long mtime, + unsigned long version, + unsigned long cversion, + CProviderNode &oprovider); + + static int SGService2Json(const SGService &oservice, + std::string &strJson, + const int env_int); + static int Json2SGService(const std::string &strJson, SGService &oservice); + static int ServiceNode2Json(const ServiceNode &oservice, + std::string &strJson); + static int Json2ServiceNode(const std::string &strJson, + ServiceNode &oservice); + static int Json2RouteData(const std::string &strJson, CRouteData &orouteData); + static int Json2RouteNode(const std::string &strJson, + unsigned long mtime, + unsigned long version, + unsigned long cversion, + CRouteNode &oroute); + + static int cJson_AddStringArray( + const std::set &vecSvrname, + cJSON *root, cJSON *item, + const std::string &itemName); + + static int cJson_AddServiceObject( + const std::map &vecSvrname, + cJSON *root, cJSON *item, + const std::string &itemName); + + static cJSON *GetObjectItem(cJSON *item, const char *name); + +}; +} // namespace meituan_mns + +#endif //OCTO_OPEN_SOURCE_JSONDATAMGR_H diff --git a/sg_agent/src/util/sds_tools.h b/sg_agent/src/util/sds_tools.h new file mode 100644 index 0000000..f3148f2 --- /dev/null +++ b/sg_agent/src/util/sds_tools.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef PROJECT_SDS_TOOLS_H +#define PROJECT_SDS_TOOLS_H +#include +#include +namespace meituan_mns{ + +class DiscTools{ + + public: + DiscTools(){}; + ~DiscTools(){}; + /** + * 产生本地缓存键值 + * @param appkey,protocol + * + * @return std::string + * + */ + static std::string LocalCacheKey(const std::string& appkey,const std::string& protocol){ + return protocol + "+" + appkey; + }; + private: + protected: + + + +}; + +} // namespace meituan_mns + +#endif //PROJECT_SDS_TOOLS_H diff --git a/sg_agent/src/util/thrift_client.h b/sg_agent/src/util/thrift_client.h new file mode 100644 index 0000000..9c638a6 --- /dev/null +++ b/sg_agent/src/util/thrift_client.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef SG_AGENT_THRIFT_CLIENT_H +#define SG_AGENT_THRIFT_CLIENT_H +#include "log4cplus.h" +#include "naming_service_types.h" +#include "base_errors_consts.h" +#include "base_consts.h" +#include "inc_comm.h" +#include "config_loader.h" +#include "thrift_connection.h" +#include "mnsc_data_types.h" +namespace meituan_mns { +template +class ThriftClient { + public: + ThriftClient() : thrift_client_(NULL) {} + ~ThriftClient() { + SAFE_DELETE(thrift_client_); + } + //get specific client + T *GetClient() { + return thrift_client_; + } + + int32_t CreateThriftClient(const std::string &ip,const int32_t port,const int32_t timeout) { + boost::shared_ptr tmp_protocol = + thrift_conn_.InitConnection(ip, port, timeout); + if (NULL != tmp_protocol.get()) { + thrift_client_ = new T(tmp_protocol); + return SUCCESS; + } + NS_LOG_ERROR("thrift handler init failed! ip = " << ip + << ", port = " << port); + return FAILURE; + } + + int32_t CheckConn() { + return thrift_conn_.CheckHandler(); + } + + private: + ThriftConn thrift_conn_; + T *thrift_client_; + +}; +} + +#endif //SG_AGENT_THRIFT_COMMON_CLIENT_H diff --git a/sg_agent/src/util/thrift_connection.cc b/sg_agent/src/util/thrift_connection.cc new file mode 100644 index 0000000..3a8e5a8 --- /dev/null +++ b/sg_agent/src/util/thrift_connection.cc @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "thrift_connection.h" +#include "config_loader.h" +namespace meituan_mns { + +ThriftConn::ThriftConn():retry_times_(CXmlFile::GetI32Para(CXmlFile::RetryTimes)) {} + +ThriftConn::~ThriftConn() { + CloseConnection(); +} + + +int32_t ThriftConn::CheckHandler() { + if (!transport_->isOpen()) { + int32_t ret = CloseConnection(); + if (SUCCESS != ret) { + NS_LOG_ERROR("Failed to close connection , ret = " << ret); + return ret; + } + //重新建立连接 + ret = CreateConnection(); + if (SUCCESS != ret) { + NS_LOG_WARN("Failed to create connection! ret = " << ret); + return ret; + } + } + return SUCCESS; +} + +boost::shared_ptr ThriftConn::InitConnection(const std::string &ip, const int32_t port, const int32_t timeout) { + ip_ = ip; + port_ = port; + socket_ = boost::shared_ptr(new TSocket(ip, port)); + transport_ = boost::shared_ptr(new TFramedTransport(socket_)); + protocol_ = boost::shared_ptr(new TBinaryProtocol(transport_)); + socket_->setConnTimeout(timeout); + socket_->setSendTimeout(timeout); + socket_->setRecvTimeout(timeout); + int32_t ret = CreateConnection(); + if (SUCCESS != ret) { + NS_LOG_ERROR("init create connection fail! ret = " << ret); + return boost::shared_ptr(); + } + return protocol_; +} + +int32_t ThriftConn::CreateConnection() { + int count = 0; + while (!transport_->isOpen() && count < retry_times_) { + ++count; + try { + transport_->open(); + NS_LOG_INFO("succeed to create connection, ip = " << ip_ << " port = " << port_); + } catch (TException &e) { + NS_LOG_WARN("Failed to create connection , error : " << e.what()); + } + } + return transport_->isOpen() ? SUCCESS : FAILURE; +} + +int32_t ThriftConn::CloseConnection() { + try { + if (NULL != transport_) { + transport_->close(); + NS_LOG_INFO("succeed to close connection, ip = " << ip_ << ", port = " << port_); + } else { + NS_LOG_ERROR("transport is NULL"); + } + } catch (TException &e) { + NS_LOG_ERROR("ERR, close connection fail! error : " << e.what()); + return ERR_CLOSE_CONNECTION; + } + return SUCCESS; +} + +} diff --git a/sg_agent/src/util/thrift_connection.h b/sg_agent/src/util/thrift_connection.h new file mode 100644 index 0000000..54f1a10 --- /dev/null +++ b/sg_agent/src/util/thrift_connection.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef PROJECT_THRIFT_CONNECTION_H +#define PROJECT_THRIFT_CONNECTION_H + + +#include "log4cplus.h" +#include "naming_service_types.h" +#include "base_errors_consts.h" +#include "inc_comm.h" +#include "config_loader.h" + +namespace meituan_mns { + + +class ThriftConn { + public: + ThriftConn(); + ~ThriftConn(); + + int32_t CheckHandler(); + + /** + * + * @param ip + * @param port + * @return + */ + boost::shared_ptr InitConnection(const std::string &ip, const int32_t port, const int32_t timeout); + + private: + int32_t CreateConnection(); + + int32_t CloseConnection(); + + private: + bool is_closed_; + int retry_times_; + std::string ip_; + int port_; + boost::shared_ptr socket_; + boost::shared_ptr transport_; + boost::shared_ptr protocol_; + +}; + + +} + +#endif //PROJECT_THRIFT_CONNECTION_H diff --git a/sg_agent/src/util/version_manager.cc b/sg_agent/src/util/version_manager.cc new file mode 100644 index 0000000..501d4bc --- /dev/null +++ b/sg_agent/src/util/version_manager.cc @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "version_manager.h" +#include "log4cplus.h" +namespace meituan_mns { + +VersionManager::VersionManager(){ + + zk_update_time_ = 1800; + zk_update_rand_time_ = 0; + key_buffer_ = boost::shared_ptr < BufferMgr < int > > (new BufferMgr()); + + srand(time(0)); + zk_update_rand_time_ = rand() % 100; +} + +//本地version与ZK上相同,如果超过半小时都没更新,则主动更新一次 +int32_t VersionManager::CheckZkVersion(const std::string &key, + const std::string &zk_version, + std::string &version) { + int last_time = 0; + int hasKey = key_buffer_->get(key, last_time); + + int curr_time = time(0); + if ((version == zk_version) && 0 == hasKey) { + if ((curr_time - last_time) > (zk_update_time_ + zk_update_rand_time_)) { + NS_LOG_INFO("start to update zk data! appkey : " << key); + } else { + NS_LOG_DEBUG("the data is the same as buf, key : " << key + << ", version : " << version); + return ERR_ZK_LIST_SAME_BUFFER; + } + } + key_buffer_->insert(key, curr_time); + NS_LOG_INFO("version is different from zk_version,need to update!"); + version = zk_version; + + return 0; +} +bool VersionManager::IsOldVersion(const std::string &version) { + if (version.empty()) { + return true; + } + std::string mtthrift_str("mtthrift"); + std::string cthrift_str("cthrift"); + std::string pigeon_str("pigeon"); + if (std::string::npos != version.find(mtthrift_str)) { + NS_LOG_INFO("version is mtthfit: " << version); + return CompareMTVersion(version); + } else if (('0' <= version[0] && '9' >= version[0]) || + (std::string::npos != version.find(pigeon_str))) { + NS_LOG_INFO("version is pigeon: " << version); + return ComparePigeonVersion(version); + } else if (std::string::npos != version.find(cthrift_str)) { + NS_LOG_INFO("version is cthrift: " << version); + return CompareCthriftVersion(version); + } else { + NS_LOG_INFO("not need to check the version : " << version); + return false; + } +} +bool VersionManager::CompareCthriftVersion(const std::string &version) { + std::vector c; + GetVersion(version, &c); + int ret = CompareVector(c, old_cthrift_version_); + return (0 > ret); +} + +bool VersionManager::ComparePigeonVersion(const std::string &version) { + std::vector p; + GetVersion(version, &p); + int ret = CompareVector(p, old_pigeon_version_); + return (0 > ret); +} +bool VersionManager::CompareMTVersion(const std::string &version) { + std::vector mt; + GetVersion(version, &mt); + int ret = CompareVector(mt, old_mtthrift_version_); + return (0 > ret); +} +int32_t VersionManager::CompareVector(const std::vector &a, + const std::vector &b) { + int i_min_size = a.size() > b.size() ? b.size() : a.size(); + for (int i = 0; i < i_min_size; i++) { + if (a[i] > b[i]) { + return 1; + } else if (a[i] < b[i]) { + return -1; + } + } + return 0; +} +void VersionManager::GetVersion(const std::string &strVersion, + std::vector *p_vec_version) { + std::string strLast; + std::stringstream ss; + int i_val; + for (int i = 0; i < strVersion.size(); i++) { + if ('.' == strVersion[i]) { + //字符串转换成整型 + ss << strLast; + ss >> i_val; + ss.str(""); + if (ss.eof()) { + ss.clear(); + } + p_vec_version->push_back(i_val); + strLast.clear(); + } else if ('0' <= strVersion[i] && '9' >= strVersion[i]) { + strLast += strVersion[i]; + } + } + + ss << strLast; + ss >> i_val; + ss.str(""); + p_vec_version->push_back(i_val); +} + + +} // namespace meituan_mns diff --git a/sg_agent/src/util/version_manager.h b/sg_agent/src/util/version_manager.h new file mode 100644 index 0000000..74f2643 --- /dev/null +++ b/sg_agent/src/util/version_manager.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_ZKTOOLS_H +#define OCTO_OPEN_SOURCE_ZKTOOLS_H +#include + +#include "zk_path_tools.h" +#include "base_consts.h" +#include "buffer_mgr.h" +namespace meituan_mns { + +class VersionManager { + public: + VersionManager(); + ~VersionManager() {} + /** + * + * @param appkey + * @param zk_version + * @param version + * @return + */ + int CheckZkVersion(const std::string &appkey, + const std::string &zk_version, + std::string &version); + /** + * + * @param version + * @return + */ + bool IsOldVersion(const std::string &version); + + + private: + + //mthrift < 1.7.0 + bool CompareMTVersion(const std::string &version); + //piegon < 2.8 + bool ComparePigeonVersion(const std::string &version); + //cthrift < 2.6.0 + bool CompareCthriftVersion(const std::string &version); + /** + * 字符串中的版本号信息提取到vector + * @param version_str + * @param p_vec_version + */ + void GetVersion(const std::string &version_str, + std::vector *p_vec_version); + + /** + * 暂不支持两个长度不等的判断 + * @param a + * @param b + * @return + */ + int32_t CompareVector(const std::vector &a, + const std::vector &b); + + private: + + int32_t zk_update_time_; + int32_t zk_update_rand_time_; + boost::shared_ptr > key_buffer_; + + std::vector old_mtthrift_version_; + std::vector old_pigeon_version_; + std::vector old_cthrift_version_; + +}; + +} // namespace meituan_mns + + +#endif //OCTO_OPEN_SOURCE_ZKTOOLS_H diff --git a/sg_agent/src/util/whitelist_manager.cc b/sg_agent/src/util/whitelist_manager.cc new file mode 100644 index 0000000..46d9939 --- /dev/null +++ b/sg_agent/src/util/whitelist_manager.cc @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "whitelist_manager.h" +#include "log4cplus.h" + +namespace meituan_mns { +bool WhiteListManager::IsAppkeyInWhitList(const std::string &appkey) { + UnorderedMapPtr set_ptr = + CXmlFile::GetWhiteAppkeys(CXmlFile::NoWatcherWhiteLists); + return IsAppkeyList(appkey, set_ptr); +} + +bool WhiteListManager::IsAppkeyInRegistUnlimitWhitList(const std::string &appkey) { + UnorderedMapPtr set_ptr = + CXmlFile::GetWhiteAppkeys(CXmlFile::RegisteUnlimitWhiteList); + return IsAppkeyList(appkey, set_ptr); +} + +bool WhiteListManager::IsAppkeyInAllEnvWhitList(const std::string &appkey) { + UnorderedMapPtr set_ptr = + CXmlFile::GetWhiteAppkeys(CXmlFile::AllEnvWhiteLists); + return IsAppkeyList(appkey,set_ptr); +} + +bool WhiteListManager::IsMacRegisterAppkey(const std::string &appkey) { + UnorderedMapPtr set_ptr = + CXmlFile::GetWhiteAppkeys(CXmlFile::MacRegisterUnlimitAppkeys); + return IsAppkeyList(appkey, set_ptr); +} + + +bool WhiteListManager::IsAppkeyContains(const std::string &appkey, + const UnorderedMapPtr &appkeys) { + if (appkey.empty()) { + NS_LOG_WARN("fileconfig req appkey is empty!"); + return false; + } + for (boost::unordered_set::const_iterator iter = appkeys->begin(); + appkeys->end() != iter; ++iter) { + if (std::string::npos != appkey.find(*iter)) { + NS_LOG_INFO(appkey << " is in the appkey white list : " << *iter); + return true; + } + } + return false; +} + +bool WhiteListManager::IsAppkeyList(const std::string &appkey, + const UnorderedMapPtr &appkeys) { + if (appkey.empty()) { + NS_LOG_WARN("fileconfig req appkey is empty!"); + return false; + } + for (boost::unordered_set::const_iterator iter = appkeys->begin(); + appkeys->end() != iter; ++iter) { + if (std::string::npos != appkey.find(*iter)) { + NS_LOG_INFO(appkey << " is in the appkey white list : " << *iter); + return true; + } + } + return false; +} +} diff --git a/sg_agent/src/util/whitelist_manager.h b/sg_agent/src/util/whitelist_manager.h new file mode 100644 index 0000000..456922d --- /dev/null +++ b/sg_agent/src/util/whitelist_manager.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _whitelist_mgr_H__ +#define _whitelist_mgr_H__ + +#include +#include "config_loader.h" + +namespace meituan_mns { + +class WhiteListManager { + public: + WhiteListManager() {} + ~WhiteListManager() {} + /** + * + * @param appkey + * @return + */ + bool IsAppkeyInWhitList(const std::string &appkey); + /** + * + * @param appkey + * @return + */ + bool IsAppkeyInRegistUnlimitWhitList(const std::string &appkey); + /** + * + * @param appkey + * @return + */ + bool IsAppkeyInAllEnvWhitList(const std::string &appkey); + + /** + * + * @param appkey + * @return + */ + bool IsMacRegisterAppkey(const std::string &appkey); + private: + /** + * + * @param appkey + * @param appkeys + * @return + */ + bool IsAppkeyContains(const std::string &appkey, + const UnorderedMapPtr &appkeys); + /** + * + * @param appkey + * @param appkeys + * @return + */ + bool IsAppkeyList(const std::string &appkey, + const UnorderedMapPtr &appkeys); +}; + +} + +#endif diff --git a/sg_agent/src/util/zk_path_tools.cc b/sg_agent/src/util/zk_path_tools.cc new file mode 100644 index 0000000..cac7b09 --- /dev/null +++ b/sg_agent/src/util/zk_path_tools.cc @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "zk_path_tools.h" +#include "base_consts.h" +#include "base_errors_consts.h" +#include "base_mns_consts.h" +#include "log4cplus.h" +#include +#include "config_loader.h" + +namespace meituan_mns { + +const std::string provider_appkey = "/octo/nameservice"; +const std::string provider_srvname = "/octo/service/"; +const std::string ProtocolProviderThriftTail = "provider"; +const std::string ProtocolRouteThriftTail = "route"; +const std::string ProtocolProviderHttpTail = "provider-http"; +const std::string ProtocolRouteHttpTail = "route-http"; + + +int32_t AgentZkPath::GenNodeType(std::string &nodeType, + const std::string &protocol) { + //protocol变量 + if (protocol.empty()) { + NS_LOG_ERROR("protocol cannot be empty."); + return FAILURE; + } else { + //新接口访问,thrift或者http服务 + if ("http" == protocol) { + nodeType += "-http"; + } else if ("thrift" == protocol) { + NS_LOG_DEBUG("nodeType: " << nodeType << " not changed"); + } else { + nodeType = nodeType + "s/" + protocol; + } + NS_LOG_DEBUG("nodeType in newInterface: " << nodeType); + } + return SUCCESS; +} + +int32_t AgentZkPath::GenProtocolZkPath(std::string &path, + const std::string &appkey, + const std::string &protocol, + std::string &node_type) { + std::string current_env(CXmlFile::GetAppenv()->GetStrEnv()); + int32_t ret = GetEnvByAppkeyWhiteList(current_env, appkey); + if (SUCCESS != ret) { + return ret; + } + ret = GenNodeType(node_type, protocol); + if (SUCCESS != ret) { + return ret; + } + path = provider_appkey + "/" +current_env + "/" + appkey + "/" + node_type; + return SUCCESS; +} + +int32_t AgentZkPath::GenRegisterZkPath(std::string &path, + const std::string &appkey, + const std::string &protocol, + const int serverType) { + std::string current_env(CXmlFile::GetAppenv()->GetStrEnv()); + int ret = GetEnvByAppkeyWhiteList(current_env, appkey); + if (SUCCESS != ret) { + return ret; + } + //获取nodeType + std::string providerType = "provider"; + if ((!protocol.empty())) { + if ("http" == protocol) { + providerType += "-http"; + } else if ("thrift" == protocol) { + NS_LOG_DEBUG("thrift in newInterface: " << providerType); + } else { + providerType = providerType + "s/" + protocol; + } + NS_LOG_INFO("provider in newInterface: " << providerType); + } else { + //为了应对前端未修改protocol的情况 + if (HTTP_TYPE == serverType) { + providerType += "-http"; + } + NS_LOG_DEBUG("provider in oldInterface: " << providerType); + } + NS_LOG_INFO("zkPath provider prefix: " << providerType); + + path = provider_appkey + "/" +current_env + "/" + appkey + "/" + + providerType; + + return SUCCESS; +} + +int32_t AgentZkPath::GenServiceNameZkPathNode(std::string &path, + const std::string &service_name, + const std::string &protocol, + const std::string &appkey) { + std::string current_env(CXmlFile::GetAppenv()->GetStrEnv()); + GetEnvByAppkeyWhiteList(current_env, appkey); + std::string new_servicename = ReplaceHttpServiceName(service_name); + + //拼接zkPath + path = provider_srvname + current_env + "/" + new_servicename + "/" + protocol; + + return SUCCESS; +} + +std::string AgentZkPath::ReplaceHttpServiceName(const std::string &servicename) { + std::string result; + for (int i = 0; i < servicename.size(); ++i) { + // replace the / with ^ + result.push_back('/' == servicename[i] ? '^' : servicename[i]); + } + return result; +} + +int32_t AgentZkPath::GenDescZkPath(std::string &path, + const std::string &appkey) { + + std::string current_env(CXmlFile::GetAppenv()->GetStrEnv());// 因为GetEnvByAppkeyWhiteList会修改第一个参数,因此必须使用临时变量 + int32_t ret = GetEnvByAppkeyWhiteList(current_env, appkey); + if (SUCCESS != ret) { + return ret; + } + + path = provider_appkey + "/" + appkey + "/desc"; + + return ret; +} +int32_t AgentZkPath::DeGenZkPath(const char *zkPath, + std::string &appkey, + std::string &protocol) { + std::vector pathList; + int32_t size = SplitStringIntoVector(zkPath, "/", pathList); + if (0 < size) { + int length = pathList.size(); + //这里必须保证zkPath符合 /octo/naming/环境/appkey/(nodeType + protocol) + if(4 < length) { + //appkey在数组的下标是4,是因为pathList[0]是"" + appkey = pathList[4]; + if(appkey.empty()) { + NS_LOG_ERROR("deGenZkPath appkey is empty! zkPath" << zkPath); + return -3; + } + //protocol取最后一个,有可能是cellar, provider, provider-http + protocol = pathList[length - 1]; + if(protocol.empty()) { + NS_LOG_ERROR("deGenZkPath protocol is empty! zkPath" << zkPath); + return -3; + } + } + else { + NS_LOG_ERROR("zkPath is not complete! zkPath: " << zkPath + << ", appkey: " << appkey + << ", length: " << length); + return -2; + } + } else { + NS_LOG_ERROR("zkPath is wroing! zkPath: " << zkPath << ", appkey:" << appkey); + return -1; + } + int32_t ret = DeGenNoDeGenNodeType(protocol); + if(SUCCESS != ret) { + NS_LOG_ERROR("deGenNodeType is wrong! protocol:" << protocol); + } + + return ret; +} + +int32_t AgentZkPath::DeGenNoDeGenNodeType(std::string &protocol) { + if(protocol.empty()) { + NS_LOG_ERROR("protocol in deGenNodeType is empty! "); + return FAILURE; + } + if(0 == protocol.compare(ProtocolProviderHttpTail) + || 0 == protocol.compare(ProtocolRouteHttpTail)) { + protocol = "http"; + } else if (0 == protocol.compare(ProtocolProviderThriftTail) + || 0 == protocol.compare(ProtocolRouteThriftTail)) { + protocol = "thrift"; + } else { + NS_LOG_INFO("when watcher trigger, in deGenNodeType, protocol:" << protocol); + } + return SUCCESS; +} + + +int32_t AgentZkPath::GetEnvByAppkeyWhiteList(std::string &env_str, + const std::string &appkey) { + if (appkey.empty()) { + NS_LOG_WARN("appkey cannot be empty."); + return FAILURE; + } + + if (whitelist_manager_.IsAppkeyInAllEnvWhitList(appkey)) { + //在白名单内的appkey, 环境强制改成prod + NS_LOG_INFO("the appkey: " << appkey << ", current the env is: " << env_str << " change to prod"); + env_str = "prod"; + } + return SUCCESS; +} + +std::string AgentZkPath::GenRoutePath(const std::string &zk_path, + const std::string &data_path) { + return zk_path + "/" + data_path; +} +} // namespace meituan_mns + diff --git a/sg_agent/src/util/zk_path_tools.h b/sg_agent/src/util/zk_path_tools.h new file mode 100644 index 0000000..48b382d --- /dev/null +++ b/sg_agent/src/util/zk_path_tools.h @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_ZK_PATH_TOOLS_H +#define OCTO_OPEN_SOURCE_ZK_PATH_TOOLS_H + +#include "naming_common_types.h" +#include "base_mns_consts.h" +#include "inc_comm.h" +#include "whitelist_manager.h" + +namespace meituan_mns { + + +class AgentZkPath { + public: + AgentZkPath() {} + ~AgentZkPath() {} + /** + * + * @param provider_path + * @param appkey + * @param protocol + * @param nodeType + * @return + */ + int32_t GenProtocolZkPath(std::string &provider_path, + const std::string &appkey, + const std::string &protocol, + std::string &nodeType); + /** + * + * @param provider_path + * @param appkey + * @param protocol + * @param serverType + * @return + */ + int32_t GenRegisterZkPath(std::string &provider_path, + const std::string &appkey, + const std::string &protocol, + const int serverType); + /** + * + * @param provider_path + * @param serviceName + * @param protocol + * @param appkey + * @return + */ + int32_t GenServiceNameZkPathNode(std::string &provider_path, + const std::string &serviceName, + const std::string &protocol, + const std::string &appkey = ""); + /** + * + * @param provider_path + * @param appkey + * @return + */ + int32_t GenDescZkPath(std::string &provider_path, + const std::string &appkey); + /** + * + * @param env_str + * @param appkey + * @return + */ + int32_t GetEnvByAppkeyWhiteList(std::string &env_str, + const std::string &appkey); + /** + * + * @param nodeType + * @param protocol + * @return + */ + int32_t GenNodeType(std::string &nodeType, + const std::string &protocol); + + /** + * + * @param servicename + * @return + */ + std::string ReplaceHttpServiceName(const std::string &servicename); + /** + * + * @param protocol + * @return + */ + static int32_t DeGenNoDeGenNodeType(std::string &protocol); + + /** + * + * @param zk_path + * @param data_path + * @return + */ + std::string GenRoutePath(const std::string &zk_path, + const std::string &data_path); + + + /** + * + * @param zkPath + * @param appkey + * @param protocol + * @return + */ + static int32_t DeGenZkPath(const char* zkPath, + std::string &appkey, + std::string &protocol); + + private: + WhiteListManager whitelist_manager_; + +}; +} // namespace meituan_mns + +#endif //OCTO_OPEN_SOURCE_ZK_PATH_TOOLS_H diff --git a/sg_agent/test/CMakeLists.txt b/sg_agent/test/CMakeLists.txt new file mode 100644 index 0000000..2395e4e --- /dev/null +++ b/sg_agent/test/CMakeLists.txt @@ -0,0 +1,99 @@ +cmake_minimum_required(VERSION 2.8) + +INCLUDE_DIRECTORIES(${THRIFT_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(/usr/include) +INCLUDE_DIRECTORIES(${CLOG_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${MUDUO_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${ZOOKEEPER_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${THRIFT_GEN_CPP_PATH}) +INCLUDE_DIRECTORIES(${AGENT_SRC_PATH}) +INCLUDE_DIRECTORIES(${CTHRIFT_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${UTIL_PATH}) +INCLUDE_DIRECTORIES(${RULE_PATH}) +INCLUDE_DIRECTORIES(${MAFKA_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${MONITOR_COLLECTOR_PATH}) +INCLUDE_DIRECTORIES(${LOG4CPLUS_PATH}) +INCLUDE_DIRECTORIES(${LOG4CPLUS_INCLUDE_DIR}) +INCLUDE_DIRECTORIES(${COMMON_PATH}) +INCLUDE_DIRECTORIES(${MNS_PATH}) +INCLUDE_DIRECTORIES(../../thrid_party/log4cplus) +INCLUDE_DIRECTORIES(../mns) +INCLUDE_DIRECTORIES(../util) +INCLUDE_DIRECTORIES(../comm) +INCLUDE_DIRECTORIES(../../common/gen-cpp) +INCLUDE_DIRECTORIES(../remote/monitor) +INCLUDE_DIRECTORIES(../rule) + +add_definitions(-Wall) + +IF (ENABLE_COVERAGE) + SET(CMAKE_CXX_FLAGS "-g -Wall -O0 -fPIC -DMUDUO_STD_STRING -DHAVE_NETINET_IN_H -DGTEST") +ELSE () + SET(CMAKE_CXX_FLAGS "-g -Wall -O2 -fPIC -DMUDUO_STD_STRING -DHAVE_NETINET_IN_H -DGTEST") +ENDIF () +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_CLOG_SUPPORT") +SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") +MESSAGE(STATUS "CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}") +IF (ENABLE_COVERAGE) + include(CodeCoverage) + APPEND_COVERAGE_COMPILER_FLAGS() +ENDIF () +MESSAGE(STATUS "CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}") +option(CHRION_DOWNLOAD_GTEST "Download and build a fresh copy of googletest. Requires Internet access." ON) +set(CHRION_SYSTEM_GTEST_SOURCE_DIR "" CACHE PATH "System googletest source directory.") +if (CHRION_DOWNLOAD_GTEST) + include(SetupGtest) + elseif (CHRION_SYSTEM_GTEST_SOURCE_DIR) + add_subdirectory("${CHRION_SYSTEM_GTEST_SOURCE_DIR}" "${PROJECT_BINARY_DIR}/system-googletest-build") +else () + message(FATAL_ERROR "Googletest is not available") +endif () + +SET(THRIFT_GEN_CPP_PATH ../../common/gen-cpp) +MESSAGE(STATUS "THRIFT_GEN_CPP_PATH DIR ${THRIFT_GEN_CPP_PATH}") + +SET(THRIFT_GENCPP_SRCS + ${THRIFT_GEN_CPP_PATH}/MNSCacheService.cpp + ${THRIFT_GEN_CPP_PATH}/mnsc_data_constants.cpp + ${THRIFT_GEN_CPP_PATH}/mnsc_data_types.cpp + ${THRIFT_GEN_CPP_PATH}/mnsc_service_constants.cpp + ${THRIFT_GEN_CPP_PATH}/mnsc_service_types.cpp + ${THRIFT_GEN_CPP_PATH}/naming_common_constants.cpp + ${THRIFT_GEN_CPP_PATH}/naming_common_types.cpp + ${THRIFT_GEN_CPP_PATH}/naming_service_constants.cpp + ${THRIFT_GEN_CPP_PATH}/naming_service_types.cpp + ${THRIFT_GEN_CPP_PATH}/unified_protocol_constants.cpp + ${THRIFT_GEN_CPP_PATH}/unified_protocol_types.cpp + ${THRIFT_GEN_CPP_PATH}/ServiceAgent.cpp + ) + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") +SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage-lgcov") + +AUX_SOURCE_DIRECTORY(. TEST_SRCS) +AUX_SOURCE_DIRECTORY(../src/comm AGENT_COMM_SRCS) +AUX_SOURCE_DIRECTORY(../src/util AGENT_UTILS_SRCS) +AUX_SOURCE_DIRECTORY(../src/rule AGENT_RULE_SRCS) +AUX_SOURCE_DIRECTORY(../src/mns AGENT_MNS_SRCS) +AUX_SOURCE_DIRECTORY(../remote/monitor MONITOR_COLLECTOR_SRCS) +AUX_SOURCE_DIRECTORY(../../thrid_party/logs/log4cplus AGENT_LOG4CPLUS_SRCS) +INCLUDE_DIRECTORIES(SYSTEM ${GTEST_INCLUDE_DIR}) + + +ADD_EXECUTABLE(agent_unittest ${TEST_SRCS} ${AGENT_MNS_SRCS} ${AGENT_MCC_SRCS} + ${AGENT_FALCON_SRCS} ${AGENT_COMMONLOG_SRCS} ${AGENT_LOG4CPLUS_SRCS} + ${MUDUO_BASE_LIBRARY} + ${THRIFT_GENCPP_SRCS} ${AGENT_COMM_SRCS} ${AGENT_UTILS_SRCS} + ${AGENT_RULE_SRCS} ${AGENT_MAFKA_SRCS} ${MONITOR_COLLECTOR_SRCS} + ) + +TARGET_LINK_LIBRARIES(agent_unittest -Xlinker "-(" + ${THRIFT_STATIC_LIB} ${CTHRIFT_LIBRARY} ${LOG4CPLUS_LIBRARY} + ${MUDUO_NET_LIBRARY} ${MUDUO_HTTP_LIBRARY} + ${ZOOKEEPER_LIBRARY} ${THRIFTNB_STATIC_LIB} + boost_system event uuid ssl dl + gtest pthread rt -Xlinker "-)" -Wl + ) + + diff --git a/sg_agent/test/build_unittest.sh b/sg_agent/test/build_unittest.sh new file mode 100755 index 0000000..89cd87a --- /dev/null +++ b/sg_agent/test/build_unittest.sh @@ -0,0 +1,6 @@ +#!/bin/sh +cmake -DCMAKE_BUILD_TYPE=debug ../sg_agent/CMakeLists.txt +cd test +make -j8 + +mv -f ../../bin/unittest ./ diff --git a/sg_agent/test/clean.sh b/sg_agent/test/clean.sh new file mode 100755 index 0000000..377f6a2 --- /dev/null +++ b/sg_agent/test/clean.sh @@ -0,0 +1,7 @@ +#!/bin/sh +#cmake -DCMAKE_BUILD_TYPE=debug src/CMakeLists.txt +#cd src/test +#make -j8 + +#mv -f ../../bin/unittest ./ +rm -rf CMakeFiles CMakeCache.txt cmake_install.cmake Makefile diff --git a/sg_agent/test/main.cpp b/sg_agent/test/main.cpp new file mode 100644 index 0000000..6d94d13 --- /dev/null +++ b/sg_agent/test/main.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include "mns/agent_server.h" +#include "mns/agent_init.h" +#include +#include +using namespace std; +using namespace muduo; +using namespace muduo::net; +using namespace meituan_mns; +typedef void *HANDLE; + +extern "C" { +int InitHost(); +} + +void* StartServer(void* args) { + + string str_svr_appkey("octo.naming.sg_agent"); //服务端的appkey + uint16_t u16_port = 5266; + bool b_single_thread = false; //当时单线程运行时,worker thread num 只能是1 + int32_t i32_timeout_ms = 30; + int32_t i32_max_conn_num = 20000; + int16_t i16_worker_thread_num = 4; + + std::cout << "start server........." << std::endl; + + try { + boost::shared_ptr handler(new meituan_mns::SGAgentServer()); + meituan_mns::ServiceAgentProcessor *processor_tmp = new + meituan_mns::ServiceAgentProcessor(handler); + boost::shared_ptr processor(processor_tmp); + + meituan_cthrift::CthriftSvr server(processor); + + if(server.Init() != 0) { + cerr << "server init error" << endl; + return NULL; + } + meituan_mns::AgentInit agent_init; + agent_init.Init(); + + sleep(6); + server.serve(); + std::cout << "start server...exit" << std::endl; + } catch (meituan_cthrift::TException &tx) { + return NULL; + } catch (int e) { + return (void*)(&e); + } + + return 0; +} +int InitHost(void) { + + pthread_t tid; + tid = pthread_create(&tid, NULL, StartServer, NULL); + sleep(20); + if(tid < 0){ + std::cout << "create thread failed..." << std::endl; + return -1; + } + return 0; +} +int main(int argc, char **argv) { + AgentInit agent_init; + agent_init.Init(); + int ret = InitHost(); + if (0 != ret) { + return -1; + } + testing::InitGoogleTest(&argc, argv); + sleep(10); + RUN_ALL_TESTS(); + return 0; +} + diff --git a/sg_agent/test/naming_config_loader_unittest.cc b/sg_agent/test/naming_config_loader_unittest.cc new file mode 100644 index 0000000..0980985 --- /dev/null +++ b/sg_agent/test/naming_config_loader_unittest.cc @@ -0,0 +1,151 @@ + +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#define private public +#define protected public +#include "config_loader.h" +#undef private +#undef protected +#include "base_consts.h" +#include "base_errors_consts.h" + +using namespace meituan_mns; + +class ConfigLoaderTest : public testing::Test { + + public: + void SetUp() { + } + public: + CXmlFile cxml_file_; + +}; + +TEST_F(ConfigLoaderTest, CXmlFileInitTest) { + + EXPECT_EQ(0,cxml_file_.CXmlFileInit()); +} + + +TEST_F(ConfigLoaderTest, InitEnvTest) { + std::string env_str = "test"; + std::string deployenv_str = "test"; + EXPECT_EQ(0, cxml_file_.InitEnv(env_str, deployenv_str)); + + env_str = "unknown"; + EXPECT_EQ(0, cxml_file_.InitEnv(env_str, deployenv_str)); + deployenv_str = "unknown"; + EXPECT_EQ(-102010, cxml_file_.InitEnv(env_str, deployenv_str)); +} + +TEST_F(ConfigLoaderTest, LoadMutableFileTest) { + EXPECT_EQ(0, cxml_file_.LoadMutableFile()); + +} + +TEST_F(ConfigLoaderTest, LoadWhiteFileTest) { + EXPECT_EQ(0, cxml_file_.LoadWhiteFile()); + +} + +TEST_F(ConfigLoaderTest ,InitAddrInfo) { + EXPECT_EQ(0, cxml_file_.InitAddrInfo()); + EXPECT_STREQ("127.0.0.1", CXmlFile::GetStrPara(CXmlFile::LocalIp).c_str()); + EXPECT_STREQ("255.255.255.0",CXmlFile::GetStrPara(CXmlFile::LocalMask).c_str()); +} + +TEST_F(ConfigLoaderTest, LoadWhiteAppkeysTest) { + tinyxml2::XMLDocument agent_whitelist; + const tinyxml2::XMLError agent_xml_ret = + agent_whitelist.LoadFile(AGENT_WHITELIST_CONF.c_str()); + + if (tinyxml2::XML_SUCCESS == agent_xml_ret) { + const tinyxml2::XMLElement *agent_xml_conf = + agent_whitelist.FirstChildElement("SGAgentWhiteListConf"); + if (NULL != agent_xml_conf) { + EXPECT_EQ(0, cxml_file_.LoadWhiteAppkeys(agent_xml_conf, + CXmlFile::MacRegisterUnlimitAppkeys)); + EXPECT_EQ(0, cxml_file_.LoadWhiteAppkeys(agent_xml_conf, + CXmlFile::AllEnvWhiteLists)); + EXPECT_EQ(0, cxml_file_.LoadWhiteAppkeys(agent_xml_conf, + CXmlFile::RegisteUnlimitWhiteList)); + EXPECT_EQ(0, cxml_file_.LoadWhiteAppkeys(agent_xml_conf, + CXmlFile::NoWatcherWhiteLists)); + CXmlFile::Type type = static_cast(-1); + EXPECT_EQ(-1, cxml_file_.LoadWhiteAppkeys(agent_xml_conf, type)); + } + } +} + +TEST_F(ConfigLoaderTest, LoadAgentFuncFlagTest) { + + tinyxml2::XMLDocument agent_mutable; + const tinyxml2::XMLError agent_xml_ret = + agent_mutable.LoadFile(AGENT_MUTABLE_CONF.c_str()); + if (tinyxml2::XML_SUCCESS == agent_xml_ret) { + const tinyxml2::XMLElement *agent_xml_conf = + agent_mutable.FirstChildElement("SGAgentMutableConf"); + if (NULL != agent_xml_conf) { + EXPECT_EQ(0, cxml_file_.LoadAgentFuncFlag(agent_xml_conf)); + } + } + +} + +TEST_F(ConfigLoaderTest, LoadRegisterWhitelistIdcTest) { + tinyxml2::XMLDocument agent_whitelist; + const tinyxml2::XMLError agent_xml_ret = + agent_whitelist.LoadFile(AGENT_WHITELIST_CONF.c_str()); + + if (tinyxml2::XML_SUCCESS == agent_xml_ret) { + const tinyxml2::XMLElement *agent_xml_conf = + agent_whitelist.FirstChildElement("SGAgentWhiteListConf"); + if (NULL != agent_xml_conf) { + EXPECT_EQ(0, cxml_file_.LoadRegisterWhitelistIdc(agent_xml_conf)); + } + } +} + + +TEST_F(ConfigLoaderTest, LoadZkConfigTest) { + tinyxml2::XMLDocument agent_mutable; + const tinyxml2::XMLError agent_xml_ret = + agent_mutable.LoadFile(AGENT_MUTABLE_CONF.c_str()); + if (tinyxml2::XML_SUCCESS == agent_xml_ret) { + const tinyxml2::XMLElement *agent_xml_conf = + agent_mutable.FirstChildElement("SGAgentMutableConf"); + if (NULL != agent_xml_conf) { + EXPECT_EQ(0, cxml_file_.LoadZkConfig(agent_xml_conf)); + } + } + +} + +TEST_F(ConfigLoaderTest, LoadIdcFileTest) { + IdcsPtr idcs = boost::make_shared > >(); + EXPECT_EQ(0, cxml_file_.LoadIdcFile(idcs)); + if (idcs.get() != NULL) { + EXPECT_EQ(0,0); + } +} diff --git a/sg_agent/test/naming_disc_service_unittest.cc b/sg_agent/test/naming_disc_service_unittest.cc new file mode 100644 index 0000000..cc57b53 --- /dev/null +++ b/sg_agent/test/naming_disc_service_unittest.cc @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include "base_consts.h" +#include "base_mns_consts.h" +#include "base_errors_consts.h" +#include +#include +#include "service_channels.h" +#include "sds_tools.h" +#define private public +#define protected public +#include "discovery_service.h" +#undef private +#undef protected + +using namespace meituan_mns; + +class DiscServiceTest : public testing::Test { + + public: + void SetUp() { + std::vector service_list; + SGService service1, service2; + service1.__set_ip("127.0.0.1"); + service1.__set_protocol("protocol"); + service1.__set_appkey("octo.naming.service.tmy"); + service1.__set_port(5266); + service1.__set_version("dev"); + service1.__set_weight(-1); + service1.__set_fweight(101.0); + service1.__set_ip("127.0.0.1"); + service1.__set_protocol("protocol"); + service1.__set_appkey("octo.naming.service.tmy"); + service1.__set_port(5266); + service1.__set_version("dev"); + service1.__set_weight(0); + service1.__set_fweight(101); + service_list.push_back(service1); + service_list.push_back(service2); + node = boost::make_shared(); + node->__set_localAppkey(""); + node->__set_remoteAppkey("octo.naming.service.tmy"); + node->__set_serviceList(service_list); + node->__set_protocol("thrift"); + discovery_service_ = DiscoveryService::GetInstance(); + + req.protocol = "thrift"; + req.remoteAppkey = "octo.naming.service.tmy"; + req.serviceName = "http://mns.octo.com"; + service_channel = boost::make_shared(); + service_channel->SetAllChannel(false); + service_channel->SetBankboneChannel(false); + service_channel->SetOriginChannel(false); + service_channel->SetSwimlaneChannel(false); + } + public: + boost::shared_ptr node; + DiscoveryService *discovery_service_; + ProtocolRequest req; + boost::shared_ptr service_channel; +}; + +TEST_F(DiscServiceTest, DiscGetSrvListTest) { + + std::vector srvlist; + ProtocolRequest req; + req.protocol = "thrift"; + req.remoteAppkey = "octo.naming.service.tmy"; + boost::shared_ptr service_channel = boost::make_shared(); + service_channel->SetAllChannel(false); + service_channel->SetBankboneChannel(false); + service_channel->SetOriginChannel(false); + service_channel->SetSwimlaneChannel(false); + EXPECT_EQ(0, discovery_service_->DiscGetSrvList(srvlist, req, service_channel)); + +} + +TEST_F(DiscServiceTest, DiscNodesFromZkTest) { + std::vector srvlist; + ProtocolRequest req; + req.protocol = "thrift"; + req.remoteAppkey = "octo.naming.service.tmy"; + EXPECT_EQ(0, discovery_service_->DiscNodesFromZk(srvlist, req)); + EXPECT_EQ(-3, discovery_service_->DiscNodesFromZk(srvlist, req)); + req.remoteAppkey = "test"; + EXPECT_EQ(-101, discovery_service_->DiscNodesFromZk(srvlist, req)); +} diff --git a/sg_agent/test/naming_http_service_unittest.cc b/sg_agent/test/naming_http_service_unittest.cc new file mode 100644 index 0000000..e726f3b --- /dev/null +++ b/sg_agent/test/naming_http_service_unittest.cc @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "config_loader.h" +#include +#include "base_errors_consts.h" +#include "registry_service.h" +#include "base_mns_consts.h" +#include "base_consts.h" +#include +#include +#include "service_channels.h" +#include "sds_tools.h" + + +#define private public +#define protected public +#include "../mns/http_service.h" +#undef private +#undef protected + +using namespace meituan_mns; + +class HttpServiceTest : public testing::Test { + public: + void SetUp() { + std::vector service_list; + SGService service1, service2; + service1.__set_ip("127.0.0.1"); + service1.__set_protocol("protocol"); + service1.__set_appkey("octo.naming.service.tmy"); + service1.__set_port(5266); + service1.__set_version("dev"); + service1.__set_weight(-1); + service1.__set_fweight(101.0); + service1.__set_ip("10.4.245.3"); + service1.__set_protocol("protocol"); + service1.__set_appkey("octo.naming.service.tmy"); + service1.__set_port(5266); + service1.__set_version("dev"); + service1.__set_weight(0); + service1.__set_fweight(101); + service_list.push_back(service1); + service_list.push_back(service2); + node = boost::make_shared(); + node->__set_localAppkey(""); + node->__set_remoteAppkey("octo.naming.service.tmy"); + node->__set_serviceList(service_list); + node->__set_protocol("thrift"); + http_server_ = HttpService::GetInstance(); + } + public: + HttpService *http_server_; + boost::shared_ptr node; + ProtocolRequest req; + boost::shared_ptr service_channel; +}; + +TEST_F(HttpServiceTest, UpdateServiceInCacheTest) { + EXPECT_EQ(0, http_server_->UpdateServiceInCache(node)); +} + +TEST_F(HttpServiceTest, GetServListAndCacheSizeTest) { + ServListAndCache list_and_cache; + std::string protocol = "thrift"; + std::string appkey = "octo.naming.service.tmy"; + EXPECT_EQ(0, http_server_->GetServListAndCacheSize(list_and_cache,protocol, appkey)); +} + +TEST_F(HttpServiceTest, RepalceServlistAndCacheTest) { + EXPECT_EQ(0, http_server_->RepalceServlistAndCache(node)); +} + +TEST_F(HttpServiceTest, GetServiceMethodFromHttpTest) { + std::string input = "/api/mns/provider/delete"; + EXPECT_EQ(0, http_server_->GetServiceMethodFromHttp(input.c_str())); + input = ""; + EXPECT_EQ(INVALID_METHOD, http_server_->GetServiceMethodFromHttp(input.c_str())); + input = "/api/monitor"; + EXPECT_EQ(GET_MONITOR_SERVICE, http_server_->GetServiceMethodFromHttp(input.c_str())); + input = "/api/healthy"; + EXPECT_EQ(HEALTHY_CHECK, http_server_->GetServiceMethodFromHttp(input.c_str())); +} + diff --git a/sg_agent/test/naming_idc_check_unittest.cpp b/sg_agent/test/naming_idc_check_unittest.cpp new file mode 100644 index 0000000..c80ea3a --- /dev/null +++ b/sg_agent/test/naming_idc_check_unittest.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include +#include "route_info.h" +#include "route_base.h" +#include "route_rule.h" + +using namespace meituan_mns; +class IdcCheck : public testing::Test { + public: + virtual void SetUp() { + } + virtual void TearDown() { + } + protected: +}; +const char* GetIdcInfo(const std::string &ip) { + boost::shared_ptr idc = IdcUtil::GetIdc(ip); + std::string res = ""; + if (NULL != idc.get()) { + res = idc->GetIdc(); + } + return res.c_str(); +} \ No newline at end of file diff --git a/sg_agent/test/naming_mnsc_service_unittest.cc b/sg_agent/test/naming_mnsc_service_unittest.cc new file mode 100644 index 0000000..e43369e --- /dev/null +++ b/sg_agent/test/naming_mnsc_service_unittest.cc @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include "base_consts.h" +#include "base_mns_consts.h" +#include "base_errors_consts.h" +#include +#include +#define private public +#define protected public +#include "mnsc_client.h" +#undef private +#undef protected + + +using namespace meituan_mns; + +class MnscServiceTest : public testing::Test { + + public: + void SetUp() { + node.__set_appkey("octo.naming.service.tmy"); + node.__set_ip("127.0.0.1"); + node.__set_port(5266); + node.__set_protocol("thrift"); + node.__set_envir(1); + node.__set_version("chrion_test"); + node.__set_fweight(10.0); + node.__set_weight(10); + node.__set_status(2); + mnsc_client_ = MnscClient::GetInstance(); + } + public: + SGService node; + MnscClient *mnsc_client_; + +}; + + +TEST_F(MnscServiceTest,GetThriftServiceListTest) { + std::string appkey = "test"; + std::vector service_list; + EXPECT_EQ(ERR_FAILEDTOGETCONFSERVLIST, mnsc_client_->GetThriftServiceList(appkey, service_list)); + appkey = "octo.naming.service.tmy";//找个节点都是不可用状态的服务 + EXPECT_EQ(ERR_SERVICELIST_NULL, mnsc_client_->GetThriftServiceList(appkey, service_list)); + +} + +TEST_F(MnscServiceTest , GetServicelistFromMnscTest) { + + std::vector serviceList; + std::string appkey = "octo.naming.cos.mtconfig"; + std::string version = ""; + std::string env = "test"; + std::string protocol = "thrift"; + boost::unordered_map count; + GetMnsCacheParams params; + params.appkey = "octo.naming.cos.mtconfig"; + params.version = "octo.naming.cos.mtconfig"; + params.env = "test"; + params.protocol = "thrift"; + + mnsc_client_->GetServicelistFromMnsc(serviceList,params); + std::cout<<"the servicelist size from mnsc "< service_list; + GetMnsCacheParams params; + params.appkey = "octo.naming.service.tmy"; + params.version = "test-verison"; + params.env = "test"; + params.protocol = "thrift"; + EXPECT_EQ(404, mnsc_client_->GetMnscCache(service_list, params)); + params.protocol = "http"; + EXPECT_EQ(200, mnsc_client_->GetMnscCache(service_list, params)); + params.protocol = "test"; + EXPECT_EQ(200, mnsc_client_->GetMnscCache(service_list, params)); +} + diff --git a/sg_agent/test/naming_registry_service_unittest.cc b/sg_agent/test/naming_registry_service_unittest.cc new file mode 100644 index 0000000..816b0e5 --- /dev/null +++ b/sg_agent/test/naming_registry_service_unittest.cc @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include +#include "base_consts.h" +#include "base_mns_consts.h" +#include "base_errors_consts.h" +#include +#include +#define private public +#define protected public +#include "registry_service.h" +#undef private +#undef protected + + +using namespace meituan_mns; + +class RegistryZkTest : public testing::Test { + + public: + void SetUp() { + node.__set_appkey("octo.naming.service.yangjie"); + node.__set_protocol("thrift"); + node.__set_envir(1); + node.__set_version("chrion_test"); + node.__set_fweight(10.0); + node.__set_weight(10); + node.__set_status(2); + + node_a.__set_appkey("octo.naming.service.yangjie"); + node_a.__set_protocol("thrift"); + node_a.__set_envir(1); + node_a.__set_version("chrion_test"); + node_a.__set_fweight(10.0); + node_a.__set_weight(10); + node_a.__set_status(2); + + node_b.__set_appkey("octo.naming.service.yangjie"); + node_b.__set_protocol("thrift"); + node_b.__set_envir(1); + node_b.__set_version("chrion_test"); + node_b.__set_fweight(10.0); + node_b.__set_weight(10); + node_b.__set_status(2); + registry_service_ = RegistryService::GetInstance(); + } + public: + SGService node; + SGService node_a; + SGService node_b; + RegistryService *registry_service_; + +}; + +TEST_F(RegistryZkTest, zkNodeNotExist) { + std::map serviceInfo; + std::map serviceInfo_a; + std::map serviceInfo_b; + int port = 10086; + std::string cell = "test"; + node.__set_ip("127.0.0.1"); + node.__set_port(port); + node_a.__set_ip("127.0.0.1"); + node_a.__set_port(port); + node_b.__set_ip("127.0.0.1"); + node_b.__set_port(port); + std::cout<<"the test registry"<RegistryStart(node, 1)); + EXPECT_EQ(SUCCESS, registry_service_->RegistryStart(node_a, 1)); + EXPECT_EQ(SUCCESS, registry_service_->RegistryStart(node_b, 1)); + +} \ No newline at end of file diff --git a/sg_agent/test/naming_registry_strategy_unittest.cc b/sg_agent/test/naming_registry_strategy_unittest.cc new file mode 100644 index 0000000..4ecd712 --- /dev/null +++ b/sg_agent/test/naming_registry_strategy_unittest.cc @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "config_loader.h" +#include +#include "base_errors_consts.h" +#include "registry_service.h" +#include "base_mns_consts.h" + + +#define private public +#define protected public +#include "../mns/registry_strategy.h" +#undef private +#undef protected + +using namespace meituan_mns; + +class RegistryStrategyTest : public testing::Test { + + public: + void SetUp() { + node.__set_appkey("octo.naming.service.yangjie"); + node.__set_protocol("thrift"); + node.__set_envir(1); + node.__set_version("chrion_test"); + node.__set_fweight(10.0); + node.__set_weight(10); + node.__set_status(2); + + node1.__set_appkey("octo.naming.service.yangjie"); + node1.__set_protocol("thrift"); + node1.__set_envir(1); + node1.__set_version("chrion_test"); + node1.__set_fweight(10.0); + node1.__set_weight(10); + node1.__set_status(2); + register_service_ = RegistryService::GetInstance(); + } + public: + SGService node; + SGService node1; + CXmlFile cxml_file_; + RegistryService *register_service_; + RegistryStrategy register_strategy_; + +}; + +#if 0 +TEST_F(RegistryStrategyTest, zkNodeNotExist) { + +} +//测试加载 +TEST_F(RegistryStrategyTest, registryInfoLoad) { + cxml_file_.CXmlFileInit(); +} +//测试 +TEST_F(RegistryStrategyTest, hotelRegistryTest) { + int port = 10086; + std::string cell = "test"; + node.__set_ip("127.0.0.1); + node.__set_port(port); + std::cout<<"the test registry"<RegistryStart(node, 1)); +} + +TEST_F(RegistryStrategyTest, IsAllowedRegistryTest) { + EXPECT_EQ(0, register_strategy_.IsAllowedRegistry(node)); + node.__set_appkey(""); + EXPECT_EQ(ERR_EMPTY_APPKEY, register_strategy_.IsAllowedRegistry(node)); + node.__set_appkey("octo.naming.travel.dsg.crmtag"); + EXPECT_EQ(-1, register_strategy_.IsAllowedRegistry(node)); + node.__set_appkey("test-benchmark-web");//双框架appkey + EXPECT_EQ(-1, register_strategy_.IsAllowedRegistry(node)); +} + +TEST_F(RegistryStrategyTest, IsRepeatedRegisterTest) { + EXPECT_TRUE(register_strategy_.IsRepeatedRegister(node,node1,UptCmd::ADD)); +} + +TEST_F(RegistryStrategyTest, CheckAllowedProtocolRegistryTest) { + node.__set_protocol("thrift"); + EXPECT_EQ(0, register_strategy_.CheckAllowedProtocolRegistry(node)); + node.__set_protocol("http"); + EXPECT_EQ(0, register_strategy_.CheckAllowedProtocolRegistry(node)); + node.__set_protocol("unknown"); + EXPECT_EQ(-1, register_strategy_.CheckAllowedProtocolRegistry(node)); +} + + +TEST_F(RegistryStrategyTest, CheckArgsTest) { + node._set_appkey(""); + EXPECT_EQ(-1, register_strategy_.CheckArgs(node)); + node.__set_appkey("octo.naming.~.)");//非法字符的appkey + EXPECT_EQ(-1, register_strategy_.CheckArgs(node)); + + +} +TEST_F(RegistryStrategyTest, CheckArgsTest1) { + node.__set_weight(-1); + EXPECT_EQ(ERR_INVALID_WEIGHT, register_strategy_.CheckArgs(node)); +} + +TEST_F(RegistryStrategyTest, CheckArgsTest2) { + node.__set_fweight(-1); + EXPECT_EQ(ERR_INVALID_WEIGHT, register_strategy_.CheckArgs(node)); +} + +TEST_F(RegistryStrategyTest, CheckArgsTest3) { + node.__set_ip("10.4"); + EXPECT_EQ(ERR_INVALID_PORT, register_strategy_.CheckArgs(node)); +} + +TEST_F(RegistryStrategyTest, CheckArgsTest3) { + node.__set_port(-1); + EXPECT_EQ(ERR_INVALID_PORT, register_strategy_.CheckArgs(node)); +} + +TEST_F(RegistryStrategyTest, IsAllowMacRegisterTest) { + CXmlFile::GetAppenv()->SetTypeEnv(Appenv::DEV); + node.__set_appkey("octo.naming.travel.dsg.trace"); + EXPECT_TRUE(register_strategy_.IsAllowMacRegister(node)); + + +} +TEST_F(RegistryStrategyTest, IsAllowMacRegisterTest1) { + CXmlFile::GetAppenv()->SetTypeEnv(Appenv::TEST); + EXPECT_TRUE(register_strategy_.IsAllowMacRegister(node)); + +} + +TEST_F(RegistryStrategyTest, IsAllowMacRegisterTest2) { + CXmlFile::GetAppenv()->SetTypeEnv(Appenv::TEST); + node.__set_appkey("octo.naming.travel.dsg.trace"); + EXPECT_TRUE(register_strategy_.IsAllowMacRegister(node)); +} + +TEST_F(RegistryStrategyTest, RegistryFilterByCacheTest) { + EXPECT_EQ(0, register_strategy_.RegistryFilterByCache(node)); + node.__set_appkey("test-benchmark-web");//双框架appkey + EXPECT_EQ(-1, register_strategy_.RegistryFilterByCache(node)); +} + +TEST_F(RegistryStrategyTest,RegistryFilterCheckTest) { + node.__set_appkey("octo.naming.inf.sg_agent"); + EXPECT_TRUE(register_strategy_.RegistryFilterCheck(node)); + node.__set_appkey("octo.naming.service.yangjie");//开启强制 + EXPECT_TRUE(register_strategy_.RegistryFilterCheck(node)); +} + +TEST_F(RegistryStrategyTest, IsLimitOnZkTest){ + node.__set_appkey("octo.naming.service.yangjie");//开启强制 + EXPECT_TRUE(register_strategy_.IsLimitOnZk(node)); + node.__set_appkey("test"); + EXPECT_FALSE(register_strategy_.IsLimitOnZk(node)); +} + +TEST_F(RegistryStrategyTest, CheckLegalOnOpsTest) { + node.__set_appkey("test"); + EXPECT_FALSE(register_strategy_.CheckLegalOnOps(node)); + node.__set_appkey("octo.naming.service.tmy"); + EXPECT_TRUE(register_strategy_.CheckLegalOnOps(node)); +} +#endif diff --git a/sg_agent/test/naming_version_manager_unittest.cc b/sg_agent/test/naming_version_manager_unittest.cc new file mode 100644 index 0000000..6e322f8 --- /dev/null +++ b/sg_agent/test/naming_version_manager_unittest.cc @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#define private public +#define protected public +#include "version_manager.h" +#undef private +#undef protected + +using namespace meituan_mns; + +class ZKVersionCheck : public testing::Test { + public: + VersionManager version_; +}; + +TEST_F(ZKVersionCheck, CheckZkVersion) { + std::string appkey = "test1"; + std::string zk_version = "1.2"; + std::string version = "2.3"; + + EXPECT_EQ(0, version_.CheckZkVersion(appkey, zk_version, version)); + usleep(100); + EXPECT_EQ(ERR_ZK_LIST_SAME_BUFFER, version_.CheckZkVersion(appkey, zk_version, version)); + +} + +TEST_F(ZKVersionCheck, GetVersionTest) { + const std::string version = "dorado-v1.7.0"; + std::vector test; + version_.GetVersion(version, &test); + EXPECT_EQ(3, test.size()); +} + +TEST_F(ZKVersionCheck, IsOldVersionTest) { + const std::string version = "dorado-v1.7.0"; + EXPECT_FALSE(version_.IsOldVersion(version)); + + const std::string version_2 = "dorado-v1.7.0-SNAPSHOT"; + EXPECT_FALSE(version_.IsOldVersion(version_2)); + + std::string version_3 = "dorado-v1.7.3"; + EXPECT_FALSE(version_.IsOldVersion(version_3)); + + version_3 = "dorado-v1.17.3"; + EXPECT_FALSE(version_.IsOldVersion(version_3)); +} + +TEST_F(ZKVersionCheck, OldVersion) { + std::string version = "dorado-v1.6.4-SNAPSHOT"; + EXPECT_TRUE(version_.IsOldVersion(version)); + + version = "dorado-v1.6.3-SNAPSHOT"; + EXPECT_TRUE(version_.IsOldVersion(version)); + + version = "dorado-v1.5.7"; + EXPECT_TRUE(version_.IsOldVersion(version)); +} + +TEST_F(ZKVersionCheck, dorado) { + EXPECT_TRUE(version_.IsOldVersion("2.7.9")); + EXPECT_TRUE(version_.IsOldVersion("dorado-v2.7.9")); + EXPECT_TRUE(version_.IsOldVersion("1.1.0")); + EXPECT_TRUE(version_.IsOldVersion("dorado-v1.1.0")); + + EXPECT_FALSE(version_.IsOldVersion("2.8.0")); + EXPECT_FALSE(version_.IsOldVersion("dorado-v2.8.0")); + EXPECT_FALSE(version_.IsOldVersion("2.8.1")); + EXPECT_FALSE(version_.IsOldVersion("2.10.0")); + EXPECT_FALSE(version_.IsOldVersion("dorado-v2.8.1")); + EXPECT_FALSE(version_.IsOldVersion("dorado-v2.10.1")); +} + +TEST_F(ZKVersionCheck, other) { + std::string version = "cthrift"; + EXPECT_FALSE(version_.IsOldVersion(version)); + + version = "pthrift"; + EXPECT_FALSE(version_.IsOldVersion(version)); + + version = ""; + EXPECT_TRUE(version_.IsOldVersion(version)); +} diff --git a/sg_agent/test/naming_whitelist_manager_unittest.cc b/sg_agent/test/naming_whitelist_manager_unittest.cc new file mode 100644 index 0000000..ccf0a5a --- /dev/null +++ b/sg_agent/test/naming_whitelist_manager_unittest.cc @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#define private public +#define protected public +#include "whitelist_manager.h" +#undef private +#undef protected + + +using namespace meituan_mns; +class WhiteListManagerTest : public testing::Test { + public: + void SetUp() { + } + public: + WhiteListManager whitelist_manager_; +}; + +TEST_F(WhiteListManagerTest, IsAppkeyInWhitListTest){ + std::string not_appkey = "octo.naming.tmy"; + std::string yes_appkey = "octo.naming.inf.logCollector"; + EXPECT_TRUE(whitelist_manager_.IsAppkeyInWhitList(yes_appkey)); + EXPECT_FALSE(whitelist_manager_.IsAppkeyInWhitList(not_appkey)); +} + +TEST_F(WhiteListManagerTest, IsAppkeyInRegistUnlimitWhitListTest) { + std::string yes_appkey = "octo.naming.inf.sg_agent"; + std::string no_appkey = "octo.naming.test"; + EXPECT_FALSE(whitelist_manager_.IsAppkeyInRegistUnlimitWhitList(no_appkey)); + + EXPECT_TRUE(whitelist_manager_.IsAppkeyInRegistUnlimitWhitList(yes_appkey)); + +} + +TEST_F(WhiteListManagerTest, IsAppkeyInAllEnvWhitListTest) { + std::string yes_appkey = "octo.naming.inf.mafka.castle"; + std::string no_appkey = "octo.naming.test"; + EXPECT_TRUE(whitelist_manager_.IsAppkeyInAllEnvWhitList(yes_appkey)); + EXPECT_FALSE(whitelist_manager_.IsAppkeyInAllEnvWhitList(no_appkey)); +} + + +TEST_F(WhiteListManagerTest, IsMacRegisterAppkeyTest) { + std::string yes_appkey = "octo.naming.flight.basis.linkstar"; + std::string no_appkey = "octo.naming.tmy"; + EXPECT_TRUE(whitelist_manager_.IsMacRegisterAppkey(yes_appkey)); + EXPECT_FALSE(whitelist_manager_.IsMacRegisterAppkey(no_appkey)); +} + +TEST_F(WhiteListManagerTest, IsAppkeyContainsTest) { + std::string appkey = ""; + UnorderedMapPtr set_ptr = boost::make_shared >(); + EXPECT_FALSE(whitelist_manager_.IsAppkeyContains(appkey, set_ptr)); +} + +TEST_F(WhiteListManagerTest, IsAppkeyListTest) { + std::string appkey = ""; + UnorderedMapPtr set_ptr = boost::make_shared >(); + EXPECT_FALSE(whitelist_manager_.IsAppkeyList(appkey, set_ptr)); +} diff --git a/sg_agent/test/naming_zk_client_unittest.cc b/sg_agent/test/naming_zk_client_unittest.cc new file mode 100644 index 0000000..5ded669 --- /dev/null +++ b/sg_agent/test/naming_zk_client_unittest.cc @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#define private public +#define protected public +#include "zk_client.h" +#include "zk_client_pool.h" +#undef private +#undef protected + +using namespace meituan_mns; + +class ZkClientTest : public testing::Test { + public: + void SetUp() { + zk_client_ = new ZkClient(); + zk_client_pool_ = ZkClientPool::GetInstance(); + zk_list = "127.0.0.1:2181"; + zk_timeout = 300000; + zk_retrytimes = 3; + } + public: + ZkClient *zk_client_; + ZkClientPool *zk_client_pool_; + std::string zk_list; + int zk_timeout; + int zk_retrytimes; +}; + +TEST_F(ZkClientTest, ZkInitTest) { + EXPECT_EQ(0, zk_client_->ZkInit(zk_client_, zk_list, zk_timeout, zk_retrytimes)); + EXPECT_EQ(0, zk_client_->ZkClose()); +} + +TEST_F(ZkClientTest, Connect2ZkTest) { + EXPECT_EQ(0, zk_client_->Reconnect2Zk()); + EXPECT_EQ(0, zk_client_->ZkClose()); +} + +TEST_F(ZkClientTest, CheckZkConnTest) { + EXPECT_EQ(0, zk_client_->CheckZkConn()); + EXPECT_EQ(0, zk_client_->ZkClose()); +} + +TEST_F(ZkClientTest, InitTest) { + EXPECT_EQ(-1, zk_client_pool_->Init(zk_list, 0, zk_timeout, zk_retrytimes)); + EXPECT_EQ(-1, zk_client_pool_->Init(zk_list, 1, zk_timeout, zk_retrytimes)); +} + +TEST_F(ZkClientTest, GetZkClientForHashTest) { + ZkClient *zk = zk_client_pool_->GetZkClientForHash(0); + if (zk == NULL) { + EXPECT_EQ(0,-1); + } else { + EXPECT_EQ(0,0); + } + EXPECT_TRUE(zk_client_pool_->started()); +} + diff --git a/sg_agent/test/naming_zk_client_unitttest.cc b/sg_agent/test/naming_zk_client_unitttest.cc new file mode 100644 index 0000000..b71c42a --- /dev/null +++ b/sg_agent/test/naming_zk_client_unitttest.cc @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include "base_consts.h" +#include "base_mns_consts.h" +#include "base_errors_consts.h" +#include +#include +#include "service_channels.h" +#define private public +#define protected public +#include "discovery_zk_client.h" +#undef private +#undef protected +using namespace meituan_mns; + +class DiscZkClientTest : public testing::Test { + public: + void SetUp() { + std::vector service_list; + SGService service1; + service1.__set_ip("127.0.0.1"); + service1.__set_protocol("protocol"); + service1.__set_appkey("octo.naming.service.tmy"); + service1.__set_port(5266); + service1.__set_version("test"); + service1.__set_weight(-1); + service1.__set_fweight(101); + service_list.push_back(service1); + node = boost::make_shared(); + node->__set_localAppkey(""); + node->__set_remoteAppkey("octo.naming.service.tmy"); + node->__set_serviceList(service_list); + node->__set_protocol("thrift"); + discovery_service_ = DiscoveryZkClient::GetInstance(); + + req.protocol = "thrift"; + req.remoteAppkey = "octo.naming.service.tmy"; + req.serviceName = "http://mns.octo.com"; + service_channel = boost::make_shared(); + service_channel->SetAllChannel(false); + service_channel->SetBankboneChannel(false); + service_channel->SetOriginChannel(false); + service_channel->SetSwimlaneChannel(false); + } + public: + boost::shared_ptr node; + DiscoveryZkClient *discovery_service_; + ProtocolRequest req; + boost::shared_ptr service_channel; +}; + + +TEST_F(DiscZkClientTest, DiscSrvListByProtocolTest) { + EXPECT_EQ(0, discovery_service_->DiscSrvListByProtocol(node)); + node->__set_remoteAppkey("octo.naming.service.mtconfig"); + EXPECT_EQ(0, discovery_service_->DiscSrvListByProtocol(node)); + node->__set_remoteAppkey("test"); + EXPECT_EQ(-101, discovery_service_->DiscSrvListByProtocol(node)); +} + +TEST_F(DiscZkClientTest, DiscRouteListByProtocolTest) { + std::vector routeList; + std::string localAppkey = "test"; + std::string appKey = "octo.naming.service.tmy"; + std::string version = ""; + std::string protocol = "thrift"; + bool route_flag = false; + EXPECT_EQ(0, discovery_service_->DiscRouteListByProtocol(routeList, + localAppkey,appKey, version,protocol, route_flag)); + EXPECT_EQ(ERR_ZK_LIST_SAME_BUFFER, discovery_service_->DiscRouteListByProtocol(routeList, + localAppkey,appKey, version,protocol, route_flag)); + appKey = "test"; + EXPECT_EQ(ERR_NODE_NOTFIND,discovery_service_->DiscRouteListByProtocol(routeList, + localAppkey,appKey, version,protocol, route_flag)); +} + +TEST_F(DiscZkClientTest, DiscAppkeyByServiceNameTest) { + std::set appkeys; + std::string local_appkey = "test"; + std::string service_name = "http://mns.octo.com"; + std::string version = "0"; + std::string protocol = "thrift"; + EXPECT_EQ(0, discovery_service_->DiscAppkeyByServiceName(appkeys, + local_appkey,service_name,version, protocol)); + service_name = "test"; + EXPECT_EQ(ERR_NODE_NOTFIND, discovery_service_->DiscAppkeyByServiceName(appkeys, + local_appkey,service_name,version, protocol)); +} + +TEST_F(DiscZkClientTest, DiscoveryListFromCacheTest) { + std::vector srvlist; + GetMnsCacheParams params; + params.appkey = "octo.naming.service.mtconfig"; + params.version = "octo.naming.service.mtconfig"; + params.env = "test"; + params.protocol = "thrift"; + //EXPECT_EQ(0, discovery_service_-> + // DiscoveryListFromCache(srvlist, params)) ; //todo for private + +} + +TEST_F(DiscZkClientTest, DivRangeDiscIndexTest) { + int index = 1; + int begin = 0; + int end = 3; + int child_count = 5; + discovery_service_->DivRangeDiscIndex(index, begin, end, child_count); +} diff --git a/sg_agent/test/naming_zk_path_tools_unittest.cc b/sg_agent/test/naming_zk_path_tools_unittest.cc new file mode 100644 index 0000000..169b948 --- /dev/null +++ b/sg_agent/test/naming_zk_path_tools_unittest.cc @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#define private public +#define protected public +#include "zk_path_tools.h" +#undef private +#undef protected + +using namespace meituan_mns; +class AgentZkPathTest : public testing::Test { + public: + void SetUp() { + m_root_path = "/octo/naming/test"; + appkey = "octo.naming.inf.tmy"; + + provider = m_root_path + "/" + appkey + "/provider"; + http = m_root_path + "/" + appkey + "/provider-http"; + tair = m_root_path + "/" + appkey + "/providers/tair"; + other = m_root_path + "/" + appkey + "/providers/other"; + remoteAppkey_ = "octo.naming.inf.logCollector"; + } + public: + AgentZkPath agent_zk_path_; + std::string m_root_path; + std::string appkey; + + std::string provider; + std::string http; + std::string tair; + std::string other; + std::string remoteAppkey_; +}; + + +TEST_F(AgentZkPathTest, GenProtocolZkPathTest) { + std::string zk_path = ""; + std::string nodeType = "provider"; + std::string appkey = "octo.naming.inf.tmy"; + EXPECT_EQ(0, agent_zk_path_.GenProtocolZkPath(zk_path, appkey, "thrift", + nodeType)); + appkey = ""; + EXPECT_EQ(-1, agent_zk_path_.GenProtocolZkPath(zk_path, appkey, "thrift", + nodeType)); + EXPECT_EQ(-1, agent_zk_path_.GenProtocolZkPath(zk_path, appkey, "", nodeType)); +} + +TEST_F(AgentZkPathTest, GenDescZkPathTest) { + std::string zk_path = ""; + std::string castle_appkey("octo.naming.inf.dorado.heartbeat"); + int ret = + agent_zk_path_.GenDescZkPath(zk_path, castle_appkey); + EXPECT_EQ(SUCCESS, ret); + + std::string zk_path_str(zk_path); + + EXPECT_FALSE(zk_path_str == "/octo/naming/test/octo.naming.inf.dorado.heartbeat" + "/desc"); + + std::string octo_tmy_appkey("octo.naming.octo.tmy"); + ret = agent_zk_path_.GenDescZkPath(zk_path, octo_tmy_appkey); + EXPECT_EQ(SUCCESS, ret); + + std::string zk_path_str1(zk_path); + EXPECT_TRUE(zk_path_str1 == "/octo/naming/prod/octo.naming.octo.tmy/desc"); +} + +TEST_F(AgentZkPathTest, GenServiceNameZkPathNodeTest) { + std::string zk_path = ""; + std::string castle_appkey("octo.naming.inf.dorado.heartbeat"); + std::string servicename("test_service_name"); + std::string protocol("thrift"); + int ret = + agent_zk_path_.GenServiceNameZkPathNode(zk_path, servicename, protocol, + castle_appkey); + EXPECT_EQ(SUCCESS, ret); + + std::string zk_path_str(zk_path); + + EXPECT_TRUE(zk_path_str == "/mns/service/prod/test_service_name/thrift"); + + std::string octo_tmy_appkey("octo.naming.octo.tmy"); + ret = agent_zk_path_.GenServiceNameZkPathNode(zk_path, servicename, protocol, + octo_tmy_appkey); + EXPECT_EQ(SUCCESS, ret); + + std::string zk_path_str1(zk_path); + std::cout << zk_path_str1 << std::endl; + EXPECT_TRUE(zk_path_str1 == "/mns/service/prod/test_service_name/thrift"); +} + + +TEST_F(AgentZkPathTest, GenRegisterZkPathTest) { + std::string zk_path = ""; + std::string castle_appkey("octo.naming.inf.dorado.heartbeat"); + std::string protocol("thrift"); + int server_type = 1; + int ret = + agent_zk_path_.GenRegisterZkPath(zk_path, castle_appkey, protocol, + server_type); + EXPECT_EQ(SUCCESS, ret); + + std::string zk_path_str(zk_path); + + EXPECT_FALSE(zk_path_str == "/octo/naming/prod/octo.naming.inf.dorado.heartbeat" + "/provider"); + + std::string octo_tmy_appkey("octo.naming.octo.tmy"); + ret = agent_zk_path_.GenRegisterZkPath(zk_path, octo_tmy_appkey, protocol, + server_type); + EXPECT_EQ(SUCCESS, ret); + + std::string zk_path_str1(zk_path); + EXPECT_TRUE(zk_path_str1 == "/octo/naming/prod/octo.naming.octo.tmy/provider"); +} + +TEST_F(AgentZkPathTest, GenProtocolZkPathTest1) { + std::string zk_path = ""; + std::string castle_appkey("octo.naming.inf.dorado.heartbeat"); + std::string protocol("thrift"); + std::string provider("provider"); + int ret = + agent_zk_path_.GenProtocolZkPath(zk_path, castle_appkey, protocol, + provider); + EXPECT_EQ(SUCCESS, ret); + + std::string zk_path_str(zk_path); + + EXPECT_FALSE(zk_path_str == "/octo/naming/prod/octo.naming.inf.dorado." + "heartbeat/provider"); + + std::string octo_tmy_appkey("octo.naming.octo.tmy"); + ret = agent_zk_path_.GenProtocolZkPath(zk_path, octo_tmy_appkey, protocol, + provider); + EXPECT_EQ(SUCCESS, ret); + + std::string zk_path_str1(zk_path); + EXPECT_TRUE(zk_path_str1 == "/octo/naming/prod/octo.naming.octo.tmy/provider"); +} + +TEST_F(AgentZkPathTest, GenRegisterZkPathTest1) { + std::string zk_path = ""; + EXPECT_LE(0, agent_zk_path_.GenRegisterZkPath(zk_path, appkey, "thrift", 0)); + zk_path = ""; + EXPECT_LE(0, agent_zk_path_.GenRegisterZkPath(zk_path, appkey, "", 0)); + + + //验证serverType无关 + EXPECT_LE(0, agent_zk_path_.GenRegisterZkPath(zk_path, appkey, "thrift", 1)); + + //验证serverType无关 + + EXPECT_LE(0, agent_zk_path_.GenRegisterZkPath(zk_path, appkey, "http", 0)); + //EXPECT_STREQ(http.c_str(), zkPath); + + + EXPECT_LE(0, agent_zk_path_.GenRegisterZkPath(zk_path, appkey, "http", 1)); + //EXPECT_STREQ(http.c_str(), zkPath_2); + + EXPECT_LE(0, agent_zk_path_.GenRegisterZkPath(zk_path, appkey, "", 1)); + + EXPECT_LE(0, agent_zk_path_.GenRegisterZkPath(zk_path, appkey, "tair", 0)); + + EXPECT_LE(0, agent_zk_path_.GenRegisterZkPath(zk_path, appkey, "tair", 1)); +} + + +TEST_F(AgentZkPathTest, GenServiceNameZkPathNodeTest1) { + std::string zk_path = ""; + std::string appkey = "octo.naming.inf.sg_agent"; + std::string serviceName = "sayHello"; + + EXPECT_LE(0, agent_zk_path_.GenServiceNameZkPathNode(zk_path, serviceName, + "thrift",appkey)); + std::cout << "zkPath = " << zk_path << std::endl; + EXPECT_STREQ(zk_path.c_str(), "/mns/service/prod/sayHello/thrift"); + + EXPECT_LE(0, agent_zk_path_.GenServiceNameZkPathNode(zk_path, serviceName, + "http", appkey)); + EXPECT_STREQ(zk_path.c_str(), "/mns/service/prod/sayHello/http"); + + + appkey = "octo.naming.inf.sg_agent"; + serviceName = "sayHello"; + + EXPECT_LE(0, agent_zk_path_.GenServiceNameZkPathNode(zk_path, + serviceName, + appkey)); + std::cout << "zkPath = " << zk_path << std::endl; + EXPECT_STREQ(zk_path.c_str(), "/mns/service/prod/sayHello"); + + EXPECT_LE(0, agent_zk_path_.GenServiceNameZkPathNode(zk_path, + serviceName, + appkey)); + EXPECT_STREQ(zk_path.c_str(), "/mns/service/prod/sayHello"); +} + +TEST_F(AgentZkPathTest, parse_xml) { + std::string char_with_empty = " "; + boost::trim(char_with_empty); + EXPECT_TRUE("" == char_with_empty); + std::string char_with_empty1 = " s "; + boost::trim(char_with_empty1); + EXPECT_TRUE("s" == char_with_empty1); +} + +TEST_F(AgentZkPathTest, thrift_provider) { + std::string zk_path = "/octo/naming/prod/octo.naming.inf.logCollector/provider"; + std::string appkey = ""; + std::string protocol = ""; + EXPECT_EQ(0, AgentZkPath::DeGenZkPath(zk_path.c_str(), appkey, protocol)); + + EXPECT_STREQ(appkey.c_str(), appkey.c_str()); + EXPECT_STREQ("thrift", protocol.c_str()); +} + +TEST_F(AgentZkPathTest, http_provider) { + std::string zk_path = "/octo/naming/prod/octo.naming.inf.logCollector/" + "provider-http"; + std::string appkey = ""; + std::string protocol = ""; + EXPECT_EQ(0, AgentZkPath::DeGenZkPath(zk_path.c_str(), appkey, protocol)); + + EXPECT_STREQ(remoteAppkey_.c_str(), appkey.c_str()); + EXPECT_STREQ("http", protocol.c_str()); +} + +TEST_F(AgentZkPathTest, cellar_provider) { + std::string zk_path = "/octo/naming/prod/octo.naming.inf.logCollector/" + "providers" + "/cellar"; + std::string appkey = ""; + std::string protocol = ""; + EXPECT_EQ(0, AgentZkPath::DeGenZkPath(zk_path.c_str(), appkey, protocol)); + + EXPECT_STREQ(remoteAppkey_.c_str(), appkey.c_str()); + EXPECT_STREQ("cellar", protocol.c_str()); +} + +TEST_F(AgentZkPathTest, thrift_route) { + std::string zk_path = "/octo/naming/prod/octo.naming.inf.logCollector/route"; + std::string appkey = ""; + std::string protocol = ""; + EXPECT_EQ(0, AgentZkPath::DeGenZkPath(zk_path.c_str(), appkey, protocol)); + + EXPECT_STREQ(remoteAppkey_.c_str(), appkey.c_str()); + EXPECT_STREQ("thrift", protocol.c_str()); +} + +TEST_F(AgentZkPathTest, http_route) { + std::string zk_path = "/octo/naming/prod/octo.naming.inf.logCollector" + "/route-http"; + std::string appkey = ""; + std::string protocol = ""; + EXPECT_EQ(0, AgentZkPath::DeGenZkPath(zk_path.c_str(), appkey, protocol)); + + EXPECT_STREQ(remoteAppkey_.c_str(), appkey.c_str()); + EXPECT_STREQ("http", protocol.c_str()); +} + +TEST_F(AgentZkPathTest, cellar_route) { + std::string zk_path = "/octo/naming/prod/octo.naming.inf.logCollector" + "/providers/cellar"; + std::string appkey = ""; + std::string protocol = ""; + EXPECT_EQ(0, AgentZkPath::DeGenZkPath(zk_path.c_str(), appkey, protocol)); + + EXPECT_STREQ(remoteAppkey_.c_str(), appkey.c_str()); + EXPECT_STREQ("cellar", protocol.c_str()); +} + +TEST_F(AgentZkPathTest, invalid_path) { + std::string appkey = ""; + std::string protocol = ""; + //empty + std::string zk_path= ""; + EXPECT_EQ(-1, AgentZkPath::DeGenZkPath(zk_path.c_str(), appkey, protocol)); + + //not complete + zk_path = "/octo/naming/prod"; + EXPECT_EQ(-2, AgentZkPath::DeGenZkPath(zk_path.c_str(), appkey, protocol)); + + zk_path = "/octo/naming/prod////"; + EXPECT_EQ(-3, AgentZkPath::DeGenZkPath(zk_path.c_str(), appkey, protocol)); +} + + diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/Echo.h b/sg_agent/thrid_party/cthrift/include/cthrift/Echo.h new file mode 100644 index 0000000..f84d819 --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/Echo.h @@ -0,0 +1,368 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef Echo_H +#define Echo_H + +#include +#include +namespace apache { namespace thrift { namespace async { +class TAsyncChannel; +}}} +#include +#include +#include "echo_types.h" + +namespace echo { + +class EchoIf { + public: + virtual ~EchoIf() {} + virtual void echo(std::string& _return, const std::string& arg, const test& arg2) = 0; +}; + +class EchoIfFactory { + public: + typedef EchoIf Handler; + + virtual ~EchoIfFactory() {} + + virtual EchoIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo) = 0; + virtual void releaseHandler(EchoIf* /* handler */) = 0; +}; + +class EchoIfSingletonFactory : virtual public EchoIfFactory { + public: + EchoIfSingletonFactory(const boost::shared_ptr& iface) : iface_(iface) {} + virtual ~EchoIfSingletonFactory() {} + + virtual EchoIf* getHandler(const ::apache::thrift::TConnectionInfo&) { + return iface_.get(); + } + virtual void releaseHandler(EchoIf* /* handler */) {} + + protected: + boost::shared_ptr iface_; +}; + +class EchoNull : virtual public EchoIf { + public: + virtual ~EchoNull() {} + void echo(std::string& /* _return */, const std::string& /* arg */, const test& /* arg2 */) { + return; + } +}; + +typedef struct _Echo_echo_args__isset { + _Echo_echo_args__isset() : arg(false), arg2(false) {} + bool arg; + bool arg2; +} _Echo_echo_args__isset; + +class Echo_echo_args { + public: + + Echo_echo_args() : arg("") { + } + + virtual ~Echo_echo_args() throw() {} + + std::string arg; + test arg2; + + _Echo_echo_args__isset __isset; + + void __set_arg(const std::string& val) { + arg = val; + } + + void __set_arg2(const test& val) { + arg2 = val; + } + + bool operator == (const Echo_echo_args & rhs) const + { + if (!(arg == rhs.arg)) + return false; + if (!(arg2 == rhs.arg2)) + return false; + return true; + } + bool operator != (const Echo_echo_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const Echo_echo_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class Echo_echo_pargs { + public: + + + virtual ~Echo_echo_pargs() throw() {} + + const std::string* arg; + const test* arg2; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _Echo_echo_result__isset { + _Echo_echo_result__isset() : success(false) {} + bool success; +} _Echo_echo_result__isset; + +class Echo_echo_result { + public: + + Echo_echo_result() : success("") { + } + + virtual ~Echo_echo_result() throw() {} + + std::string success; + + _Echo_echo_result__isset __isset; + + void __set_success(const std::string& val) { + success = val; + } + + bool operator == (const Echo_echo_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const Echo_echo_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const Echo_echo_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _Echo_echo_presult__isset { + _Echo_echo_presult__isset() : success(false) {} + bool success; +} _Echo_echo_presult__isset; + +class Echo_echo_presult { + public: + + + virtual ~Echo_echo_presult() throw() {} + + std::string* success; + + _Echo_echo_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +class EchoClient : virtual public EchoIf { + public: + EchoClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> prot) : + piprot_(prot), + poprot_(prot) { + iprot_ = prot.get(); + oprot_ = prot.get(); + } + EchoClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> iprot, boost::shared_ptr< ::apache::thrift::protocol::TProtocol> oprot) : + piprot_(iprot), + poprot_(oprot) { + iprot_ = iprot.get(); + oprot_ = oprot.get(); + } + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol() { + return piprot_; + } + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol() { + return poprot_; + } + void echo(std::string& _return, const std::string& arg, const test& arg2); + void send_echo(const std::string& arg, const test& arg2); + void recv_echo(std::string& _return); + protected: + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> piprot_; + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> poprot_; + ::apache::thrift::protocol::TProtocol* iprot_; + ::apache::thrift::protocol::TProtocol* oprot_; +}; + +class EchoProcessor : public ::apache::thrift::TProcessor { + protected: + boost::shared_ptr iface_; + virtual bool process_fn(apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, std::string& fname, int32_t seqid, void* callContext); + private: + std::map processMap_; + void process_echo(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + public: + EchoProcessor(boost::shared_ptr iface) : + iface_(iface) { + processMap_["echo"] = &EchoProcessor::process_echo; + } + + virtual bool process(boost::shared_ptr piprot, boost::shared_ptr poprot, void* callContext); + virtual ~EchoProcessor() {} +}; + +class EchoProcessorFactory : public ::apache::thrift::TProcessorFactory { + public: + EchoProcessorFactory(const ::boost::shared_ptr< EchoIfFactory >& handlerFactory) : + handlerFactory_(handlerFactory) {} + + ::boost::shared_ptr< ::apache::thrift::TProcessor > getProcessor(const ::apache::thrift::TConnectionInfo& connInfo); + + protected: + ::boost::shared_ptr< EchoIfFactory > handlerFactory_; +}; + +class EchoMultiface : virtual public EchoIf { + public: + EchoMultiface(std::vector >& ifaces) : ifaces_(ifaces) { + } + virtual ~EchoMultiface() {} + protected: + std::vector > ifaces_; + EchoMultiface() {} + void add(boost::shared_ptr iface) { + ifaces_.push_back(iface); + } + public: + void echo(std::string& _return, const std::string& arg, const test& arg2) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->echo(_return, arg, arg2); + return; + } else { + ifaces_[i]->echo(_return, arg, arg2); + } + } + } + +}; + +class EchoCobClient; + +class EchoCobClIf { + public: + virtual ~EchoCobClIf() {} + virtual void echo(std::tr1::function cob, const std::string& arg, const test& arg2) = 0; +}; + +class EchoCobSvIf { + public: + virtual ~EchoCobSvIf() {} + virtual void echo(std::tr1::function cob, const std::string& arg, const test& arg2) = 0; +}; + +class EchoCobSvIfFactory { + public: + typedef EchoCobSvIf Handler; + + virtual ~EchoCobSvIfFactory() {} + + virtual EchoCobSvIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo) = 0; + virtual void releaseHandler(EchoCobSvIf* /* handler */) = 0; +}; + +class EchoCobSvIfSingletonFactory : virtual public EchoCobSvIfFactory { + public: + EchoCobSvIfSingletonFactory(const boost::shared_ptr& iface) : iface_(iface) {} + virtual ~EchoCobSvIfSingletonFactory() {} + + virtual EchoCobSvIf* getHandler(const ::apache::thrift::TConnectionInfo&) { + return iface_.get(); + } + virtual void releaseHandler(EchoCobSvIf* /* handler */) {} + + protected: + boost::shared_ptr iface_; +}; + +class EchoCobSvNull : virtual public EchoCobSvIf { + public: + virtual ~EchoCobSvNull() {} + void echo(std::tr1::function cob, const std::string& /* arg */, const test& /* arg2 */) { + std::string _return = ""; + return cob(_return); + } +}; + +class EchoCobClient : virtual public EchoCobClIf { + public: + EchoCobClient(boost::shared_ptr< ::apache::thrift::async::TAsyncChannel> channel, ::apache::thrift::protocol::TProtocolFactory* protocolFactory) : + channel_(channel), + itrans_(new ::apache::thrift::transport::TMemoryBuffer()), + otrans_(new ::apache::thrift::transport::TMemoryBuffer()), + piprot_(protocolFactory->getProtocol(itrans_)), + poprot_(protocolFactory->getProtocol(otrans_)) { + iprot_ = piprot_.get(); + oprot_ = poprot_.get(); + } + boost::shared_ptr< ::apache::thrift::async::TAsyncChannel> getChannel() { + return channel_; + } + virtual void completed__(bool /* success */) {} + void echo(std::tr1::function cob, const std::string& arg, const test& arg2); + void send_echo(const std::string& arg, const test& arg2); + void recv_echo(std::string& _return); + protected: + boost::shared_ptr< ::apache::thrift::async::TAsyncChannel> channel_; + boost::shared_ptr< ::apache::thrift::transport::TMemoryBuffer> itrans_; + boost::shared_ptr< ::apache::thrift::transport::TMemoryBuffer> otrans_; + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> piprot_; + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> poprot_; + ::apache::thrift::protocol::TProtocol* iprot_; + ::apache::thrift::protocol::TProtocol* oprot_; +}; + +class EchoAsyncProcessor : public ::apache::thrift::TAsyncProcessor { + protected: + boost::shared_ptr iface_; + virtual void process_fn(std::tr1::function cob, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, std::string& fname, int32_t seqid); + private: + std::map, int32_t, apache::thrift::protocol::TProtocol*, apache::thrift::protocol::TProtocol*)> processMap_; + void process_echo(std::tr1::function cob, int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot); + void return_echo(std::tr1::function cob, int32_t seqid, ::apache::thrift::protocol::TProtocol* oprot, void* ctx, const std::string& _return); + void throw_echo(std::tr1::function cob, int32_t seqid, apache::thrift::protocol::TProtocol* oprot, void* ctx, apache::thrift::TDelayedException* _throw); + public: + EchoAsyncProcessor(boost::shared_ptr iface) : + iface_(iface) { + processMap_["echo"] = &EchoAsyncProcessor::process_echo; + } + + virtual void process(std::tr1::function cob, boost::shared_ptr piprot, boost::shared_ptr poprot); + virtual ~EchoAsyncProcessor() {} +}; + +class EchoAsyncProcessorFactory : public ::apache::thrift::async::TAsyncProcessorFactory { + public: + EchoAsyncProcessorFactory(const ::boost::shared_ptr< EchoCobSvIfFactory >& handlerFactory) : + handlerFactory_(handlerFactory) {} + + ::boost::shared_ptr< ::apache::thrift::async::TAsyncProcessor > getProcessor(const ::apache::thrift::TConnectionInfo& connInfo); + + protected: + ::boost::shared_ptr< EchoCobSvIfFactory > handlerFactory_; +}; + +} // namespace + +#endif diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_async_callback.h b/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_async_callback.h new file mode 100644 index 0000000..b7ea23a --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_async_callback.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef CTHRIFT_SRC_CTHRIFT_ASYNC_CALLBACK_H_ +#define CTHRIFT_SRC_CTHRIFT_ASYNC_CALLBACK_H_ + +#include "cthrift/util/cthrift_common.h" + +namespace meituan_cthrift { + +template +class AsyncCallback { + public: + // typedef void (*AsyncCobType) (CobClient *client); + typedef boost::function AsyncCobType; + + AsyncCallback() : cob_success_(boost::bind(&Default, _1)), + cob_timeout_(boost::bind(&Default, _1)), + cob_highwater_(boost::bind(&Default, _1)) { + } + + ~AsyncCallback() { + } + + static void Default(CobClient *client) { + CTHRIFT_LOG_DEBUG("Default callback function"); + } + + void Callback(CobClient *client) { + AsyncState async_task_state = boost::any_cast( + (muduo::net::EventLoop::getEventLoopOfCurrentThread()) + ->getContext()); + switch (async_task_state) { + case kTaskStateSuccess : CTHRIFT_LOG_DEBUG("Call Success cob_: "); + cob_success_(client); + break; + case kTaskStateTimeOut : CTHRIFT_LOG_DEBUG("Call Timeout cob_: "); + cob_timeout_(client); + break; + case kTaskStateTooMany : CTHRIFT_LOG_DEBUG("Call HighWater cob_: "); + cob_highwater_(client); + break; + default: CTHRIFT_LOG_ERROR("Invalid callback type"); + } + } + + void Success(const AsyncCobType &cob) { + cob_success_ = cob; + } + void Timeout(const AsyncCobType &cob) { + cob_timeout_ = cob; + } + void HighWater(const AsyncCobType &cob) { + cob_highwater_ = cob; + } + + private: + AsyncCobType cob_success_; + AsyncCobType cob_timeout_; + AsyncCobType cob_highwater_; +}; +} // namespace meituan_cthrift + +#endif // CTHRIFT_SRC_CTHRIFT_ASYNC_CALLBACK_H_ diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_client.h b/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_client.h new file mode 100644 index 0000000..9261794 --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_client.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef CTHRIFT_SRC_CTHRIFT_CTHRIFT_CLIENT_H_ +#define CTHRIFT_SRC_CTHRIFT_CTHRIFT_CLIENT_H_ + +#include "cthrift/util/cthrift_common.h" +#include "cthrift_tbinary_protocol.h" +#include "cthrift_transport.h" + +namespace meituan_cthrift { +using namespace apache::thrift; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; + +class CthriftClient { + private: + static const int32_t kI32DefaultTimeoutMsForClient; + + std::string str_svr_appkey_; + std::string str_cli_appkey_; + int32_t i32_timeout_ms_; // TODO(specify timeout differ by interface) + std::string str_serviceName_filter_; + int32_t i32_port_filter_; + bool b_parallel_; + int32_t i32_async_pending_threshold_; + bool b_async_; + + std::string str_server_ip_; + int16_t i16_server_port_; + unsigned int i32_worker_num_; + + boost::shared_ptr sp_cthrift_client_worker_; + + static muduo::MutexLock work_resource_lock_; + typedef boost::weak_ptr WorkerWeakPtr; + static boost::unordered_multimap map_appkey_worker_; + + int InitWorker(bool async); + + public: + CthriftClient(const std::string &str_ip, + const int16_t &i16_port, + const int32_t &i32_timeout_ms); + + CthriftClient(const std::string &str_svr_appkey, + const int32_t &i32_timeout); + + ~CthriftClient(void) { + // 可以正常释放资源 + // delete will cause memory issue, cthriftclient should keepalive during + // thread life-time, so two pointers leak acceptable + + /*if (CTHRIFT_LIKELY(p_sp_cthrift_tbinary_protocol_)) { + delete p_sp_cthrift_tbinary_protocol_; + } + + if (CTHRIFT_LIKELY(p_sp_cthrift_transport_)) { + delete p_sp_cthrift_transport_; + }*/ + } + + boost::shared_ptr GetCthriftProtocol(void); + + int SetClientAppkey(const std::string &str_appkey); + + int SetFilterPort(const unsigned int &i32_port); + + int SetFilterService(const std::string &str_serviceName); + + inline void SetParallel(const bool &b_par) { + b_parallel_ = b_par; + } + + inline void SetThreshold(const int &threshold) { + i32_async_pending_threshold_ = threshold; + } + + inline void SetAsync(const bool &b_async) { + b_async_ = b_async; + } + + inline void SetWorkerNumber(const unsigned int &num) { + i32_worker_num_ = num; + } + + inline int32_t GetThreshold() const { + return i32_async_pending_threshold_; + } + + int Init(void); + + int32_t GetTimeout() const { + return i32_timeout_ms_; + } + + boost::shared_ptr GetClientWorker() { + return sp_cthrift_client_worker_; + } + + std::string GetEnvInfo(void) const { + return meituan_cthrift::CthriftNameService::str_env_; + } +}; + +} // namespace meituan_cthrift + +#endif // CTHRIFT_SRC_CTHRIFT_CTHRIFT_CLIENT_H_ diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_client_channel.h b/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_client_channel.h new file mode 100644 index 0000000..1263e28 --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_client_channel.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +#ifndef CTHRIFT_SRC_CTHRIFT_CTHRIFT_ASYNC_CALLBACK_H_ +#define CTHRIFT_SRC_CTHRIFT_CTHRIFT_ASYNC_CALLBACK_H_ + +#include +#include "cthrift_client.h" +#include "cthrift/util/cthrift_common.h" + +namespace apache { +namespace thrift { +namespace transport { +class TMemoryBuffer; +} +} +} + +namespace meituan_cthrift { +class CthriftClientChannel : public apache::thrift::async::TAsyncChannel { + public: + using apache::thrift::async::TAsyncChannel::VoidCallback; + + explicit CthriftClientChannel(boost::shared_ptr sp_cthrift_cli); + ~CthriftClientChannel(); + + virtual void sendAndRecvMessage( + const VoidCallback &cob, + apache::thrift::transport::TMemoryBuffer *sendBuf, + apache::thrift::transport::TMemoryBuffer *recvBuf); + + virtual void sendMessage(const VoidCallback &cob, + apache::thrift::transport::TMemoryBuffer *message); + virtual void recvMessage(const VoidCallback &cob, + apache::thrift::transport::TMemoryBuffer *message); + + virtual bool good() const; + virtual bool error() const; + virtual bool timedOut() const; + + private: + boost::shared_ptr sp_cthrift_client_; + boost::shared_ptr sp_cthrift_client_worker_; + + // 没有实际作用,只是为了复用SharedContSharedPtr结构体 + muduo::MutexLock mutexlock_conn_ready; + muduo::Condition cond_ready_read; + + boost::shared_ptr sp_mutexlock_read_buf; + TMemBufSharedPtr sp_write_buf; + boost::shared_ptr sp_mutexlock_write_buf; + TMemBufSharedPtr sp_read_buf; +}; +} // namespace meituan_cthrift + +#endif // CTHRIFT_SRC_CTHRIFT_CTHRIFT_CLIENT_CHANNEL_H_ diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_client_worker.h b/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_client_worker.h new file mode 100644 index 0000000..3a230e8 --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_client_worker.h @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef CTHRIFT_SRC_CTHRIFT_CTHRIFT_CLIENT_WORKER_H_ +#define CTHRIFT_SRC_CTHRIFT_CTHRIFT_CLIENT_WORKER_H_ + +#include "cthrift/util/cthrift_common.h" +#include "cthrift_name_service.h" +#include "cthrift_client.h" +#include "cthrift_transport.h" + +namespace meituan_cthrift { +using namespace apache::thrift; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; + +struct WeightSort { + bool operator()(const double &a, const double &b) const { + return a > b; + } +}; + +class ConnInfo { + private: + meituan_mns::SGService sgservice_; + TcpClientSharedPtr sp_tcpclient_; + + std::multimap *p_map_weight_tcpclientwp_; + +// for relate to weight index, if not be deleted, safe + std::multimap::iterator + it_map_weight_tcpclientwp_index_; + + public: + ConnInfo(const meituan_mns::SGService &sgservice_tmp, + std::multimap * + p_map_weight_tcpclientwp) : sgservice_(sgservice_tmp), + p_map_weight_tcpclientwp_( + p_map_weight_tcpclientwp) {} + + ~ConnInfo(void) { + if (CTHRIFT_UNLIKELY(!p_map_weight_tcpclientwp_)) { + CTHRIFT_LOG_ERROR("p_map_weight_tcpclientwp_ NULL"); + } else { + CTHRIFT_LOG_INFO("delete appkey " << sgservice_.appkey << " ip: " + << sgservice_.ip << " port: " + << sgservice_.port + << " from weight pool"); + p_map_weight_tcpclientwp_->erase(it_map_weight_tcpclientwp_index_); + } + } + + const meituan_mns::SGService &GetSgservice(void) const { + return sgservice_; + } + + bool CheckConnHealthy(void) const; + + void UptSgservice(const meituan_mns::SGService &sgservice); + + void setSp_tcpclient_(const TcpClientSharedPtr &sp_tcpclient); + + TcpClientSharedPtr &getSp_tcpclient_() { + return sp_tcpclient_; + } + + /* + int8_t FetchTcpConnSP(muduo::net::TcpConnectionPtr *p_tcpconn_sp) { + if (sp_tcpclient_.get() && sp_tcpclient_->connection()) { + p_tcpconn_sp->reset((sp_tcpclient_->connection()).get()); + return 0; + } + + CTHRIFT_LOG_INFO << "sp_tcpclient_ NOT init"; + return -1; + } + */ +}; + +typedef boost::shared_ptr ConnInfoSharedPtr; +typedef boost::weak_ptr ConnInfoWeakPtr; + +struct ConnContext4Worker { + public: + State enum_state; + int32_t i32_want_size; + + /* + time_t t_last_conn_time_; + time_t t_last_recv_time_; + time_t t_last_send_time_; + */ + bool b_highwater; + bool b_occupied; + + ConnInfoWeakPtr wp_conn_info; + // std::queue queue_send; + + explicit ConnContext4Worker(const ConnInfoSharedPtr &sp_conn_info) + : enum_state(kExpectFrameSize), i32_want_size(0), b_highwater(false), + b_occupied(false), wp_conn_info(sp_conn_info) {} +}; + +typedef boost::shared_ptr Context4WorkerSharedPtr; + +class CthriftClientWorker { + private: + struct CnxtEntry : public muduo::copyable { + WeakContSharedPtr wp_cnxt_; + CthriftClientWorker *p_worker_; + + explicit CnxtEntry(const WeakContSharedPtr &wp_cnxt, + CthriftClientWorker *parent) + : wp_cnxt_(wp_cnxt), p_worker_(parent) {} + + ~CnxtEntry(void) { + SharedContSharedPtr sp_cnxt = wp_cnxt_.lock(); + if (sp_cnxt && p_worker_) { + p_worker_->map_id_sharedcontextsp_.erase(sp_cnxt->str_id); + } + p_worker_ = NULL; + } + }; + + typedef boost::shared_ptr AsyncCnxtEntry; + typedef boost::unordered_set CnxtEntryBucket; + typedef boost::circular_buffer CnxtBuf; + CnxtBuf cnxt_entry_circul_buf_; + + static const int8_t kI8TimeWheelNum; + + typedef boost::unordered_map::iterator + UnorderedMapStr2SpConnInfoIter; + + static const int32_t kI32HighWaterSize; // 64K + + muduo::MutexLock mutexlock_avaliable_conn_ready_; + muduo::Condition cond_avaliable_conn_ready_; + + muduo::AtomicInt32 + atomic_avaliable_conn_num_; // exclude disconn/highwater/occupied + + std::string str_svr_appkey_; + std::string str_client_appkey_; + std::string str_serviceName_filter_; + int32_t i32_port_filter_; + int32_t i32_timeout_; + + int8_t i8_destructor_flag_; + + std::string str_server_ip_; + int16_t i16_server_port_; + bool b_user_set_ip; + + boost::unordered_map + map_ipport_sgservice_; // use compare and update svrlist + + // boost::shared_ptr sp_cthrift_transport_sgagent_; + boost::shared_ptr sp_cthrift_client_; + // boost::shared_ptr sp_sgagent_client_; + + // for get seqid from raw buffer + boost::shared_ptr + *sp_p_tmemorybuffer_; + boost::shared_ptr + *sp_p_cthrift_tbinary_protocol_; + + // for common srvlist update + boost::unordered_map + map_ipport_spconninfo_; + + std::multimap + * // ONLY used by conninfo + p_multimap_weight_wptcpcli_; + + typedef boost::unordered_map + ::iterator + UnorderedMapIpPort2ConnInfoSP; + + typedef std::multimap::iterator + MultiMapIter; + + // MultiMapIter it_last_choose_conn; + + boost::shared_ptr sp_event_thread_; + + boost::shared_ptr sp_event_thread_sgagent_; + + muduo::net::EventLoop *p_event_loop_; + muduo::net::EventLoop *p_event_loop_sgagent_; + + // muduo::net::EventLoopThread *p_async_event_thread_; + boost::shared_ptr sp_async_event_thread_; + muduo::net::EventLoop *p_async_event_loop_; + + boost::unordered_map + map_id_sharedcontextsp_; + + typedef boost::unordered_map::iterator + MapID2SharedPointerIter; + + void AddSrv( + const std::vector &vec_add_sgservice); + void DelSrv( + const std::vector &vec_add_sgservice); + void ChgSrv( + const std::vector &vec_add_sgservice); + + void OnConn(const muduo::net::TcpConnectionPtr &conn); + void OnMsg(const muduo::net::TcpConnectionPtr &conn, + muduo::net::Buffer *buffer, + muduo::Timestamp receiveTime); + void HandleMsg(const muduo::net::TcpConnectionPtr &conn, + Context4WorkerSharedPtr &sp_context_worker, + muduo::net::Buffer *buffer); + + void HandleThriftMsg(const muduo::net::TcpConnectionPtr &conn, + const int32_t &length, uint8_t *buf); + + void OnWriteComplete(const muduo::net::TcpConnectionPtr &conn); + void OnHighWaterMark(const muduo::net::TcpConnectionPtr &conn, size_t len); + + void UpdateSvrList + (const std::vector &vec_sgservice); + + void InitWorker(void); + void InitSgagentHandlerThread(void); + + void GetSvrList(void); + + int8_t ChooseNextReadyConn(TcpClientWeakPtr *p_wp_tcpcli); + static int8_t CheckRegion(const double &d_weight); + + // filter + bool FilterAll(const meituan_mns::SGService &sg); + bool FilterService(const meituan_mns::SGService &sg); + bool FilterPort(const meituan_mns::SGService &sg); + + // async + void AsyncCallback(const uint32_t &size, + uint8_t *recv_buf, + SharedContSharedPtr sp_shared); + + public: + CthriftClientWorker(const std::string &str_svr_appkey, + const std::string &str_cli_appkey, + const std::string &str_serviceName_filter, + const int32_t &i32_port_filter, + const std::string &str_server_ip, + const int16_t &i16_server_port); + + void ClearTcpClient(muduo::CountDownLatch *p_clear_countdown) { + CTHRIFT_LOG_DEBUG("into worker thread clean resource"); + map_ipport_spconninfo_.clear(); // clear tcpclient, OR may core when + + // p_multimap_weight_wptcpcli_ only need free memory in work thread. + delete p_multimap_weight_wptcpcli_; + p_clear_countdown->countDown(); + } + + virtual ~CthriftClientWorker() { + // set destructor flag + i8_destructor_flag_ = 1; + + muduo::CountDownLatch clear_countdown(1); + p_event_loop_->runInLoop(boost::bind(&CthriftClientWorker::ClearTcpClient, + this, &clear_countdown)); + // wait until end of the destructor + clear_countdown.wait(); + + if (p_async_event_loop_) { + p_async_event_loop_->quit(); + sp_async_event_thread_.reset(); + } + + // delete will cause memory issue, CthriftClientWorker should keepalive + // during + // thread life-time, so two pointers leak acceptable + // fix以上问题,可以正常释放 + if (CTHRIFT_LIKELY(sp_p_tmemorybuffer_)) { + delete sp_p_tmemorybuffer_; + } + + if (CTHRIFT_LIKELY(sp_p_cthrift_tbinary_protocol_)) { + delete sp_p_cthrift_tbinary_protocol_; + } + } + + muduo::net::EventLoop *getP_event_loop_(void) const { + return p_event_loop_; + } + + void DelContextMapByID(const std::string &str_id) { + MapID2SharedPointerIter + map_iter = map_id_sharedcontextsp_.find(str_id); + if (map_iter != map_id_sharedcontextsp_.end()) { + boost::shared_ptr + sp_send_conn((map_iter->second->wp_send_conn).lock()); + if (sp_send_conn) { + CTHRIFT_LOG_WARN("del id from ipport :" + << (sp_send_conn->peerAddress()).toIpPort()); + } + } + + CTHRIFT_LOG_WARN("del id " << str_id << " by transport for timeout"); + map_id_sharedcontextsp_.erase(str_id); + } + + void SendTransportReq(SharedContSharedPtr sp_shared); + + void TimewheelKick(); + void EnableAsync(const int32_t &i32_timeout_ms); + void AsyncSendReq(SharedContSharedPtr sp_shared); + + int32_t atomic_avaliable_conn_num() { + return atomic_avaliable_conn_num_.get(); + } + + muduo::Condition &cond_avaliable_conn_ready() { + return cond_avaliable_conn_ready_; + } + + muduo::MutexLock &mutexlock_avaliable_conn_ready(void) { + return mutexlock_avaliable_conn_ready_; + } +}; +} // namespace meituan_cthrift + +#endif // CTHRIFT_SRC_CTHRIFT_CTHRIFT_CLIENT_WORKER_H_ diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_name_service.h b/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_name_service.h new file mode 100644 index 0000000..548291b --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_name_service.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +#ifndef CTHRIFT_SRC_CTHRIFT_CTHRIFT_NAME_SERVICE_H_ +#define CTHRIFT_SRC_CTHRIFT_CTHRIFT_NAME_SERVICE_H_ + +#include "cthrift/util/cthrift_common.h" +#include "cthrift/util/cthrift_ns_interface.h" + +namespace meituan_cthrift { +using namespace apache::thrift; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; + +class CthriftNameService { + public: + static bool b_is_init_ns_; + static muduo::MutexLock s_lock; + + static void IntranetIp(char ip[INET_ADDRSTRLEN]); + static void GetHostIPInfo(void); // fill ip, isMac, host,hostname + + static const double kDGetSvrListIntervalSecs; + static const double kDFirstRegionMin; + static const double kDSecondRegionMin; + + static std::string str_env_; + static std::string str_swimlane_; + static std::string str_local_ip_; + static std::string str_host_; + static std::string str_hostname_; + + static CthriftNsInterface ns_interface_; + + CthriftNameService(void) throw(TException); + static void PackDefaultSgservice(const std::string &str_svr_appkey, + const std::string &str_local_ip, + const uint16_t &u16_port, + meituan_mns::SGService *p_sgservice); + + static std::string SGService2String( + const meituan_mns::SGService &sgservice); + + static double + FetchOctoWeight(const double &fweight, const double &weight); + + static int32_t InitNS(); + static void UnInitNS(); + + static int GetSrvListFrom(ServicePtr service); + + static int RegisterService(const meituan_mns::SGService &oservice); +}; + +extern const meituan_cthrift::CthriftNameService g_cthrift_ns; +} // namespace meituan_cthrift + + +#endif // CTHRIFT_SRC_CTHRIFT_CTHRIFT_NAME_SERVICE_H_ diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_svr.h b/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_svr.h new file mode 100644 index 0000000..9573535 --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_svr.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef CTHRIFT_SRC_CTHRIFT_CTHRIFT_SVR_H_ +#define CTHRIFT_SRC_CTHRIFT_CTHRIFT_SVR_H_ + +#include "cthrift/util/cthrift_common.h" +#include "cthrift_client.h" +#include "cthrift_tbinary_protocol.h" +#include "cthrift_transport.h" +#include "cthrift_name_service.h" + +namespace meituan_cthrift { +using apache::thrift::server::TServer; +using apache::thrift::TProcessor; +using apache::thrift::TProcessorFactory; +using apache::thrift::protocol::TProtocolFactory; +using apache::thrift::transport::TTransportFactory; + +typedef boost::weak_ptr TcpConnWeakPtr; + +struct ConnEntry : public muduo::copyable { + TcpConnWeakPtr wp_conn_; + + explicit ConnEntry(const TcpConnWeakPtr &wp_conn) + : wp_conn_(wp_conn) {} + + ~ConnEntry(void) { + muduo::net::TcpConnectionPtr sp_conn = wp_conn_.lock(); + + if (sp_conn && sp_conn->connected()) { + CTHRIFT_LOG_INFO("conn " << (sp_conn->peerAddress()).toIpPort() + << " timeout"); + sp_conn->shutdown(); + } + } +}; + +typedef boost::weak_ptr ConnEntryWeakPtr; + +struct ConnContext { + public: + enum meituan_cthrift::State enum_state; + int32_t i32_want_size; + // time_t t_conn; + time_t t_last_active; + ConnEntryWeakPtr wp_conn_entry; + ConnContext(void) + : enum_state(kExpectFrameSize), i32_want_size(0), + t_last_active(0) {} +}; + +typedef boost::shared_ptr ConnContextSharedPtr; +typedef boost::weak_ptr ConnContextWeakPtr; + +class CthriftSvr : boost::noncopyable, + public TServer { + private: + // time wheel + typedef boost::shared_ptr ConnEntrySharedPtr; + // more than one data entry in one grid in circule buffer + typedef boost::unordered_set + ConnEntryBucket; + typedef boost::circular_buffer ConnEntryBucketCirculBuf; + typedef muduo::ThreadLocalSingleton + LocalSingConnEntryCirculBuf; // kick idle conn + + // static const double kDCheckConnIntervalSec; + static const double kTMaxCliIdleTimeSec; + static const int8_t kI8TimeWheelGridNum; + + static __thread boost::shared_ptr + *sp_p_input_tmemorybuffer_; + static __thread boost::shared_ptr + *sp_p_output_tmemorybuffer_; + + static __thread boost::shared_ptr + *sp_p_input_tprotocol_; + static __thread boost::shared_ptr + *sp_p_output_tprotocol_; + + static __thread boost::shared_ptr *sp_p_processor_; + + std::string str_svr_appkey_; + uint16_t u16_svr_port_; + + int32_t i32_max_conn_num_; + int32_t i32_svr_overtime_ms_; + int16_t i16_conn_thread_num_; + int16_t i16_worker_thread_num_; + int8_t i8_heartbeat_status_; + + // s秒 + double con_collection_interval_; + + static __thread int32_t i32_curr_conn_num_; + + muduo::net::EventLoop event_loop_; // guarantee init before server_ !! + boost::shared_ptr sp_server_; + + muduo::AtomicInt64 atom_i64_worker_thread_pos_; + std::vector vec_worker_event_loop_; + + meituan_mns::SGService sg_service_; + + boost::shared_ptr + sp_timerid_regsvr_; // use to control getsvrlist + + muduo::AtomicInt64 atom_i64_recv_msg_per_min_; + + void OnConn(const muduo::net::TcpConnectionPtr &conn); + void OnMsg(const muduo::net::TcpConnectionPtr &conn, + muduo::net::Buffer *buffer, + muduo::Timestamp receiveTime); + void OnWriteComplete(const muduo::net::TcpConnectionPtr &conn); + + void WorkerThreadInit(muduo::CountDownLatch *p_countdown_workthread_init); + + void Process(const boost::shared_ptr &sp_buf, + boost::weak_ptr wp_tcp_conn, + Timestamp timestamp_from_recv); + + void Process(const int32_t &i32_req_size, + uint8_t *p_u8_req_buf, + boost::weak_ptr wp_tcp_conn, + muduo::Timestamp timestamp); + + void TimewheelKick(void); + + void ConnThreadInit(muduo::CountDownLatch *p_countdown_connthread_init); + + void RegSvr(void); + + int32_t ArgumentCheck(const std::string &str_app_key, + const uint16_t &u16_port, + const int32_t &i32_svr_overtime_ms, + const int32_t &i32_max_conn_num, + // 0: ONLY check str_app_key & port 1: full check + const int8_t &i8_check_type, + std::string *p_str_reason) const; + + void InitStaticThreadLocalMember(void); + + public: + int32_t Init(void); + + // construct with over_time/max_conn_num set/worker_thread + template + CthriftSvr(const boost::shared_ptr &processor, + THRIFT_OVERLOAD_IF(Processor, TProcessor)) throw(TException) + :TServer(processor), + con_collection_interval_(kTMaxCliIdleTimeSec) { + } + + void StatMsgNumPerMin(void); + + void InitWorkerThreadPos(void); + + ~CthriftSvr(void); + + void serve(); + + void stop(); + + const muduo::string &name() const { + return sp_server_->name(); + } +}; // CthriftSvr +} // namespace meituan_cthrift + +#endif // CTHRIFT_SRC_CTHRIFT_CTHRIFT_SVR_H_ diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_tbinary_protocol.h b/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_tbinary_protocol.h new file mode 100644 index 0000000..ae025ca --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_tbinary_protocol.h @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef CTHRIFT_SRC_CTHRIFT_CTHRIFT_TBINARY_PROTOCOL_H_ +#define CTHRIFT_SRC_CTHRIFT_CTHRIFT_TBINARY_PROTOCOL_H_ + +#include "cthrift/util/cthrift_common.h" +#include "cthrift_transport.h" +#include "cthrift_name_service.h" + +namespace meituan_cthrift { + +enum UseType { + CTHRIFT_SERVER, + CTHRIFT_CLIENT, + UNDEFINED +}; + +template +class CthriftTBinaryProtocolT + : public TVirtualProtocol > { + protected: + UseType use_type_; + + static const int32_t VERSION_MASK = 0xffff0000; + static const int32_t VERSION_1 = 0x80010000; + // VERSION_2 (0x80020000) is taken by TDenseProtocol. + + public: + CthriftTBinaryProtocolT(boost::shared_ptr trans, + const UseType &use_type = UNDEFINED) : + TVirtualProtocol >(trans), + use_type_(use_type), + trans_(trans.get()), + string_limit_(meituan_cthrift::GetStringLimit()), + container_limit_(0), + strict_read_(false), + strict_write_(true), + string_buf_(NULL), + string_buf_size_(0) { + if (0 == g_atomic_i32_seq_id.get()) { + g_atomic_i32_seq_id.getAndSet(1); // tiny chance NOT safe + } + } + + CthriftTBinaryProtocolT(boost::shared_ptr trans, + int32_t string_limit, + int32_t container_limit, + bool strict_read, + bool strict_write) : + TVirtualProtocol >(trans), + use_type_(UNDEFINED), + trans_(trans.get()), + string_limit_(string_limit), + container_limit_(container_limit), + strict_read_(strict_read), + strict_write_(strict_write), + string_buf_(NULL), + string_buf_size_(0) {} + + ~CthriftTBinaryProtocolT() { + if (string_buf_ != NULL) { + std::free(string_buf_); + string_buf_size_ = 0; + } + } + + void setStringSizeLimit(int32_t string_limit) { + string_limit_ = string_limit; + } + + void setContainerSizeLimit(int32_t container_limit) { + container_limit_ = container_limit; + } + + void setStrict(bool strict_read, bool strict_write) { + strict_read_ = strict_read; + strict_write_ = strict_write; + } + + /** + * Writing functions. + */ + + inline int32_t GetSeqID(void); + + /*ol*/ inline uint32_t writeMessageBegin(const std::string &name, + const TMessageType messageType, + const int32_t seqid); + + /*ol*/ inline uint32_t writeMessageEnd(); + + inline uint32_t writeStructBegin(const char *name); + + inline uint32_t writeStructEnd(); + + inline uint32_t writeFieldBegin(const char *name, + const TType fieldType, + const int16_t fieldId); + + inline uint32_t writeFieldEnd(); + + inline uint32_t writeFieldStop(); + + inline uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size); + + inline uint32_t writeMapEnd(); + + inline uint32_t writeListBegin(const TType elemType, const uint32_t size); + + inline uint32_t writeListEnd(); + + inline uint32_t writeSetBegin(const TType elemType, const uint32_t size); + + inline uint32_t writeSetEnd(); + + inline uint32_t writeBool(const bool value); + + inline uint32_t writeByte(const int8_t byte); + + inline uint32_t writeI16(const int16_t i16); + + inline uint32_t writeI32(const int32_t i32); + + inline uint32_t writeI64(const int64_t i64); + + inline uint32_t writeDouble(const double dub); + + inline uint32_t writeString(const std::string &str); + + inline uint32_t writeBinary(const std::string &str); + + /** + * Reading functions + */ + + + /*ol*/ uint32_t readMessageBegin(std::string &name, + TMessageType &messageType, + int32_t &seqid); + + /*ol*/ uint32_t readMessageEnd(); + + inline uint32_t readStructBegin(std::string &name); + + inline uint32_t readStructEnd(); + + inline uint32_t readFieldBegin(std::string &name, + TType &fieldType, + int16_t &fieldId); + + inline uint32_t readFieldEnd(); + + inline uint32_t readMapBegin(TType &keyType, + TType &valType, + uint32_t &size); + + inline uint32_t readMapEnd(); + + inline uint32_t readListBegin(TType &elemType, uint32_t &size); + + inline uint32_t readListEnd(); + + inline uint32_t readSetBegin(TType &elemType, uint32_t &size); + + inline uint32_t readSetEnd(); + + inline uint32_t readBool(bool &value); + // Provide the default readBool() implementation for std::vector + using TVirtualProtocol >::readBool; + + inline uint32_t readByte(int8_t &byte); + + inline uint32_t readI16(int16_t &i16); + + inline uint32_t readI32(int32_t &i32); + + inline uint32_t readI64(int64_t &i64); + + inline uint32_t readDouble(double &dub); + + inline uint32_t readString(std::string &str); + + inline uint32_t readBinary(std::string &str); + + protected: + uint32_t readStringBody(std::string &str, int32_t sz); + + Transport_ *trans_; + + int32_t string_limit_; + int32_t container_limit_; + + // Enforce presence of version identifier + bool strict_read_; + bool strict_write_; + + // Buffer for reading strings, save for the lifetime of the protocol to + // avoid memory churn allocating memory on every string read + uint8_t *string_buf_; + int32_t string_buf_size_; +}; + +// typedef CthriftTBinaryProtocolT CthriftTBinaryProtocol; + +typedef CthriftTBinaryProtocolT + CthriftTBinaryProtoWithCthriftTrans; + +typedef CthriftTBinaryProtocolT + CthriftTBinaryProtocolWithTMemoryBuf; + +template<> +inline uint32_t CthriftTBinaryProtocolT:: +writeMessageBegin(const std::string &name, + const TMessageType messageType, + const int32_t seqid); + +template<> +inline uint32_t CthriftTBinaryProtocolT:: +writeMessageBegin(const std::string &name, + const TMessageType messageType, + const int32_t seqid); + +template<> +inline int32_t CthriftTBinaryProtocolT::GetSeqID(void); + +/** + * Constructs binary protocol handlers + */ +template +class CthriftTBinaryProtocolFactoryT : public TProtocolFactory { + public: + CthriftTBinaryProtocolFactoryT() : + string_limit_(0), + container_limit_(0), + strict_read_(false), + strict_write_(true) {} + + CthriftTBinaryProtocolFactoryT(int32_t string_limit, int32_t container_limit, + bool strict_read, bool strict_write) : + string_limit_(string_limit), + container_limit_(container_limit), + strict_read_(strict_read), + strict_write_(strict_write) {} + + virtual ~CthriftTBinaryProtocolFactoryT() {} + + void setStringSizeLimit(int32_t string_limit) { + string_limit_ = string_limit; + } + + void setContainerSizeLimit(int32_t container_limit) { + container_limit_ = container_limit; + } + + void setStrict(bool strict_read, bool strict_write) { + strict_read_ = strict_read; + strict_write_ = strict_write; + } + + boost::shared_ptr + getProtocol(boost::shared_ptr trans) { + boost::shared_ptr specific_trans = + boost::dynamic_pointer_cast(trans); + TProtocol *prot; + if (specific_trans) { + prot = + new CthriftTBinaryProtocolT(specific_trans, + string_limit_, + container_limit_, + strict_read_, + strict_write_); + } else { + prot = new CthriftTBinaryProtocolT(trans, string_limit_, + container_limit_, + strict_read_, + strict_write_); + } + + return boost::shared_ptr(prot); + } + + private: + int32_t string_limit_; + int32_t container_limit_; + bool strict_read_; + bool strict_write_; +}; + +typedef CthriftTBinaryProtocolFactoryT + CthriftTBinaryProtocolFactory; +typedef CthriftTBinaryProtocolFactoryT + CthriftTAsyncProtocolFactory; + +} // namespace meituan_cthrift + +#include "cthrift_tbinary_protocol.tcc" + +#endif // CTHRIFT_SRC_CTHRIFT_CTHRIFT_TBINARY_PROTOCOL_H_ diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_tbinary_protocol.tcc b/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_tbinary_protocol.tcc new file mode 100644 index 0000000..4eafb83 --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_tbinary_protocol.tcc @@ -0,0 +1,617 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef CTHRIFT_SRC_CTHRIFT_TBINARY_PROTOCOL_TCC_ +#define CTHRIFT_SRC_CTHRIFT_TBINARY_PROTOCOL_TCC_ + +#include "cthrift_transport.h" +#include "cthrift_tbinary_protocol.h" + +namespace meituan_cthrift { +using namespace std; +using namespace muduo; + +template<> +int32_t CthriftTBinaryProtocolT::GetSeqID(void) { + + int32_t i32_size = 0; + readI32(i32_size); + + // follow two just offset + string str_name; + int8_t i8_type; + + int32_t i32_seq_id = 0; + + if (0 > i32_size && ((i32_size & VERSION_MASK) == VERSION_1)) { + readString(str_name); + readI32(i32_seq_id); + + CTHRIFT_LOG_DEBUG("seq_id " << i32_seq_id); + return i32_seq_id; + } else if (0 <= i32_size && !(this->strict_read_)) { + readStringBody(str_name, i32_size); + readByte(i8_type); + readI32(i32_seq_id); + + CTHRIFT_LOG_DEBUG("seq_id " << i32_seq_id); + return i32_seq_id; + } + + return 0; +} + +template +int32_t +CthriftTBinaryProtocolT::GetSeqID(void) { + return 0; +} + +template<> +uint32_t CthriftTBinaryProtocolT:: +writeMessageBegin(const std::string &name, + const TMessageType messageType, + const int32_t seqid) { + CTHRIFT_LOG_DEBUG("async writeMessageBegin"); + + int32_t i32_seq_id = seqid; + if (0 == seqid) { + i32_seq_id = g_atomic_i32_seq_id + .incrementAndGet(); + + if (CTHRIFT_UNLIKELY(std::numeric_limits::max() == i32_seq_id)) { + CTHRIFT_LOG_WARN("i32_seq_id " << i32_seq_id + << " up to int32 max value, reset to 1"); + g_atomic_i32_seq_id.getAndSet(1); + i32_seq_id = 1; + } + + } + CTHRIFT_LOG_DEBUG("seq_id " << i32_seq_id); + + if (this->strict_write_) { + int32_t version = (VERSION_1) | (static_cast(messageType)); + uint32_t wsize = 0; + // 协助channel获取seq,从而避免内存copy开销 + wsize += writeI32(version); + wsize += writeString(name); + wsize += writeI32(i32_seq_id); + + wsize += writeI32(version); + wsize += writeString(name); + wsize += writeI32(i32_seq_id); + return wsize; + } else { + uint32_t wsize = 0; + // 协助channel获取seq,从而避免内存copy开销 + wsize += writeString(name); + wsize += writeByte(static_cast(messageType)); + wsize += writeI32(i32_seq_id); + + wsize += writeString(name); + wsize += writeByte(static_cast(messageType)); + wsize += writeI32(i32_seq_id); + return wsize; + } +} + +template<> +uint32_t CthriftTBinaryProtocolT:: +writeMessageBegin(const std::string &name, + const TMessageType messageType, + const int32_t seqid) { + CTHRIFT_LOG_DEBUG("writeMessageBegin"); + + int32_t i32_seq_id = seqid; + if (CTHRIFT_CLIENT == use_type_ && 0 == seqid) { + i32_seq_id = g_atomic_i32_seq_id + .incrementAndGet(); + + if (CTHRIFT_UNLIKELY(std::numeric_limits::max() == i32_seq_id)) { + CTHRIFT_LOG_WARN("i32_seq_id " << i32_seq_id << + " up to int32 max value, reset to 1"); + g_atomic_i32_seq_id.getAndSet(1); + i32_seq_id = 1; + } + + CTHRIFT_LOG_DEBUG("seq_id " << i32_seq_id); + + string str_id; + try { + str_id = boost::lexical_cast(i32_seq_id); + } catch (boost::bad_lexical_cast &e) { + + CTHRIFT_LOG_ERROR("boost::bad_lexical_cast :" << e.what() + << "i32_seq_id : " + << i32_seq_id); + } + + boost::dynamic_pointer_cast + (getTransport())->ResetWriteBuf(); + CTHRIFT_LOG_DEBUG("clear write buf done"); + + boost::dynamic_pointer_cast + (getTransport())->SetID2Transport( + str_id); //Transport to CthriftTransport, CANNOT + // use dynamic_cast + } + + if (this->strict_write_) { + int32_t version = (VERSION_1) | (static_cast(messageType)); + uint32_t wsize = 0; + wsize += writeI32(version); + wsize += writeString(name); + wsize += writeI32(i32_seq_id); + return wsize; + } else { + uint32_t wsize = 0; + wsize += writeString(name); + wsize += writeByte(static_cast(messageType)); + wsize += writeI32(i32_seq_id); + return wsize; + } +} + +template +uint32_t +CthriftTBinaryProtocolT::writeMessageBegin(const std::string &name, + const TMessageType messageType, + const int32_t seqid) { + CTHRIFT_LOG_DEBUG("Transport_ writeMessageBegin"); + if (this->strict_write_) { + int32_t version = (VERSION_1) | (static_cast(messageType)); + uint32_t wsize = 0; + wsize += writeI32(version); + wsize += writeString(name); + wsize += writeI32(seqid); + return wsize; + } else { + uint32_t wsize = 0; + wsize += writeString(name); + wsize += writeByte(static_cast(messageType)); + wsize += writeI32(seqid); + return wsize; + } +} + +template +uint32_t CthriftTBinaryProtocolT::writeMessageEnd() { + return 0; +} + +template +uint32_t +CthriftTBinaryProtocolT::writeStructBegin(const char *name) { + (void) name; + return 0; +} + +template +uint32_t CthriftTBinaryProtocolT::writeStructEnd() { + return 0; +} + +template +uint32_t CthriftTBinaryProtocolT::writeFieldBegin(const char *name, + const TType fieldType, + const int16_t fieldId) { + (void) name; + uint32_t wsize = 0; + wsize += writeByte(static_cast(fieldType)); + wsize += writeI16(fieldId); + return wsize; +} + +template +uint32_t CthriftTBinaryProtocolT::writeFieldEnd() { + return 0; +} + +template +uint32_t CthriftTBinaryProtocolT::writeFieldStop() { + return + writeByte(static_cast(T_STOP)); +} + +template +uint32_t CthriftTBinaryProtocolT::writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size) { + uint32_t wsize = 0; + wsize += writeByte(static_cast(keyType)); + wsize += writeByte(static_cast(valType)); + wsize += writeI32(static_cast(size)); + return wsize; +} + +template +uint32_t CthriftTBinaryProtocolT::writeMapEnd() { + return 0; +} + +template +uint32_t +CthriftTBinaryProtocolT::writeListBegin(const TType elemType, + const uint32_t size) { + uint32_t wsize = 0; + wsize += writeByte(static_cast(elemType)); + wsize += writeI32(static_cast(size)); + return wsize; +} + +template +uint32_t CthriftTBinaryProtocolT::writeListEnd() { + return 0; +} + +template +uint32_t +CthriftTBinaryProtocolT::writeSetBegin(const TType elemType, + const uint32_t size) { + uint32_t wsize = 0; + wsize += writeByte(static_cast(elemType)); + wsize += writeI32(static_cast(size)); + return wsize; +} + +template +uint32_t CthriftTBinaryProtocolT::writeSetEnd() { + return 0; +} + +template +uint32_t CthriftTBinaryProtocolT::writeBool(const bool value) { + uint8_t tmp = value ? 1 : 0; + this->trans_->write(&tmp, 1); + return 1; +} + +template +uint32_t CthriftTBinaryProtocolT::writeByte(const int8_t byte) { + uint8_t u_byte = static_cast(byte); + this->trans_->write(&u_byte, 1); + return 1; +} + +template +uint32_t CthriftTBinaryProtocolT::writeI16(const int16_t i16) { + int16_t net = static_cast((htons)(i16)); + this->trans_->write(reinterpret_cast(&net), 2); + return 2; +} + +template +uint32_t CthriftTBinaryProtocolT::writeI32(const int32_t i32) { + int32_t net = static_cast( htonl(i32)); + this->trans_->write(reinterpret_cast(&net), 4); + return 4; +} + +template +uint32_t CthriftTBinaryProtocolT::writeI64(const int64_t i64) { + int64_t net = static_cast( htonll(i64)); + this->trans_->write(reinterpret_cast(&net), 8); + return 8; +} + +template +uint32_t CthriftTBinaryProtocolT::writeDouble(const double dub) { + BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); + BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + + uint64_t bits = bitwise_cast(dub); + bits = htonll(bits); + this->trans_->write(reinterpret_cast(&bits), 8); + return 8; +} + +template +uint32_t +CthriftTBinaryProtocolT::writeString(const std::string &str) { + uint32_t size = static_cast(str.size()); + uint32_t result = writeI32(static_cast( size )); + if (size > 0) { + this->trans_->write(reinterpret_cast( str.data()), size); + } + return result + size; +} + +template +uint32_t +CthriftTBinaryProtocolT::writeBinary(const std::string &str) { + return CthriftTBinaryProtocolT::writeString(str); +} + +/** + * Reading functions + */ + +template +uint32_t +CthriftTBinaryProtocolT::readMessageBegin(std::string &name, + TMessageType &messageType, + int32_t &seqid) { + uint32_t result = 0; + int32_t sz; + result += readI32(sz); + + if (sz < 0) { + // Check for correct version number + int32_t version = sz & VERSION_MASK; + if (version != VERSION_1) { + throw TProtocolException(TProtocolException::BAD_VERSION, + "Bad version identifier"); + } + messageType = static_cast(sz & 0x000000ff); + result += readString(name); + result += readI32(seqid); + } else { + if (this->strict_read_) { + throw TProtocolException(TProtocolException::BAD_VERSION, + "No version identifier... old protocol client in strict mode?"); + } else { + // Handle pre-versioned input + int8_t type; + result += readStringBody(name, sz); + result += readByte(type); + messageType = static_cast( type ); + result += readI32(seqid); + } + } + return result; +} + +template +uint32_t CthriftTBinaryProtocolT::readMessageEnd() { + return 0; +} + +template +uint32_t +CthriftTBinaryProtocolT::readStructBegin(std::string &name) { + name = ""; + return 0; +} + +template +uint32_t CthriftTBinaryProtocolT::readStructEnd() { + return 0; +} + +template +uint32_t CthriftTBinaryProtocolT::readFieldBegin(std::string &name, + TType &fieldType, + int16_t &fieldId) { + (void) name; + uint32_t result = 0; + int8_t type; + result += readByte(type); + fieldType = static_cast( type ); + if (fieldType == T_STOP) { + fieldId = 0; + return result; + } + result += readI16(fieldId); + return result; +} + +template +uint32_t CthriftTBinaryProtocolT::readFieldEnd() { + return 0; +} + +template +uint32_t CthriftTBinaryProtocolT::readMapBegin(TType &keyType, + TType &valType, + uint32_t &size) { + int8_t k, v; + uint32_t result = 0; + int32_t sizei; + result += readByte(k); + keyType = static_cast( k ); + result += readByte(v); + valType = static_cast( v ); + result += readI32(sizei); + if (sizei < 0) { + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } else if (this->container_limit_ && sizei > this->container_limit_) { + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + size = static_cast( sizei ); + return result; +} + +template +uint32_t CthriftTBinaryProtocolT::readMapEnd() { + return 0; +} + +template +uint32_t CthriftTBinaryProtocolT::readListBegin(TType &elemType, + uint32_t &size) { + int8_t e; + uint32_t result = 0; + int32_t sizei; + result += readByte(e); + elemType = static_cast( e ); + result += readI32(sizei); + if (sizei < 0) { + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } else if (this->container_limit_ && sizei > this->container_limit_) { + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + size = static_cast( sizei ); + return result; +} + +template +uint32_t CthriftTBinaryProtocolT::readListEnd() { + return 0; +} + +template +uint32_t CthriftTBinaryProtocolT::readSetBegin(TType &elemType, + uint32_t &size) { + int8_t e; + uint32_t result = 0; + int32_t sizei; + result += readByte(e); + elemType = static_cast( e ); + result += readI32(sizei); + if (sizei < 0) { + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } else if (this->container_limit_ && sizei > this->container_limit_) { + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + size = static_cast( sizei ); + return result; +} + +template +uint32_t CthriftTBinaryProtocolT::readSetEnd() { + return 0; +} + +template +uint32_t CthriftTBinaryProtocolT::readBool(bool &value) { + uint8_t b[1]; + this->trans_->readAll(b, 1); + value = *reinterpret_cast(b) != 0; + return 1; +} + +template +uint32_t CthriftTBinaryProtocolT::readByte(int8_t &byte) { + uint8_t b[1]; + this->trans_->readAll(b, 1); + byte = *reinterpret_cast(b); + return 1; +} + +template +uint32_t CthriftTBinaryProtocolT::readI16(int16_t &i16) { + union bytes { + uint8_t b[2]; + int16_t all; + } theBytes; + this->trans_->readAll(theBytes.b, 2); + i16 = static_cast((ntohs)(theBytes.all)); + return 2; +} + +template +uint32_t CthriftTBinaryProtocolT::readI32(int32_t &i32) { + union bytes { + uint8_t b[4]; + int32_t all; + } theBytes; + this->trans_->readAll(theBytes.b, 4); + i32 = static_cast(ntohl(theBytes.all)); + return 4; +} + +template +uint32_t CthriftTBinaryProtocolT::readI64(int64_t &i64) { + union bytes { + uint8_t b[8]; + int64_t all; + } theBytes; + this->trans_->readAll(theBytes.b, 8); + i64 = static_cast(ntohll(theBytes.all)); + return 8; +} + +template +uint32_t CthriftTBinaryProtocolT::readDouble(double &dub) { + BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); + BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + + union bytes { + uint8_t b[8]; + uint64_t all; + } theBytes; + this->trans_->readAll(theBytes.b, 8); + theBytes.all = ntohll(theBytes.all); + dub = bitwise_cast(theBytes.all); + return 8; +} + +template +uint32_t CthriftTBinaryProtocolT::readString(std::string &str) { + uint32_t result; + int32_t size; + result = readI32(size); + return result + readStringBody(str, size); +} + +template +uint32_t CthriftTBinaryProtocolT::readBinary(std::string &str) { + return CthriftTBinaryProtocolT::readString(str); +} + +template +uint32_t CthriftTBinaryProtocolT::readStringBody(std::string &str, + int32_t size) { + uint32_t result = 0; + + // Catch error cases + if (size < 0) { + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } + if (this->string_limit_ > 0 && size > this->string_limit_) { + CTHRIFT_LOG_ERROR("throw TProtocolException::SIZE_LIMIT : " + << this->string_limit_ + << " read size:" << size); + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + + // Catch empty string case + if (size == 0) { + str = ""; + return result; + } + + // Try to borrow first + const uint8_t *borrow_buf; + uint32_t got = size; + if ((borrow_buf = this->trans_->borrow(NULL, &got))) { + str.assign(reinterpret_cast(borrow_buf), size); + this->trans_->consume(size); + return size; + } + + // Use the heap here to prevent stack overflow for v. large strings + if (size > this->string_buf_size_ || this->string_buf_ == NULL) { + void *new_string_buf = + std::realloc(this->string_buf_, static_cast( size )); + if (new_string_buf == NULL) { + throw std::bad_alloc(); + } + this->string_buf_ = static_cast( new_string_buf ); + this->string_buf_size_ = size; + } + this->trans_->readAll(this->string_buf_, size); + str = std::string(reinterpret_cast( this->string_buf_ ), size); + return static_cast( size ); +} +} // namespace meituan_cthrift + +#endif diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_transport.h b/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_transport.h new file mode 100644 index 0000000..7dd3908 --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/cthrift_transport.h @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef CTHRIFT_SRC_CTHRIFT_CTHRIFT_TRANSPORT_H_ +#define CTHRIFT_SRC_CTHRIFT_CTHRIFT_TRANSPORT_H_ + +#include "cthrift/util/cthrift_common.h" + +namespace meituan_cthrift { +using namespace apache::thrift; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; + +class CthriftClientWorker; +class CthriftNameService; + +struct SharedBetweenWorkerTransport { + apache::thrift::async::TAsyncChannel::VoidCallback cob_; + std::string str_id; // write by transport + muduo::MutexLock *p_mutexlock_conn_ready; + muduo::Condition *p_cond_ready_read; + + boost::weak_ptr wp_mutexlock_read_buf; + TMemBufSharedPtr *p_sp_read_tmembuf; + // 写锁在超时场景下存在idl-client销毁风险,用weak_ptr监控对象生命周期 + boost::weak_ptr wp_mutexlock_write_buf; + TMemBufSharedPtr *p_sp_write_tmembuf; + + int32_t i32_timeout_ms; + muduo::Timestamp timestamp_start; + muduo::Timestamp timestamp_cliworker_send; // use ONLY by clientworker + boost::weak_ptr + wp_send_conn; // use ONLY by clientworker + + boost::weak_ptr wp_b_timeout; // use to note client_worker timeout + + // async + bool async_flag; + TMemoryBuffer *p_recv_tmembuf; + TMemBufSharedPtr sp_send_tmembuf; + + SharedBetweenWorkerTransport() + : p_mutexlock_conn_ready(0), p_cond_ready_read(0), + p_sp_read_tmembuf(0), p_sp_write_tmembuf(0), + i32_timeout_ms(0), timestamp_start(muduo::Timestamp::now()), + async_flag(false), p_recv_tmembuf(0) { ; } + + ~SharedBetweenWorkerTransport() { + p_sp_read_tmembuf = NULL; + p_sp_write_tmembuf = NULL; + } + + SharedBetweenWorkerTransport( + muduo::MutexLock *p_mutexlock_conn_ready_tmp, + muduo::Condition *p_cond_ready_read_tmp, + boost::weak_ptr wp_mutexlock_read_buf_tmp, + TMemBufSharedPtr *p_sp_read_tmembuf_tmp, + boost::weak_ptr wp_mutexlock_write_buf_tmp, + TMemBufSharedPtr *p_sp_write_tmembuf_tmp, + const int32_t &i32_timeout_tmp) + : p_mutexlock_conn_ready(p_mutexlock_conn_ready_tmp), + p_cond_ready_read(p_cond_ready_read_tmp), + wp_mutexlock_read_buf(wp_mutexlock_read_buf_tmp), + p_sp_read_tmembuf(p_sp_read_tmembuf_tmp), + wp_mutexlock_write_buf(wp_mutexlock_write_buf_tmp), + p_sp_write_tmembuf(p_sp_write_tmembuf_tmp), + i32_timeout_ms(i32_timeout_tmp), + timestamp_start(muduo::Timestamp::now()), + async_flag(false), + p_recv_tmembuf(0) { ; } + + SharedBetweenWorkerTransport(const SharedBetweenWorkerTransport &shared) { + str_id.assign(shared.str_id); + + async_flag = shared.async_flag; + p_mutexlock_conn_ready = shared.p_mutexlock_conn_ready; + p_cond_ready_read = shared.p_cond_ready_read; + wp_mutexlock_read_buf = shared.wp_mutexlock_read_buf; + p_sp_read_tmembuf = shared.p_sp_read_tmembuf; + wp_mutexlock_write_buf = shared.wp_mutexlock_write_buf; + p_sp_write_tmembuf = shared.p_sp_write_tmembuf; + + i32_timeout_ms = shared.i32_timeout_ms; + + timestamp_start = shared.timestamp_start; + timestamp_cliworker_send = shared.timestamp_cliworker_send; + + wp_b_timeout = shared.wp_b_timeout; + p_recv_tmembuf = shared.p_recv_tmembuf; + sp_send_tmembuf = shared.sp_send_tmembuf; + } + + SharedBetweenWorkerTransport & + operator=(const SharedBetweenWorkerTransport &shared) { + if (this != &shared) { + str_id.assign(shared.str_id); + + async_flag = shared.async_flag; + p_mutexlock_conn_ready = shared.p_mutexlock_conn_ready; + p_cond_ready_read = shared.p_cond_ready_read; + wp_mutexlock_read_buf = shared.wp_mutexlock_read_buf; + p_sp_read_tmembuf = shared.p_sp_read_tmembuf; + wp_mutexlock_write_buf = shared.wp_mutexlock_write_buf; + p_sp_write_tmembuf = shared.p_sp_write_tmembuf; + + i32_timeout_ms = shared.i32_timeout_ms; + + timestamp_start = shared.timestamp_start; + timestamp_cliworker_send = shared.timestamp_cliworker_send; + + wp_b_timeout = shared.wp_b_timeout; + p_recv_tmembuf = shared.p_recv_tmembuf; + sp_send_tmembuf = shared.sp_send_tmembuf; + } + + return *this; + } + + bool IsTimeout(void) { + return wp_b_timeout.expired(); + } + + void EnableTimeout(const boost::shared_ptr &sp_b_timeout) { + wp_b_timeout = sp_b_timeout; + } + + int8_t GetAsyncWriteBuf(muduo::net::Buffer *p_buf) { + if (CTHRIFT_UNLIKELY(!p_buf || !sp_send_tmembuf)) { + CTHRIFT_LOG_ERROR("async p_buf OR sp_send_tmembuf NULL"); + return -1; + } + + uint8_t *buf = 0; + uint32_t u32_len = 0; + + sp_send_tmembuf->getBuffer(&buf, &u32_len); + CTHRIFT_LOG_DEBUG("u32_len " << u32_len); + + if (0 == u32_len) { + CTHRIFT_LOG_WARN("async 0 == u32_len"); + return -1; + } + + p_buf->appendInt32(u32_len); // Head size + p_buf->append(buf, u32_len); + + return 0; + } + + int8_t GetWriteBuf(muduo::net::Buffer *p_buf) { + boost::shared_ptr sp_mutexlock_write_buf + = wp_mutexlock_write_buf.lock(); + + if (CTHRIFT_UNLIKELY(!sp_mutexlock_write_buf || !p_sp_write_tmembuf)) { + CTHRIFT_LOG_ERROR("p_sp_write_tmembuf OR p_mutexlock_write_buf NULL"); + return -1; + } + + TMemBufSharedPtr tmem_tmp; + { + muduo::MutexLockGuard lock(*sp_mutexlock_write_buf); + tmem_tmp = *p_sp_write_tmembuf; + } + + uint8_t *buf = 0; + uint32_t u32_len = 0; + + tmem_tmp->getBuffer(&buf, &u32_len); + CTHRIFT_LOG_DEBUG("u32_len " << u32_len); + + if (0 == u32_len) { + CTHRIFT_LOG_WARN("0 == u32_len"); + return -1; + } + + p_buf->appendInt32(u32_len); // Head size + p_buf->append(buf, u32_len); + + return 0; + } + + void ResetReadBuf(uint8_t *p_buf, uint32_t u32_len) { + boost::shared_ptr sp_mutexlock_read_buf + = wp_mutexlock_read_buf.lock(); + if (CTHRIFT_UNLIKELY(!sp_mutexlock_read_buf || !p_sp_read_tmembuf)) { + CTHRIFT_LOG_ERROR("p_sp_read_tmembuf OR p_mutexlock_read_buf NULL"); + return; + } + + muduo::MutexLockGuard lock(*sp_mutexlock_read_buf); + if (!(p_sp_read_tmembuf->unique())) { + // No need copy original buf since reset + *p_sp_read_tmembuf = + boost::make_shared(); + } + + (*p_sp_read_tmembuf)->resetBuffer(p_buf, u32_len, TMemoryBuffer::COPY); + } + + void ResetRecvBuf(uint8_t *p_buf, uint32_t u32_len) { + if (CTHRIFT_UNLIKELY(!p_buf || u32_len <= 0)) { + CTHRIFT_LOG_WARN("p_buf invalid OR u32_len <= 0," + << " maybe task timeout befor network transport"); + return; + } + // 避免重复buffer拷贝,将传入的内存生命周期交给TMemoryBuffer对象管理 + p_recv_tmembuf->resetBuffer(p_buf, u32_len, TMemoryBuffer::TAKE_OWNERSHIP); + } + + /*void GeneteUuid(void) { + uuid_t uuid; + + { + muduo::MutexLockGuard lock(g_mutexlock_uuid); + uuid_generate(uuid); //NOT thread safe + } + + char uuid_str[37] = {0}; + uuid_unparse(uuid, uuid_str); + str_id.assign(uuid_str); + + CTHRIFT_LOG_DEBUG << "uuid " << str_id; + }*/ +}; + +typedef boost::shared_ptr SharedContSharedPtr; +typedef boost::weak_ptr WeakContSharedPtr; +} // meituan_cthrift + +namespace apache { +namespace thrift { +namespace transport { +using namespace meituan_cthrift; + +class CthriftTransport : public TTransport { + private: + std::string str_svr_appkey_; + int32_t i32_timeout_ms_; + std::string str_cli_appkey_; + + muduo::MutexLock mutexlock_conn_ready; + muduo::Condition cond_ready_read; + + boost::shared_ptr sp_mutexlock_read_buf; + TMemBufSharedPtr sp_read_tmembuf_; + boost::shared_ptr sp_mutexlock_write_buf; + TMemBufSharedPtr sp_write_tmembuf_; + + SharedContSharedPtr sp_shared_worker_transport_; + + boost::shared_ptr sp_cthrift_client_worker_; + + // for note timeout to clientworker immediately + boost::shared_ptr sp_bool_timeout_; + + void AppendReadBuf(const uint8_t *buf, uint32_t len) { + muduo::MutexLockGuard lock(*sp_mutexlock_read_buf); + if (!(sp_read_tmembuf_.unique())) { + uint8_t *p_buf = 0; + uint32_t u32_len = 0; + + sp_read_tmembuf_->getBuffer(&p_buf, &u32_len); + sp_read_tmembuf_ = + boost::make_shared(p_buf, + u32_len, + TMemoryBuffer::COPY); + } + + sp_read_tmembuf_->write(buf, len); + } + + void AppendWriteBuf(const uint8_t *buf, uint32_t len) { + muduo::MutexLockGuard lock(*sp_mutexlock_write_buf); + if (!(sp_write_tmembuf_.unique())) { + uint8_t *p_buf = 0; + uint32_t u32_len = 0; + + sp_write_tmembuf_->getBuffer(&p_buf, &u32_len); + sp_write_tmembuf_ = + boost::make_shared(p_buf, + u32_len, + TMemoryBuffer::COPY); + } + + sp_write_tmembuf_->write(buf, len); + } + + uint32_t ReadBufAvaliableReadSize(void) { + TMemBufSharedPtr sp_read_buf; + { + muduo::MutexLockGuard lock(*sp_mutexlock_read_buf); + sp_read_buf = sp_read_tmembuf_; + } + + return sp_read_buf->available_read(); + } + + uint32_t ReadBufRead(uint8_t *buf, uint32_t len) { + muduo::MutexLockGuard lock(*sp_mutexlock_read_buf); + if (!(sp_read_tmembuf_.unique())) { + uint8_t *p_buf = 0; + uint32_t u32_len = 0; + + sp_read_tmembuf_->getBuffer(&p_buf, &u32_len); + sp_read_tmembuf_ = + boost::make_shared(p_buf, + u32_len, + TMemoryBuffer::COPY); + } + + return sp_read_tmembuf_->read(buf, len); + } + + void ResetReadBuf(void) { + muduo::MutexLockGuard lock(*sp_mutexlock_read_buf); + if (!(sp_read_tmembuf_.unique())) { + // No need copy original buf since reset + sp_read_tmembuf_ = + boost::make_shared(); + } + + sp_read_tmembuf_->resetBuffer(); + } + + public: + CthriftTransport(const std::string &str_svr_appkey, + const int32_t &i32_timeout, + const std::string &str_cli_appkey, + const boost::shared_ptr + &sp_cthrift_client_worker) + : str_svr_appkey_(str_svr_appkey), + // cthrift_client already check i32_timeout + i32_timeout_ms_(i32_timeout), + str_cli_appkey_(str_cli_appkey), + cond_ready_read(mutexlock_conn_ready), + sp_cthrift_client_worker_(sp_cthrift_client_worker) { + sp_mutexlock_read_buf = boost::make_shared(); + sp_mutexlock_write_buf = boost::make_shared(); + + sp_read_tmembuf_ = boost::make_shared(); + sp_write_tmembuf_ = boost::make_shared(); + + sp_shared_worker_transport_ = boost::make_shared< + SharedBetweenWorkerTransport>(&mutexlock_conn_ready, + &cond_ready_read, + sp_mutexlock_read_buf, + &sp_read_tmembuf_, + sp_mutexlock_write_buf, + &sp_write_tmembuf_, + i32_timeout_ms_); + } + + virtual uint32_t read_virt(uint8_t *buf, uint32_t len) throw + (TTransportException); + + virtual void write_virt(const uint8_t *buf, uint32_t len); + + void flush(void) throw(TTransportException); + + void SetID2Transport(const std::string &str_id); + + void ResetWriteBuf(void); +}; +} // namespace meituan_cthrift +} // namespace thrift +} // namespace apache + + +#endif // CTHRIFT_SRC_CTHRIFT_CTHRIFT_TRANSPORT_H_ diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/echo_constants.h b/sg_agent/thrid_party/cthrift/include/cthrift/echo_constants.h new file mode 100644 index 0000000..cce2431 --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/echo_constants.h @@ -0,0 +1,24 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef echo_CONSTANTS_H +#define echo_CONSTANTS_H + +#include "echo_types.h" + +namespace echo { + +class echoConstants { + public: + echoConstants(); + +}; + +extern const echoConstants g_echo_constants; + +} // namespace + +#endif diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/echo_types.h b/sg_agent/thrid_party/cthrift/include/cthrift/echo_types.h new file mode 100644 index 0000000..a00028d --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/echo_types.h @@ -0,0 +1,116 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef echo_TYPES_H +#define echo_TYPES_H + +#include +#include +#include +#include + + + +namespace echo { + +struct TweetType { + enum type { + TWEET = 0, + RETWEET = 2, + DM = 10, + REPLY = 11 + }; +}; + +extern const std::map _TweetType_VALUES_TO_NAMES; + + +class test { + public: + + static const char* ascii_fingerprint; // = "BE83BDAD1197A19ED21F973CAC2DABDF"; + static const uint8_t binary_fingerprint[16]; // = {0xBE,0x83,0xBD,0xAD,0x11,0x97,0xA1,0x9E,0xD2,0x1F,0x97,0x3C,0xAC,0x2D,0xAB,0xDF}; + + test() : arg(""), arg2(0), arg5(0), arg7(0), arg8((TweetType::type)0) { + } + + virtual ~test() throw() {} + + std::string arg; + double arg2; + std::vector arg3; + std::map arg4; + bool arg5; + std::set arg6; + int32_t arg7; + TweetType::type arg8; + + void __set_arg(const std::string& val) { + arg = val; + } + + void __set_arg2(const double val) { + arg2 = val; + } + + void __set_arg3(const std::vector & val) { + arg3 = val; + } + + void __set_arg4(const std::map & val) { + arg4 = val; + } + + void __set_arg5(const bool val) { + arg5 = val; + } + + void __set_arg6(const std::set & val) { + arg6 = val; + } + + void __set_arg7(const int32_t val) { + arg7 = val; + } + + void __set_arg8(const TweetType::type val) { + arg8 = val; + } + + bool operator == (const test & rhs) const + { + if (!(arg == rhs.arg)) + return false; + if (!(arg2 == rhs.arg2)) + return false; + if (!(arg3 == rhs.arg3)) + return false; + if (!(arg4 == rhs.arg4)) + return false; + if (!(arg5 == rhs.arg5)) + return false; + if (!(arg6 == rhs.arg6)) + return false; + if (!(arg7 == rhs.arg7)) + return false; + if (!(arg8 == rhs.arg8)) + return false; + return true; + } + bool operator != (const test &rhs) const { + return !(*this == rhs); + } + + bool operator < (const test & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +} // namespace + +#endif diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/util/cthrift_common.h b/sg_agent/thrid_party/cthrift/include/cthrift/util/cthrift_common.h new file mode 100755 index 0000000..3bb9b61 --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/util/cthrift_common.h @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef CTHRIFT_SRC_CTHRIFT_UTIL_CTHRIFT_COMMON_H_ +#define CTHRIFT_SRC_CTHRIFT_UTIL_CTHRIFT_COMMON_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include + +#include "log4cplus.h" +#include "cthrift_config.h" + +#include +#include +#include + +extern "C" { +#ifdef htonl +#undef htonl +#endif +#ifdef htonll +#undef htonll +#endif +#include +} + + +namespace meituan_cthrift { +using apache::thrift::transport::TMemoryBuffer; +using apache::thrift::transport::TTransport; + +using namespace muduo; + +typedef boost::shared_ptr TcpClientSharedPtr; +typedef boost::weak_ptr TcpClientWeakPtr; +typedef boost::shared_ptr TMemBufSharedPtr; + +const int MNS_SUCCESS = 0; +const int FAILURE = -1; +const int ZK_CLIENT_TIMEOUT = 10000; +const int ZK_RETRY = 3; +const int DEFAULT_SERVICE_TIMEOUT = 200000; + +const int ERR_NODE_NOTFIND = -101; +const int ERR_INVALID_PARAM = 400; +const int ERR_FAILEDSENDMSG = -220044; +const int ERR_JSON_TO_DATA_FAIL = -300012; + +// -3 01 xxx for zk +const int ERR_ZK_LIST_SAME_BUFFER = -301001; +const int ERR_GET_ZK_HANDLER_FAIL = -301002; +const int ERR_ZK_CONNECTION_LOSS = -301003; +const int ERR_ZK_EVENTLOOP_TIMEOUT = -301004; + +// -3 02 xxx for serviceList +const int ERR_REGIST_SERVICE_ZK_FAIL = -302001; +const int ERR_NODE_LOST = -302002; + +const int MAX_BUF_SIZE = 1024; +const int kZkContentSize = 1024; +const int32_t kMaxZkPathDepth = 8; + +const int THRIFT_TYPE = 0; +const int HTTP_TYPE = 1; + +#define SAFE_DELETE(p) { if (p) { delete (p); (p)=NULL; } } +#define SAFE_FREE(p) { if (p) { free(p); (p)=NULL; } } +#define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p); (p)=NULL; } } +#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } } + +#define SLEEP_FOR_SAFE_EXIT 1000*1000 +#define MILLISENCOND_COUNT_IN_SENCOND 1000 +#define SENCOND_COUNT_IN_MIN 60 +#define DEFAULT_ASYNC_PENDING_THRESHOLD 30 +#define WORKER_THREAD_POS_SECOND 60*5 +#define TEMP_BUFFER_LENGTH 256 +#define ZK_TIMEOUT_SENCOND 10 +#define ZK_DEFAULT_RETRY_TIMES 3 +#define ZK_DEFAULT_RETRY_SLEEP_US 50*1000 +#define MAX_ZK_THREADPOOL_NUM 20 +#define MIX_ZK_THREADPOOL_NUM 0 + +#define KD_RETRY_INTERVAL_SEC 10.0 + +#define DEFAULT_CONFIG_SERVER_APPKEY "com.company.newct" +#define DEFAULT_CONFIG_FRAMEWORK_VERSION "3.0.0" +#define DEFAULT_CONFIG_CLIENT_APPKEY "com.company.newct.client" + +#define DEFAULT_CONFIG_SERVER_PORT 16888 +#define DEFAULT_CONFIG_CONN_THREADNUM 4 +#define DEFAULT_CONFIG_WORK_THREADNUM 40 +#define DEFAULT_CONFIG_MAX_CONN_NUM 10000 +#define DEFAULT_CONFIG_SERVER_TIMEOUT 30 +#define DEFAULT_CONFIG_CONN_GC_TIME 600 + +#define CTHRIFT_LIKELY(x) (__builtin_expect(!!(x), 1)) +#define CTHRIFT_UNLIKELY(x) (__builtin_expect(!!(x), 0)) +#define BYTE unsigned char + +enum RegionType { + kRegionTypeOne, + kRegionTypeTwo, + kRegionTypeThree, +}; + +enum State { + kExpectFrameSize, + kExpectFrame +}; + +enum AsyncState { + kTaskStateInit = 0, + kTaskStateSuccess, + kTaskStateTimeOut, + kTaskStateTooMany +}; + +enum ErrorNum { + SUCCESS = 0, + ERR_EMPRY_CONFIG = 1, + ERR_WRONG_CONTENT = 2, + ERR_EMPTY_NS_ORIGIN =3, + ERR_EMPTY_ENV = 4, + ERR_CON_NOT_READY = 5, + ERR_NS_CON_NOT_READY = 6, + ERR_PARA_INVALID = 7, + ERR_INVALID_PORT = 8, + ERR_INVALID_TIMEOUT = 9, + ERR_INVALID_MAX_CONNNUM = 10, +}; + + +int16_t NumCPU(void); + +bool CheckDoubleEqual(const double &d1, const double &d2); + +void ReplaceAllDistinct + (const std::string &old_value, + const std::string &new_value, + std::string *p_str); + +bool CheckOverTime(const muduo::Timestamp ×tamp, const double +&d_overtime_secs, double *p_d_left_secs); + +bool ValidatePort(const unsigned int &port); + +int32_t GetStringLimit(); + +std::string StrToLower(const std::string &str_tmp); +} // namespace meituan_cthrift + +extern const int16_t kI16CpuNum; + +extern muduo::AtomicInt32 g_atomic_i32_seq_id; + +#endif // CTHRIFT_SRC_CTHRIFT_UTIL_CTHRIFT_COMMON_H_ + diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/util/cthrift_config.h b/sg_agent/thrid_party/cthrift/include/cthrift/util/cthrift_config.h new file mode 100644 index 0000000..019971e --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/util/cthrift_config.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef CTHRIFT_SRC_CTHRIFT_UTIL_CTHRIFT_CONFIG_H_ +#define CTHRIFT_SRC_CTHRIFT_UTIL_CTHRIFT_CONFIG_H_ + +#include + +namespace meituan_cthrift { + +class CthriftConfig { + public: + CthriftConfig(); + int LoadConfig(const bool client = false); + + public: + std::string ns_origin_; + std::string server_version_; + int listen_port_; + std::string server_appkey_; + std::string client_appkey_; + int server_work_threadnum_; + int server_conn_threadnum_; + int server_max_connnum_; + int server_timeout_; + int server_conn_gctime_; + bool server_register_; + bool mns_origin_; + std::string env_; +}; + +extern meituan_cthrift::CthriftConfig g_cthrift_config; +} // namespace meituan_cthrift + + + +#endif // CTHRIFT_SRC_CTHRIFT_UTIL_CTHRIFT_CONFIG_H_ diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/util/cthrift_mns_imp.h b/sg_agent/thrid_party/cthrift/include/cthrift/util/cthrift_mns_imp.h new file mode 100644 index 0000000..9ebf4e4 --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/util/cthrift_mns_imp.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +#ifndef CTHRIFT_SRC_CTHRIFT_UTIL_CTHRIFT_MNS_IMP_H_ +#define CTHRIFT_SRC_CTHRIFT_UTIL_CTHRIFT_MNS_IMP_H_ + +#include "cthrift_ns_interface.h" + +namespace meituan_cthrift { + +class CthriftMnsImp { + public: + CthriftMnsImp(); + int32_t Init(); + void Destroy(); + + virtual ~CthriftMnsImp(); + + int32_t GetSrvList(ServicePtr service, const int64_t rcv_watcher_time = -1); + + int32_t RegisterService(const meituan_mns::SGService &oservice, + meituan_mns::RegistCmd::type regCmd = meituan_mns::RegistCmd::REGIST, + int uptCmd = meituan_mns::UptCmd::RESET); + +}; + +extern meituan_cthrift::CthriftMnsImp g_cthrift_mns_default; + +} // namespace meituan_cthrift + + +#endif // CTHRIFT_SRC_CTHRIFT_UTIL_CTHRIFT_NS_IMP_H_ diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/util/cthrift_ns_imp.h b/sg_agent/thrid_party/cthrift/include/cthrift/util/cthrift_ns_imp.h new file mode 100644 index 0000000..a3b3061 --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/util/cthrift_ns_imp.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +#ifndef CTHRIFT_SRC_CTHRIFT_UTIL_CTHRIFT_NS_IMP_H_ +#define CTHRIFT_SRC_CTHRIFT_UTIL_CTHRIFT_NS_IMP_H_ + +#include "cthrift_ns_interface.h" + +namespace meituan_cthrift { + +class CthriftNsImp { + public: + CthriftNsImp(); + int32_t Init(); + void Destroy(); + + virtual ~CthriftNsImp(); + + int32_t GetSrvList(ServicePtr service, const int64_t rcv_watcher_time = -1); + + int32_t RegisterService(const meituan_mns::SGService &oservice, + meituan_mns::RegistCmd::type regCmd = meituan_mns::RegistCmd::REGIST, + int uptCmd = meituan_mns::UptCmd::RESET); + + private: + // 注册IP:PORT节点 + int32_t RegisterServiceNodeToZk(const meituan_mns::SGService &oservice, + meituan_mns::RegistCmd::type regCmd = meituan_mns::RegistCmd::REGIST, + int uptCmd = meituan_mns::UptCmd::RESET); + + int32_t EditServiceName(meituan_mns::SGService &, + const meituan_mns::SGService &, + int32_t); + + private: + const int retry_; + + ServiceZkClient *p_m_zk_client; +}; + +extern meituan_cthrift::CthriftNsImp g_cthrift_ns_default; + +} // namespace meituan_cthrift + + +#endif // CTHRIFT_SRC_CTHRIFT_UTIL_CTHRIFT_NS_IMP_H_ diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/util/cthrift_ns_interface.h b/sg_agent/thrid_party/cthrift/include/cthrift/util/cthrift_ns_interface.h new file mode 100644 index 0000000..0d13fa9 --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/util/cthrift_ns_interface.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +#ifndef CTHRIFT_SRC_CTHRIFT_UTIL_CTHRIFT_NS_INTERFACE_H_ +#define CTHRIFT_SRC_CTHRIFT_UTIL_CTHRIFT_NS_INTERFACE_H_ + +#include +#include +#include +#include + +#include +#include +#include + +#include "cthrift_common.h" +#include "cthrift_zk_client.h" +#include "log4cplus.h" + +namespace meituan_cthrift { + +typedef boost::shared_ptr ServicePtr; +typedef boost::function DestroyFunction; +typedef boost::function InitFunction; +typedef boost::function GetFunction; +typedef boost::function RegFunction; + +class CthriftNsInterface { + public: + void SetRegFunction(RegFunction reg) { + reg_ = reg; + } + + void SetInitFunction(InitFunction init) { + init_ = init; + } + + void SetDesFunction(DestroyFunction des) { + destroy_ = des; + } + + void SetGetFunction(GetFunction get) { + get_ = get; + } + + CthriftNsInterface() { + init_ = boost::bind(&CthriftNsInterface::OnInit, this); + destroy_ = boost::bind(&CthriftNsInterface::OnDestory, this); + reg_ = boost::bind(&CthriftNsInterface::OnRegisterService, + this, _1, _2, _3); + get_ = boost::bind(&CthriftNsInterface::OnGetSrvList, + this, _1, _2); + } + + virtual ~CthriftNsInterface() { + } + + int32_t Init() { + return init_(); + } + + void Destory() { + destroy_(); + } + + int32_t GetSrvList(ServicePtr service, + const int64_t rcv_watcher_time = -1) { + return get_(service, rcv_watcher_time); + } + + int32_t RegisterService(const meituan_mns::SGService &oservice, + meituan_mns::RegistCmd::type regCmd = meituan_mns::RegistCmd::REGIST, + int32_t uptCmd = meituan_mns::UptCmd::RESET) { + return reg_(oservice, regCmd, uptCmd); + } + + private: + int32_t OnRegisterService(const meituan_mns::SGService &oservice, + meituan_mns::RegistCmd::type regCmd, + int32_t uptCmd) { + CTHRIFT_LOG_WARN("OnRegisterService default."); + return -1; + } + + int32_t OnGetSrvList(ServicePtr service, const int64_t rcv_watcher_time) { + CTHRIFT_LOG_WARN("OnGetSrvList default."); + return -1; + } + + void OnDestory() { + CTHRIFT_LOG_WARN("OnDestory default."); + return; + } + + int32_t OnInit() { + CTHRIFT_LOG_WARN("OnInit default."); + return -1; + } + + DestroyFunction destroy_; + InitFunction init_; + RegFunction reg_; + GetFunction get_; +}; + +} // namespace meituan_cthrift + + +#endif // CTHRIFT_SRC_CTHRIFT_UTIL_CTHRIFT_NS_INTERFACE_H_ diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/util/cthrift_zk_client.h b/sg_agent/thrid_party/cthrift/include/cthrift/util/cthrift_zk_client.h new file mode 100644 index 0000000..1a36eb6 --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/util/cthrift_zk_client.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef CTHRIFT_SRC_UTIL_CTHRIFT_ZK_CLIENT_H_ +#define CTHRIFT_SRC_UTIL_CTHRIFT_ZK_CLIENT_H_ + + +#include "cthrift_common.h" +#include "zk_tools.h" + +namespace meituan_cthrift { + +class CthriftNsImp; + +class ServiceZkClient { + public: + explicit ServiceZkClient(CthriftNsImp *p); + ~ServiceZkClient(); + typedef boost::function + ThreadInitCallback; + + int GetSrvListByProtocol(std::vector *srvlist, + const std::string &localAppkey, + const std::string &appKey, + const std::string &protocol, + bool is_watcher_callback = false); + + // TODO(All service change watcher function) + static void ServiceByProtocolWatcher(zhandle_t *zh, int type, + int state, const char *path, + void *watcherCtx); + + private: + int GetSubSrvListFromZk( + boost::shared_ptr > > *srvlist, + ZkWGetChildrenInvokeParams *param, + const int &index, + const std::string &provider_path, + const std::string &remote_appkey + ); + + void MnsThreadPoolInit(); + void InitThreadPool(muduo::net::EventLoop *mns_loop, + int num_threads, const std::string &name); + void SetThreadInitCallback(const ThreadInitCallback &cb) { + threadInitCallback_ = cb; + } + void Init(void); + + private: + CthriftNsImp *plugin; + static muduo::net::EventLoopThread s_watcher_thread; + + ThreadInitCallback threadInitCallback_; + static muduo::net::EventLoopThreadPool *mns_zk_pool[]; + static muduo::net::EventLoop *mns_loop_pool[]; + static std::vector pool_watcher; +}; +} // namespace meituan_cthrift + +#endif + diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/util/log4cplus.h b/sg_agent/thrid_party/cthrift/include/cthrift/util/log4cplus.h new file mode 100644 index 0000000..888fcf5 --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/util/log4cplus.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef CTHRIFT_SRC_CTHRIFT_UTIL_LOG4CPLUS_H_ +#define CTHRIFT_SRC_CTHRIFT_UTIL_LOG4CPLUS_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace meituan_cthrift { + +using std::auto_ptr; +using log4cplus::Logger; +using log4cplus::ConsoleAppender; +using log4cplus::FileAppender; +using log4cplus::Appender; +using log4cplus::Layout; +using log4cplus::PatternLayout; +using log4cplus::helpers::SharedObjectPtr; + +extern Logger debug_instance; +extern Logger info_instance; +extern Logger warn_instance; +extern Logger error_instance; +extern Logger fatal_instance; +extern Logger stat_instance; + +#define CTHRIFT_LOG_DEBUG(debugContent) \ + { LOG4CPLUS_DEBUG(debug_instance, debugContent); } +#define CTHRIFT_LOG_INFO(infoContent) \ + { LOG4CPLUS_INFO(info_instance, infoContent); } +#define CTHRIFT_LOG_WARN(warnContent) \ + { LOG4CPLUS_WARN(warn_instance, warnContent); } +#define CTHRIFT_LOG_ERROR(errorContent) \ + { LOG4CPLUS_ERROR(error_instance, errorContent); } +#define CTHRIFT_LOG_FATAL(fatalContent) \ + { LOG4CPLUS_ERROR(fatal_instance, fatalContent); } +#define CTHRIFT_LOG_STAT(statContent) \ + { LOG4CPLUS_INFO(stat_instance, statContent); } +} // namespace meituan_cthrift + +#endif // CTHRIFT_SRC_CTHRIFT_UTIL_LOG4CPLUS_H_ diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/util/task_context.h b/sg_agent/thrid_party/cthrift/include/cthrift/util/task_context.h new file mode 100644 index 0000000..0d7f5df --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/util/task_context.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef CTHRIFT_SRC_CTHRIFT_UTIL_TASK_CONTEXT_H_ +#define CTHRIFT_SRC_CTHRIFT_UTIL_TASK_CONTEXT_H_ + +#include "cthrift_common.h" + +namespace meituan_cthrift { + +static const int64_t kSleepInterval = 2 * 1000; // us + +template +class TaskContext { + public: + explicit TaskContext(const Request &req) + : req_(req), result_ready_(false) {} + ~TaskContext() {} + + // 单位us + void WaitResult(int64_t timeout) { + int64_t time_spent = 0; + + while (true) { + if (result_ready_ || time_spent > timeout) { + break; + } + time_spent += kSleepInterval; + usleep(kSleepInterval); + } + } + + void set_response(const Response &rsp) { + rsp_ = rsp; + result_ready_ = true; + } + + const Request *get_request() const { + return &req_; + } + + const Response *get_response() const { + if (result_ready_) { + return &rsp_; + } + return NULL; + } + + private: + Request req_; + Response rsp_; + volatile bool result_ready_; +}; + +} // namespace meituan_cthrift + +#endif // CTHRIFT_SRC_CTHRIFT_UTIL_TASK_CONTEXT_H_ diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/util/zk_client.h b/sg_agent/thrid_party/cthrift/include/cthrift/util/zk_client.h new file mode 100644 index 0000000..e855e4c --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/util/zk_client.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef CTHRIFT_SRC_CTHRIFT_UTIL_ZK_CLIENT_H_ +#define CTHRIFT_SRC_CTHRIFT_UTIL_ZK_CLIENT_H_ + + +#include "task_context.h" +#include "zk_tools.h" + +namespace meituan_cthrift { + +class ZKNodeData{ + public: + ZKNodeData(const std::string path,const std::string data) + : data_value_(data), + data_path_(path) + { + } + + ZKNodeData & + operator=(const ZKNodeData &node) { + data_value_ = node.data_value_; + data_path_ = node.data_path_; + return *this; + } + ZKNodeData(const ZKNodeData &node) { + data_value_ = node.data_value_; + data_path_ = node.data_path_; + } + + + std::string data_value_; + std::string data_path_; +}; + +class ZkClient { + public: + typedef boost::shared_ptr > + ZkGetContextPtr; + typedef boost::shared_ptr > + ZkWGetContextPtr; + typedef boost::shared_ptr > + ZkWGetChildrenContextPtr; + typedef boost::shared_ptr > ZkConnContextPtr; + typedef boost::shared_ptr > + ZkCreateContextPtr; + typedef boost::shared_ptr > ZkSetContextPtr; + typedef boost::shared_ptr > + ZkExistsContextPtr; + typedef boost::function + ZkGetCallBack; + typedef boost::function ZkWGetCallBack; + typedef boost::function + ZkWGetChildrenCallBack; + typedef boost::function ZkCreateCallBack; + typedef boost::function ZkSetCallBack; + typedef boost::function ZkExistsCallBack; + typedef boost::function ThreadInitCallback; + + typedef boost::shared_ptr ZkExistsRequestPtr; + typedef boost::shared_ptr ZkCreateRequestPtr; + + ZkClient(); + ~ZkClient(); + + static ZkClient *GetInstance(); + static void Destroy(); + + int Init(const std::string &server, const bool &origin, + int timeout = 10000, int retry = 3); + + // connection watcher function + static void ConnWatcher(zhandle_t *zh, int type, int state, + const char *path, void *watcher_ctx); + + void SetTimeout(int timeout) { m_timeout = timeout; } + + void SetRetry(int retry) { m_retry = retry; } + + void OnReconnect(); + + void OnReCreate(); + + int ConnectToZk(); + + int CheckZk(); + + int RandSleep(); + + // ZK接口封装 + int ZkGet(meituan_cthrift::ZkGetInvokeParams *req); + int ZkWGet(meituan_cthrift::ZkWGetInvokeParams *req); + int ZkWGetChildren(meituan_cthrift::ZkWGetChildrenInvokeParams *req); + int ZkCreate(meituan_cthrift::ZkCreateInvokeParams *req); + int ZkSet(meituan_cthrift::ZkSetRequest *req); + int ZkExists(meituan_cthrift::ZkExistsRequest *req); + + private: + zhandle_t *m_zh; // zk handler + std::string m_server; // server ip list and port + int m_timeout; // timeout + int m_retry; // retry time + + unsigned int rand_try_times; + int timeout_; // eventloop timeout + + static ZkClient *mZkClient; + ThreadInitCallback threadInitCallback_; + + int ZkInit(); + int ZkClose(); + int ZkGet(const char *path, int watch, std::string *buffer, + int *buffer_len, struct Stat *stat); + int ZkWgetChildren(const char *path, watcher_fn watch, void *watcherCtx, + struct String_vector *strings); + int ZkWget(const char *path, + watcher_fn watch, + void *watcherCtx, + std::string *buffer, + int *buffer_len, + struct Stat *stat); + + int ZkPathCreateRecursivly(std::string zk_path); + + void SetThreadInitCallback(const ThreadInitCallback &cb) { + threadInitCallback_ = cb; + } + + void InitZkGetThreadPool(muduo::net::EventLoop *mns_loop, int num_threads, + const std::string &name); + void Init(void); + + ZkGetCallBack zk_get_cb_; + ZkWGetCallBack zk_wget_cb_; + ZkWGetChildrenCallBack zk_wget_children_cb_; + ZkCreateCallBack zk_create_cb_; + ZkSetCallBack zk_set_cb_; + ZkExistsCallBack zk_exists_cb_; + + int HandleZkGetReq(ZkGetContextPtr context, muduo::CountDownLatch *latcher); + int HandleZkWGetReq(ZkWGetContextPtr context); + int HandleZkWGetChildrenReq(ZkWGetChildrenContextPtr context); + int HandleZkCreateReq(ZkCreateContextPtr context); + int HandleZkSetReq(ZkSetContextPtr context); + int HandleZkExistsReq(ZkExistsContextPtr context); + muduo::net::EventLoopThread zk_loop_thread_; + muduo::net::EventLoopThread zk_get_loop_thread_; + muduo::net::EventLoop *zk_loop_; + static muduo::net::EventLoop *zk_get_loop_; + static muduo::net::EventLoopThreadPool *zk_get_pool; + std::vector pool_loops_; + std::map path_data_; +}; + +} // namespace meituan_cthrift +#endif // CTHRIFT_SRC_CTHRIFT_UTIL_ZK_CLIENT_H_ + diff --git a/sg_agent/thrid_party/cthrift/include/cthrift/util/zk_tools.h b/sg_agent/thrid_party/cthrift/include/cthrift/util/zk_tools.h new file mode 100644 index 0000000..8a5a9b2 --- /dev/null +++ b/sg_agent/thrid_party/cthrift/include/cthrift/util/zk_tools.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef CTHRIFT_SRC_CTHRIFT_UTIL_ZK_TOOLS_H_ +#define CTHRIFT_SRC_CTHRIFT_UTIL_ZK_TOOLS_H_ + +#include "cthrift_common.h" + +namespace meituan_cthrift { + +typedef struct ZkGetRequest { + int zk_index; + std::string path; + int watch; + ZkGetRequest() : zk_index(0), path(""), watch(0) {} +} ZkGetRequest; + +typedef struct ZkGetResponse { + std::string buffer; + int buffer_len; + struct Stat stat; + int err_code; +} ZkGetResponse; + +typedef struct ZkGetInvokeParams { + ZkGetRequest zk_get_request; + ZkGetResponse zk_get_response; +} ZkGetInvokeParams; + +typedef struct ZkWGetRequest { + std::string path; + watcher_fn watch; + void *watcherCtx; +} ZkWGetRequest; + +typedef struct ZkWGetResponse { + std::string buffer; + int buffer_len; + struct Stat stat; + int err_code; +} ZkWGetResponse; + +typedef struct ZkWGetInvokeParams { + ZkWGetRequest zk_wget_request; + ZkWGetResponse zk_wget_response; +} ZkWGetInvokeParams; + +typedef struct ZkWGetChildrenRequest { + std::string path; + watcher_fn watch; + void *watcherCtx; +} ZkWGetChildrenRequest; + +typedef struct ZkWGetChildrenResponse { + int err_code; + int count; + std::vector data; +} ZkWGetChildrenResponse; + +typedef struct ZkWGetChildrenInvokeParams { + ZkWGetChildrenRequest zk_wgetchildren_request; + ZkWGetChildrenResponse zk_wgetchildren_response; +} ZkWGetChildrenInvokeParams; + +typedef struct ZkCreateRequest { + std::string path; + std::string value; + bool ephemeral; + int value_len; +} ZkCreateRequest; + +typedef struct ZkCreateInvokeParams { + ZkCreateRequest zk_create_request; + int zk_create_response; +} ZkCreateInvokeParams; + +typedef struct ZkSetRequest { + std::string path; + std::string buffer; + int version; +} ZkSetRequest; + +typedef struct ZkExistsRequest { + std::string path; + int watch; +} ZkExistsRequest; + +enum ServiceNameType { + ZK_GET = 1, + ZK_WGET, + ZK_WGET_CHILDREN, +}; + +class ZkTools { + public: + static int InitZk(char *zk_host, int32_t timeout, bool retry); + + static int64_t DeltaTime(timeval end, timeval start); + + static int SplitStringIntoVector(const char *sContent, + const char *sDivider, + std::vector &vecStr); + + static int InvokeService(int service_name, void *service_params); + + static int GenRegisterZkPath(char (&zkPath)[MAX_BUF_SIZE], + const std::string &appkey, + const std::string &protocol, + const int serverType); + + static int GenProtocolZkPath(char (&zkPath)[MAX_BUF_SIZE], + const std::string &appkey, + const std::string &protocol, + const std::string &node_type); + + // 根据传入zkPath,解析出appkey, protocol + static int DeGenZkPath(const char *zkPath, std::string *appkey, + std::string *protocol); + + static int DeGenNodeType(std::string *protocol); + + static int Json2SGService(const std::string &strJson, + meituan_mns::SGService *oservice); + + static int SGService2Json(const meituan_mns::SGService &oservice, + std::string *strJson, const int env_int); + + static int ProviderNode2Json(const meituan_mns::CProviderNode &oprovider, + std::string *strJson); +}; +} // namespace meituan_cthrift + +#endif // CTHRIFT_SRC_CTHRIFT_UTIL_ZK_TOOLS_H_ diff --git a/sg_agent/thrid_party/cthrift/lib/libcthrift.a b/sg_agent/thrid_party/cthrift/lib/libcthrift.a new file mode 100644 index 0000000..589bccf Binary files /dev/null and b/sg_agent/thrid_party/cthrift/lib/libcthrift.a differ diff --git a/sg_agent/thrid_party/cthrift/lib/libcthrift.so b/sg_agent/thrid_party/cthrift/lib/libcthrift.so new file mode 100755 index 0000000..5051403 Binary files /dev/null and b/sg_agent/thrid_party/cthrift/lib/libcthrift.so differ diff --git a/sg_agent/thrid_party/cthrift/version b/sg_agent/thrid_party/cthrift/version new file mode 100644 index 0000000..914ec96 --- /dev/null +++ b/sg_agent/thrid_party/cthrift/version @@ -0,0 +1 @@ +2.6.0 \ No newline at end of file diff --git a/sg_agent/thrid_party/logs/include/appender.h b/sg_agent/thrid_party/logs/include/appender.h new file mode 100644 index 0000000..5eca94c --- /dev/null +++ b/sg_agent/thrid_party/logs/include/appender.h @@ -0,0 +1,289 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: appender.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_APPENDER_HEADER_ +#define LOG4CPLUS_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include + +#include + + +namespace log4cplus { + + + namespace helpers + { + + class Properties; + + } + + + /** + * This class is used to "handle" errors encountered in an {@link + * log4cplus::Appender}. + */ + class LOG4CPLUS_EXPORT ErrorHandler + { + public: + ErrorHandler (); + virtual ~ErrorHandler() = 0; + virtual void error(const log4cplus::tstring& err) = 0; + virtual void reset() = 0; + }; + + + class LOG4CPLUS_EXPORT OnlyOnceErrorHandler + : public ErrorHandler + { + public: + // Ctor + OnlyOnceErrorHandler(); + virtual ~OnlyOnceErrorHandler (); + virtual void error(const log4cplus::tstring& err); + virtual void reset(); + + private: + bool firstTime; + }; + + + /** + * Extend this class for implementing your own strategies for printing log + * statements. + * + *

Properties

+ *
+ * + *
layout
+ *
This property specifies message layout used by + * Appender. + * \sa Layout + *
+ * + *
filters
+ *
This property specifies possibly multiple filters used by + * Appender. Each of multple filters and its properties is under a + * numbered subkey of filters key. E.g.: + * filters.1=log4cplus::spi::LogLevelMatchFilter. Filter + * subkey numbers must be consecutive.
+ * + *
Threshold
+ *
This property specifies log level threshold. Events with + * lower log level than the threshold will not be logged by + * appender.
+ * + *
UseLockFile
+ *
Set this property to true if you want your output + * through this appender to be synchronized between multiple + * processes. When this property is set to true then log4cplus + * uses OS specific facilities (e.g., lockf()) to + * provide inter-process locking. With the exception of + * FileAppender and its derived classes, it is also necessary to + * provide path to a lock file using the LockFile + * property. + * \sa FileAppender + *
+ * + *
LockFile
+ *
This property specifies lock file, file used for + * inter-process synchronization of log file access. The property + * is only used when UseLockFile is set to true. Then it + * is mandatory. + * \sa FileAppender + *
+ *
+ */ + class LOG4CPLUS_EXPORT Appender + : public virtual log4cplus::helpers::SharedObject + { + public: + // Ctor + Appender(); + Appender(const log4cplus::helpers::Properties & properties); + + // Dtor + virtual ~Appender(); + + /** + * This function is for derived appenders to call from their + * destructors. All classes derived from `Appender` class + * _must_ call this function from their destructors. It + * ensures that appenders will get properly closed during + * shutdown by call to `close()` function before they are + * destroyed. + */ + void destructorImpl(); + + // Methods + /** + * Release any resources allocated within the appender such as file + * handles, network connections, etc. + * + * It is a programming error to append to a closed appender. + */ + virtual void close() = 0; + + /** + * Check if this appender is in closed state. + */ + bool isClosed() const; + + /** + * This method performs threshold checks and invokes filters before + * delegating actual logging to the subclasses specific {@link + * #append} method. + */ + void doAppend(const log4cplus::spi::InternalLoggingEvent& event); + + /** + * Get the name of this appender. The name uniquely identifies the + * appender. + */ + virtual log4cplus::tstring getName(); + + /** + * Set the name of this appender. The name is used by other + * components to identify this appender. + */ + virtual void setName(const log4cplus::tstring& name); + + /** + * Set the {@link ErrorHandler} for this Appender. + */ + virtual void setErrorHandler(std::auto_ptr eh); + + /** + * Return the currently set {@link ErrorHandler} for this + * Appender. + */ + virtual ErrorHandler* getErrorHandler(); + + /** + * Set the layout for this appender. Note that some appenders have + * their own (fixed) layouts or do not use one. For example, the + * SocketAppender ignores the layout set here. + */ + virtual void setLayout(std::auto_ptr layout); + + /** + * Returns the layout of this appender. The value may be NULL. + * + * This class owns the returned pointer. + */ + virtual Layout* getLayout(); + + /** + * Set the filter chain on this Appender. + */ + void setFilter(log4cplus::spi::FilterPtr f) { filter = f; } + + /** + * Get the filter chain on this Appender. + */ + log4cplus::spi::FilterPtr getFilter() const { return filter; } + + /** + * Returns this appenders threshold LogLevel. See the {@link + * #setThreshold} method for the meaning of this option. + */ + LogLevel getThreshold() const { return threshold; } + + /** + * Set the threshold LogLevel. All log events with lower LogLevel + * than the threshold LogLevel are ignored by the appender. + * + * In configuration files this option is specified by setting the + * value of the Threshold option to a LogLevel + * string, such as "DEBUG", "INFO" and so on. + */ + void setThreshold(LogLevel th) { threshold = th; } + + /** + * Check whether the message LogLevel is below the appender's + * threshold. If there is no threshold set, then the return value is + * always true. + */ + bool isAsSevereAsThreshold(LogLevel ll) const { + return ((ll != NOT_SET_LOG_LEVEL) && (ll >= threshold)); + } + + protected: + // Methods + /** + * Subclasses of Appender should implement this + * method to perform actual logging. + * @see doAppend method. + */ + virtual void append(const log4cplus::spi::InternalLoggingEvent& event) = 0; + + tstring & formatEvent (const log4cplus::spi::InternalLoggingEvent& event) const; + + // Data + /** The layout variable does not need to be set if the appender + * implementation has its own layout. */ + std::auto_ptr layout; + + /** Appenders are named. */ + log4cplus::tstring name; + + /** There is no LogLevel threshold filtering by default. */ + LogLevel threshold; + + /** The first filter in the filter chain. Set to null + * initially. */ + log4cplus::spi::FilterPtr filter; + + /** It is assumed and enforced that errorHandler is never null. */ + std::auto_ptr errorHandler; + + //! Optional system wide synchronization lock. + std::auto_ptr lockFile; + + //! Use lock file for inter-process synchronization of access + //! to log file. + bool useLockFile; + + /** Is this appender closed? */ + bool closed; + }; + + /** This is a pointer to an Appender. */ + typedef helpers::SharedObjectPtr SharedAppenderPtr; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_APPENDER_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/asyncappender.h b/sg_agent/thrid_party/logs/include/asyncappender.h new file mode 100644 index 0000000..af9d5e5 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/asyncappender.h @@ -0,0 +1,90 @@ +// -*- C++ -*- +// Module: Log4cplus +// File: asyncappender.h +// Created: 1/2009 +// Author: Vaclav Haisman +// +// +// Copyright (C) 2009-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// + +/** @file */ + +#ifndef LOG4CPLUS_ASYNCAPPENDER_H +#define LOG4CPLUS_ASYNCAPPENDER_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#ifndef LOG4CPLUS_SINGLE_THREADED + +#include +#include +#include +#include + + +namespace log4cplus +{ + + +class LOG4CPLUS_EXPORT AsyncAppender + : public Appender + , public helpers::AppenderAttachableImpl +{ +public: + AsyncAppender (SharedAppenderPtr const & app, unsigned max_len); + AsyncAppender (helpers::Properties const &); + virtual ~AsyncAppender (); + + virtual void close (); + +protected: + virtual void append (spi::InternalLoggingEvent const &); + + void init_queue_thread (unsigned); + + thread::AbstractThreadPtr queue_thread; + thread::QueuePtr queue; + +private: + AsyncAppender (AsyncAppender const &); + AsyncAppender & operator = (AsyncAppender const &); +}; + + +typedef helpers::SharedObjectPtr AsyncAppenderPtr; + + +} // namespace log4cplus + + +#endif // LOG4CPLUS_SINGLE_THREADED + +#endif // LOG4CPLUS_ASYNCAPPENDER_H diff --git a/sg_agent/thrid_party/logs/include/boost/deviceappender.hxx b/sg_agent/thrid_party/logs/include/boost/deviceappender.hxx new file mode 100644 index 0000000..e31fc79 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/boost/deviceappender.hxx @@ -0,0 +1,201 @@ +// Copyright (C) 2009-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_BOOST_DEVICEAPPENDER_HXX +#define LOG4CPLUS_BOOST_DEVICEAPPENDER_HXX + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include + + +namespace log4cplus +{ + + +namespace device_appender_detail +{ + + +template +struct device_type_traits +{ + typedef T & device_type; + + static + device_type + unwrap (device_type x) + { + return x; + } +}; + + +template +struct device_type_traits > +{ + typedef boost::shared_ptr device_type; + + static + T & + unwrap (device_type const & ptr) + { + return *ptr; + } +}; + + +} // namespace device_appender_detail + + +template +class DeviceAppender + : public Appender +{ +public: + typedef device_appender_detail::device_type_traits device_traits; + typedef typename device_traits::device_type device_type; + + template + DeviceAppender (D & d, bool close_device = true) + : device (d) + , close_flag (close_device) + { } + + template + DeviceAppender (boost::shared_ptr const & d, bool close_device = true) + : device (d) + , close_flag (close_device) + { } + + template + DeviceAppender (D & d, const helpers::Properties & props) + : Appender (props) + , device (d) + { + if (props.exists (LOG4CPLUS_TEXT ("CloseDevice"))) + close_flag = true; + else + close_flag = false; + } + + template + DeviceAppender (boost::shared_ptr const & d, + const helpers::Properties & props) + : Appender (props) + , device (d) + { + if (props.exists (LOG4CPLUS_TEXT ("CloseDevice"))) + close_flag = true; + else + close_flag = false; + } + + virtual + ~DeviceAppender () + { } + + virtual + void + close () + { + if (close_flag) + boost::iostreams::close (device_traits::unwrap (device)); + } + +protected: + virtual + void + append (log4cplus::spi::InternalLoggingEvent const & event) + { + tstring & str = formatEvent (event); + boost::iostreams::write (device_traits::unwrap (device), + str.c_str (), str.size ()); + } + + device_type device; + bool close_flag; + +private: + DeviceAppender (DeviceAppender const &); + DeviceAppender & operator = (DeviceAppender const &); +}; + + +template +inline +SharedAppenderPtr +make_device_appender (T & d, bool close_device = true) +{ + SharedAppenderPtr app (new DeviceAppender (d, close_device)); + return app; +} + + +template +inline +SharedAppenderPtr +make_device_appender (T & d, const helpers::Properties & props) +{ + SharedAppenderPtr app (new DeviceAppender (d, props)); + return app; +} + + +template +inline +SharedAppenderPtr +make_device_appender_sp (boost::shared_ptr const & p, + bool close_device = true) +{ + SharedAppenderPtr app ( + new DeviceAppender > (p, close_device)); + return app; +} + + +template +inline +SharedAppenderPtr +make_device_appender_sp (boost::shared_ptr const & p, + const helpers::Properties & props) +{ + SharedAppenderPtr app ( + new DeviceAppender > (p, props)); + return app; +} + + +} // namespace log4cplus + + +#endif // LOG4CPLUS_BOOST_DEVICEAPPENDER_HXX diff --git a/sg_agent/thrid_party/logs/include/clfsappender.h b/sg_agent/thrid_party/logs/include/clfsappender.h new file mode 100644 index 0000000..ca46b69 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/clfsappender.h @@ -0,0 +1,98 @@ +// -*- C++ -*- +// Module: Log4cplus +// File: clfsappender.h +// Created: 5/2012 +// Author: Vaclav Zeman +// +// +// Copyright (C) 2012-2013, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// + +/** @file */ + +#ifndef LOG4CPLUS_CLFSAPPENDER_H +#define LOG4CPLUS_CLFSAPPENDER_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + + +#if defined (LOG4CPLUS_CLFSAPPENDER_BUILD_DLL) +# if defined (INSIDE_LOG4CPLUS_CLFSAPPENDER) +# define LOG4CPLUS_CLFSAPPENDER_EXPORT __declspec(dllexport) +# else +# define LOG4CPLUS_CLFSAPPENDER_EXPORT __declspec(dllimport) +# endif +#else +# define LOG4CPLUS_CLFSAPPENDER_EXPORT +#endif + + +namespace log4cplus +{ + + +class LOG4CPLUS_CLFSAPPENDER_EXPORT CLFSAppender + : public Appender +{ +public: + CLFSAppender (tstring const & logname, unsigned long logsize, + unsigned long buffersize); + explicit CLFSAppender (helpers::Properties const &); + virtual ~CLFSAppender (); + + virtual void close (); + + static void registerAppender (); + +protected: + virtual void append (spi::InternalLoggingEvent const &); + + void init (tstring const & logname, unsigned long logsize, + unsigned long buffersize); + + struct Data; + + Data * data; + +private: + CLFSAppender (CLFSAppender const &); + CLFSAppender & operator = (CLFSAppender const &); +}; + + +typedef helpers::SharedObjectPtr CLFSAppenderPtr; + + +} // namespace log4cplus + + +#endif // LOG4CPLUS_CLFSAPPENDER_H diff --git a/sg_agent/thrid_party/logs/include/clogger.h b/sg_agent/thrid_party/logs/include/clogger.h new file mode 100644 index 0000000..a340d1b --- /dev/null +++ b/sg_agent/thrid_party/logs/include/clogger.h @@ -0,0 +1,85 @@ +// -*- C -*- +/** + * Module: Log4CPLUS + * File: clogger.h + * Created: 01/2011 + * Author: Jens Rehsack + * + * + * Copyright 2011-2013 Jens Rehsack & Tad E. Smith + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * This header defines the C API for log4cplus and the logging macros. */ + +#ifndef LOG4CPLUS_CLOGGERHEADER_ +#define LOG4CPLUS_CLOGGERHEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + + +#ifdef __cplusplus +extern "C" +{ +#endif + +// TODO UNICDE capable + +typedef void *logger_t; +typedef int loglevel_t; + +#define L4CP_OFF_LOG_LEVEL 60000 +#define L4CP_FATAL_LOG_LEVEL 50000 +#define L4CP_ERROR_LOG_LEVEL 40000 +#define L4CP_WARN_LOG_LEVEL 30000 +#define L4CP_INFO_LOG_LEVEL 20000 +#define L4CP_DEBUG_LOG_LEVEL 10000 +#define L4CP_TRACE_LOG_LEVEL 0 +#define L4CP_ALL_LOG_LEVEL TRACE_LOG_LEVEL +#define L4CP_NOT_SET_LOG_LEVEL -1 + +#ifdef UNICODE +# define LOG4CPLUS_TEXT2(STRING) L##STRING +typedef wchar_t log4cplus_char_t; +#else +# define LOG4CPLUS_TEXT2(STRING) STRING +typedef char log4cplus_char_t; +#endif // UNICODE +#define LOG4CPLUS_TEXT(STRING) LOG4CPLUS_TEXT2(STRING) + +LOG4CPLUS_EXPORT int log4cplus_file_configure(const log4cplus_char_t *pathname); +LOG4CPLUS_EXPORT int log4cplus_str_configure(const log4cplus_char_t *config); +LOG4CPLUS_EXPORT int log4cplus_basic_configure(void); +LOG4CPLUS_EXPORT void log4cplus_shutdown(void); + +LOG4CPLUS_EXPORT int log4cplus_logger_exists(const log4cplus_char_t *name); +LOG4CPLUS_EXPORT int log4cplus_logger_is_enabled_for( + const log4cplus_char_t *name, loglevel_t ll); +LOG4CPLUS_EXPORT int log4cplus_logger_log(const log4cplus_char_t *name, + loglevel_t ll, const log4cplus_char_t *msgfmt, ...) + LOG4CPLUS_FORMAT_ATTRIBUTE (__printf__, 3, 4); +LOG4CPLUS_EXPORT int log4cplus_logger_force_log(const log4cplus_char_t *name, + loglevel_t ll, const log4cplus_char_t *msgfmt, ...) + LOG4CPLUS_FORMAT_ATTRIBUTE (__printf__, 3, 4); + +#ifdef __cplusplus +} +#endif + +#endif /*?LOG4CPLUS_CLOGGERHEADER_*/ diff --git a/sg_agent/thrid_party/logs/include/config.h b/sg_agent/thrid_party/logs/include/config.h new file mode 100644 index 0000000..a7f3eb7 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/config.h @@ -0,0 +1,498 @@ +/* include/log4cplus/config.h. Generated from config.h.in by configure. */ +/* include/log4cplus/config.h.in. Generated from configure.ac by autoheader. */ + +#ifndef LOG4CPLUS_CONFIG_H + +#define LOG4CPLUS_CONFIG_H + +/* Defined if the compiler supports C99 style variadic macros with + __VA_ARGS__. */ +/* #undef HAS_C99_VARIADIC_MACROS */ + +/* Defined if the compiler supports GNU style variadic macros. */ +/* #undef HAS_GNU_VARIADIC_MACROS */ + +/* Define to 1 if you have the `clock_gettime' function. */ +#define HAVE_CLOCK_GETTIME 1 + +/* Define to 1 if you have the `clock_nanosleep' function. */ +#define HAVE_CLOCK_NANOSLEEP 1 + +/* Defined if the compiler provides C++11 header and increment, + decrement operations. */ +/* #undef HAVE_CXX11_ATOMICS */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `fcntl' function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have the `flock' function. */ +#define HAVE_FLOCK 1 + +/* Define to 1 if you have the `ftime' function. */ +#define HAVE_FTIME 1 + +/* Define to 1 if the system has the `constructor' function attribute */ +#define HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR 1 + +/* */ +#define HAVE_GETADDRINFO 1 + +/* */ +#define HAVE_GETHOSTBYNAME_R 1 + +/* Define to 1 if you have the `getpid' function. */ +#define HAVE_GETPID 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `gmtime_r' function. */ +#define HAVE_GMTIME_R 1 + +/* Define to 1 if you have the `htonl' function. */ +#define HAVE_HTONL 1 + +/* Define to 1 if you have the `htons' function. */ +#define HAVE_HTONS 1 + +/* Define to 1 if you have the `iconv' function. */ +/* #undef HAVE_ICONV */ + +/* Define to 1 if you have the `iconv_close' function. */ +/* #undef HAVE_ICONV_CLOSE */ + +/* Define to 1 if you have the `iconv_open' function. */ +/* #undef HAVE_ICONV_OPEN */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `advapi32' library (-ladvapi32). */ +/* #undef HAVE_LIBADVAPI32 */ + +/* Define to 1 if you have the `libiconv' function. */ +/* #undef HAVE_LIBICONV */ + +/* Define to 1 if you have the `libiconv_close' function. */ +/* #undef HAVE_LIBICONV_CLOSE */ + +/* Define to 1 if you have the `libiconv_open' function. */ +/* #undef HAVE_LIBICONV_OPEN */ + +/* Define to 1 if you have the `kernel32' library (-lkernel32). */ +/* #undef HAVE_LIBKERNEL32 */ + +/* Define to 1 if you have the `ws2_32' library (-lws2_32). */ +/* #undef HAVE_LIBWS2_32 */ + +/* Define to 1 if you have the `localtime_r' function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if you have the `lockf' function. */ +#define HAVE_LOCKF 1 + +/* Define to 1 if you have the `lstat' function. */ +#define HAVE_LSTAT 1 + +/* Define to 1 if you have the `mbstowcs' function. */ +#define HAVE_MBSTOWCS 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `nanosleep' function. */ +#define HAVE_NANOSLEEP 1 + +/* Define to 1 if you have the `ntohl' function. */ +#define HAVE_NTOHL 1 + +/* Define to 1 if you have the `ntohs' function. */ +#define HAVE_NTOHS 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have the `pipe2' function. */ +#define HAVE_PIPE2 1 + +/* Define to 1 if you have the `poll' function. */ +#define HAVE_POLL 1 + +/* Define if you have POSIX threads libraries and header files. */ +#define HAVE_PTHREAD 1 + +/* Have PTHREAD_PRIO_INHERIT. */ +#define HAVE_PTHREAD_PRIO_INHERIT 1 + +/* Define to 1 if you have the `shutdown' function. */ +#define HAVE_SHUTDOWN 1 + +/* Define to 1 if you have the `stat' function. */ +#define HAVE_STAT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Defined if the compiler understands __thread or __declspec(thread) + construct. */ +#define HAVE_TLS_SUPPORT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if the system has the `init_priority' variable attribute */ +#define HAVE_VAR_ATTRIBUTE_INIT_PRIORITY 1 + +/* Define to 1 if you have the `vfprintf_s' function. */ +/* #undef HAVE_VFPRINTF_S */ + +/* Define to 1 if you have the `vfwprintf_s' function. */ +/* #undef HAVE_VFWPRINTF_S */ + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the `vsnwprintf' function. */ +/* #undef HAVE_VSNWPRINTF */ + +/* Define to 1 if you have the `vsprintf_s' function. */ +/* #undef HAVE_VSPRINTF_S */ + +/* Define to 1 if you have the `vswprintf_s' function. */ +/* #undef HAVE_VSWPRINTF_S */ + +/* Define to 1 if you have the `wcstombs' function. */ +#define HAVE_WCSTOMBS 1 + +/* Define to 1 if you have the `_vsnprintf_s' function. */ +/* #undef HAVE__VSNPRINTF_S */ + +/* Define to 1 if you have the `_vsnwprintf' function. */ +/* #undef HAVE__VSNWPRINTF */ + +/* Define to 1 if you have the `_vsnwprintf_s' function. */ +/* #undef HAVE__VSNWPRINTF_S */ + +/* Defined if the compiler supports __FUNCTION__ macro. */ +/* #undef HAVE___FUNCTION___MACRO */ + +/* Defined if the compiler supports __func__ symbol. */ +/* #undef HAVE___FUNC___SYMBOL */ + +/* Defined if the compiler supports __PRETTY_FUNCTION__ macro. */ +/* #undef HAVE___PRETTY_FUNCTION___MACRO */ + +/* Defined if the compiler provides __sync_add_and_fetch(). */ +#define HAVE___SYNC_ADD_AND_FETCH 1 + +/* Defined if the compiler provides __sync_sub_and_fetch(). */ +#define HAVE___SYNC_SUB_AND_FETCH 1 + +/* Defined for --enable-debugging builds. */ +/* #undef LOG4CPLUS_DEBUGGING */ + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) or __global construct. */ +#define LOG4CPLUS_DECLSPEC_EXPORT __attribute__ ((visibility("default"))) + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) or __global construct. */ +#define LOG4CPLUS_DECLSPEC_IMPORT __attribute__ ((visibility("default"))) + +/* Defined if the compiler understands __attribute__((visibility("hidden"))) + or __hidden construct. */ +#define LOG4CPLUS_DECLSPEC_PRIVATE __attribute__ ((visibility("hidden"))) + +/* */ +#define LOG4CPLUS_HAVE_ARPA_INET_H 1 + +/* */ +#define LOG4CPLUS_HAVE_C99_VARIADIC_MACROS 1 + +/* */ +#define LOG4CPLUS_HAVE_CLOCK_GETTIME 1 + +/* */ +#define LOG4CPLUS_HAVE_CLOCK_NANOSLEEP 1 + +/* */ +/* #undef LOG4CPLUS_HAVE_CXX11_ATOMICS */ + +/* */ +#define LOG4CPLUS_HAVE_ENAMETOOLONG 1 + +/* */ +#define LOG4CPLUS_HAVE_ERRNO_H 1 + +/* */ +#define LOG4CPLUS_HAVE_FCNTL 1 + +/* */ +#define LOG4CPLUS_HAVE_FCNTL_H 1 + +/* */ +#define LOG4CPLUS_HAVE_FLOCK 1 + +/* */ +#define LOG4CPLUS_HAVE_FTIME 1 + +/* */ +#define LOG4CPLUS_HAVE_FUNCTION_MACRO 1 + +/* */ +#define LOG4CPLUS_HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR 1 + +/* */ +#define LOG4CPLUS_HAVE_FUNC_SYMBOL 1 + +/* */ +#define LOG4CPLUS_HAVE_GETADDRINFO 1 + +/* */ +#define LOG4CPLUS_HAVE_GETHOSTBYNAME_R 1 + +/* */ +#define LOG4CPLUS_HAVE_GETPID 1 + +/* */ +#define LOG4CPLUS_HAVE_GETTID 1 + +/* */ +#define LOG4CPLUS_HAVE_GETTIMEOFDAY 1 + +/* */ +#define LOG4CPLUS_HAVE_GMTIME_R 1 + +/* */ +#define LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS 1 + +/* */ +#define LOG4CPLUS_HAVE_HTONL 1 + +/* */ +#define LOG4CPLUS_HAVE_HTONS 1 + +/* */ +/* #undef LOG4CPLUS_HAVE_ICONV */ + +/* */ +/* #undef LOG4CPLUS_HAVE_ICONV_CLOSE */ + +/* */ +/* #undef LOG4CPLUS_HAVE_ICONV_H */ + +/* */ +/* #undef LOG4CPLUS_HAVE_ICONV_OPEN */ + +/* */ +#define LOG4CPLUS_HAVE_LIMITS_H 1 + +/* */ +#define LOG4CPLUS_HAVE_LOCALTIME_R 1 + +/* */ +#define LOG4CPLUS_HAVE_LOCKF 1 + +/* */ +#define LOG4CPLUS_HAVE_LSTAT 1 + +/* */ +#define LOG4CPLUS_HAVE_MBSTOWCS 1 + +/* */ +#define LOG4CPLUS_HAVE_NANOSLEEP 1 + +/* */ +#define LOG4CPLUS_HAVE_NETDB_H 1 + +/* */ +#define LOG4CPLUS_HAVE_NETINET_IN_H 1 + +/* */ +#define LOG4CPLUS_HAVE_NETINET_TCP_H 1 + +/* */ +#define LOG4CPLUS_HAVE_NTOHL 1 + +/* */ +#define LOG4CPLUS_HAVE_NTOHS 1 + +/* */ +#define LOG4CPLUS_HAVE_PIPE 1 + +/* */ +#define LOG4CPLUS_HAVE_PIPE2 1 + +/* */ +#define LOG4CPLUS_HAVE_POLL 1 + +/* */ +#define LOG4CPLUS_HAVE_POLL_H 1 + +/* */ +#define LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO 1 + +/* */ +#define LOG4CPLUS_HAVE_SHUTDOWN 1 + +/* */ +#define LOG4CPLUS_HAVE_STAT 1 + +/* */ +#define LOG4CPLUS_HAVE_STDARG_H 1 + +/* */ +#define LOG4CPLUS_HAVE_STDIO_H 1 + +/* */ +#define LOG4CPLUS_HAVE_STDLIB_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYSLOG_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_FILE_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_SOCKET_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_STAT_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_SYSCALL_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_TIMEB_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_TIME_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_TYPES_H 1 + +/* */ +#define LOG4CPLUS_HAVE_TIME_H 1 + +/* */ +#define LOG4CPLUS_HAVE_TLS_SUPPORT 1 + +/* */ +#define LOG4CPLUS_HAVE_UNISTD_H 1 + +/* */ +#define LOG4CPLUS_HAVE_VAR_ATTRIBUTE_INIT_PRIORITY 1 + +/* */ +/* #undef LOG4CPLUS_HAVE_VFPRINTF_S */ + +/* */ +/* #undef LOG4CPLUS_HAVE_VFWPRINTF_S */ + +/* */ +#define LOG4CPLUS_HAVE_VSNPRINTF 1 + +/* */ +/* #undef LOG4CPLUS_HAVE_VSNWPRINTF */ + +/* */ +/* #undef LOG4CPLUS_HAVE_VSPRINTF_S */ + +/* */ +/* #undef LOG4CPLUS_HAVE_VSWPRINTF_S */ + +/* */ +#define LOG4CPLUS_HAVE_WCHAR_H 1 + +/* */ +#define LOG4CPLUS_HAVE_WCSTOMBS 1 + +/* */ +/* #undef LOG4CPLUS_HAVE__VSNPRINTF_S */ + +/* */ +/* #undef LOG4CPLUS_HAVE__VSNWPRINTF */ + +/* */ +/* #undef LOG4CPLUS_HAVE__VSNWPRINTF_S */ + +/* */ +#define LOG4CPLUS_HAVE___SYNC_ADD_AND_FETCH 1 + +/* */ +#define LOG4CPLUS_HAVE___SYNC_SUB_AND_FETCH 1 + +/* Define if this is a single-threaded library. */ +/* #undef LOG4CPLUS_SINGLE_THREADED */ + +/* */ +#define LOG4CPLUS_THREAD_LOCAL_VAR __thread + +/* */ +/* #undef LOG4CPLUS_USE_PTHREADS */ + +/* Define when iconv() is available. */ +/* #undef LOG4CPLUS_WITH_ICONV */ + +/* Define for C99 compilers/standard libraries that support more than just the + "C" locale. */ +/* #undef LOG4CPLUS_WORKING_C_LOCALE */ + +/* Define for compilers/standard libraries that support more than just the "C" + locale. */ +/* #undef LOG4CPLUS_WORKING_LOCALE */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "log4cplus" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "log4cplus 1.1.3" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "log4cplus" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.1.3" + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +/* #undef PTHREAD_CREATE_JOINABLE */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Defined to the actual TLS support construct. */ +#define TLS_SUPPORT_CONSTRUCT __thread + +/* Substitute for socklen_t */ +/* #undef socklen_t */ + +#endif // LOG4CPLUS_CONFIG_H diff --git a/sg_agent/thrid_party/logs/include/config.h.cmake.in b/sg_agent/thrid_party/logs/include/config.h.cmake.in new file mode 100644 index 0000000..3ba79af --- /dev/null +++ b/sg_agent/thrid_party/logs/include/config.h.cmake.in @@ -0,0 +1,347 @@ +/* include/log4cplus/config.h.in. Generated from configure.in by autoheader. */ + +#ifndef LOG4CPLUS_CONFIG_H + +#define LOG4CPLUS_CONFIG_H + +/* Defined if the compiler supports C99 style variadic macros with + __VA_ARGS__. */ +/* #undef HAS_C99_VARIADIC_MACROS */ + +/* Defined if the compiler supports GNU style variadic macros. */ +/* #undef HAS_GNU_VARIADIC_MACROS */ + +/* Define to 1 if you have the `clock_gettime' function. */ +#undef HAVE_CLOCK_GETTIME + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ftime' function. */ +#cmakedefine HAVE_FTIME 1 + +/* */ +#cmakedefine HAVE_GETADDRINFO 1 + +/* */ +#cmakedefine HAVE_GETHOSTBYNAME_R 1 + +/* Define to 1 if you have the `getpid' function. */ +#cmakedefine HAVE_GETPID 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#cmakedefine HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `gmtime_r' function. */ +#cmakedefine HAVE_GMTIME_R 1 + +/* Define to 1 if you have the `htonl' function. */ +#cmakedefine HAVE_HTONL 1 + +/* Define to 1 if you have the `htons' function. */ +#cmakedefine HAVE_HTONS 1 + +/* Define to 1 if you have the `iconv' function. */ +#cmakedefine HAVE_ICONV 1 + +/* Define to 1 if you have the `iconv_close' function. */ +#cmakedefine HAVE_ICONV_CLOSE 1 + +/* Define to 1 if you have the `iconv_open' function. */ +#cmakedefine HAVE_ICONV_OPEN 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `advapi32' library (-ladvapi32). */ +#cmakedefine HAVE_LIBADVAPI32 1 + +/* Define to 1 if you have the `libiconv' function. */ +/* #undef HAVE_LIBICONV */ + +/* Define to 1 if you have the `libiconv_close' function. */ +/* #undef HAVE_LIBICONV_CLOSE */ + +/* Define to 1 if you have the `libiconv_open' function. */ +/* #undef HAVE_LIBICONV_OPEN */ + +/* Define to 1 if you have the `kernel32' library (-lkernel32). */ +#cmakedefine HAVE_LIBKERNEL32 1 + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +#cmakedefine HAVE_LIBNSL 1 + +/* Define to 1 if you have the `rt' library (-lrt). */ +#cmakedefine HAVE_LIBRT 1 + +/* Define to 1 if you have the `socket' library (-lsocket). */ +#cmakedefine HAVE_LIBSOCKET 1 + +/* Define to 1 if you have the `ws2_32' library (-lws2_32). */ +#cmakedefine HAVE_LIBWS2_32 1 + +/* Define to 1 if you have the `localtime_r' function. */ +#cmakedefine HAVE_LOCALTIME_R 1 + +/* Define to 1 if you have the `lstat' function. */ +#cmakedefine HAVE_LSTAT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `ntohl' function. */ +#cmakedefine HAVE_NTOHL 1 + +/* Define to 1 if you have the `ntohs' function. */ +#cmakedefine HAVE_NTOHS 1 + +/* Define if you have POSIX threads libraries and header files. */ +#undef HAVE_PTHREAD + +/* Define to 1 if you have the `stat' function. */ +#cmakedefine HAVE_STAT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vfprintf_s' function. */ +#cmakedefine HAVE_VFPRINTF_S 1 + +/* Define to 1 if you have the `vfwprintf_s' function. */ +#cmakedefine HAVE_VFWPRINTF_S 1 + +/* Define to 1 if you have the `vsnprintf' function. */ +#cmakedefine HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the `vsprintf_s' function. */ +#cmakedefine HAVE_VSPRINTF_S 1 + +/* Define to 1 if you have the `vswprintf_s' function. */ +#cmakedefine HAVE_VSWPRINTF_S 1 + +/* Define to 1 if you have the `_vsnprintf' function. */ +#cmakedefine HAVE__VSNPRINTF 1 + +/* Define to 1 if you have the `_vsnprintf_s' function. */ +#cmakedefine HAVE__VSNPRINTF_S 1 + +/* Define to 1 if you have the `_vsnwprintf_s' function. */ +#cmakedefine HAVE__VSNWPRINTF_S 1 + +/* Defined if the compiler supports __FUNCTION__ macro. */ +#cmakedefine HAVE___FUNCTION___MACRO 1 + +/* Defined if the compiler supports __PRETTY_FUNCTION__ macro. */ +#cmakedefine HAVE___PRETTY_FUNCTION___MACRO 1 + +/* Defined if the compiler provides __sync_add_and_fetch(). */ +#cmakedefine HAVE___SYNC_ADD_AND_FETCH 1 + +/* Defined if the compiler provides __sync_sub_and_fetch(). */ +#cmakedefine HAVE___SYNC_SUB_AND_FETCH 1 + +/* Defined for --enable-debugging builds. */ +#undef LOG4CPLUS_DEBUGGING + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) construct. */ +#define LOG4CPLUS_DECLSPEC_EXPORT @LOG4CPLUS_DECLSPEC_EXPORT@ + +/* Defined if the compiler understands __declspec(dllexport) or construct. */ +#define LOG4CPLUS_DECLSPEC_IMPORT @LOG4CPLUS_DECLSPEC_IMPORT@ /**/ + +/* */ +#cmakedefine LOG4CPLUS_HAVE_C99_VARIADIC_MACROS 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_CLOCK_GETTIME 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_ENAMETOOLONG 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_ERRNO_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_FTIME 1 + +/* */ +#define LOG4CPLUS_HAVE_FUNCTION_MACRO 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GETADDRINFO 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GETHOSTBYNAME_R 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GETPID 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GETTID 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GETTIMEOFDAY 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GMTIME_R 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_HTONL 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_HTONS 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_ICONV 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_ICONV_CLOSE 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_ICONV_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_ICONV_OPEN 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_LIMITS_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_LOCALTIME_R 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_LSTAT 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_NETDB_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_NETINET_IN_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_NETINET_TCP_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_NTOHL 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_NTOHS 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_STAT 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_STDARG_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_STDIO_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_STDLIB_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYSLOG_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYS_SOCKET_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYS_STAT_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYS_SYSCALL_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYS_TIMEB_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYS_TIME_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYS_TYPES_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_TIME_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_UNISTD_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_VFPRINTF_S 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_VFWPRINTF_S 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_VSNPRINTF 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_VSPRINTF_S 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_VSWPRINTF_S 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_WCHAR_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE__VSNPRINTF 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE__VSNPRINTF_S 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE__VSNWPRINTF_S 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE___SYNC_ADD_AND_FETCH 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE___SYNC_SUB_AND_FETCH 1 + +/* Define if this is a single-threaded library. */ +#undef LOG4CPLUS_SINGLE_THREADED + +/* */ +#undef LOG4CPLUS_USE_PTHREADS + +/* Define for compilers/standard libraries that support more than just the "C" + locale. */ +#undef LOG4CPLUS_WORKING_LOCALE + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +#undef PTHREAD_CREATE_JOINABLE + +/* Define to 1 if you have the ANSI C header files. Seems to be unused*/ +#cmakedefine STDC_HEADERS 1 + +/* Define to int if undefined. */ +#cmakedefine socklen_t int + +#endif // LOG4CPLUS_CONFIG_H diff --git a/sg_agent/thrid_party/logs/include/config.h.in b/sg_agent/thrid_party/logs/include/config.h.in new file mode 100644 index 0000000..1f2ef95 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/config.h.in @@ -0,0 +1,497 @@ +/* include/log4cplus/config.h.in. Generated from configure.ac by autoheader. */ + +#ifndef LOG4CPLUS_CONFIG_H + +#define LOG4CPLUS_CONFIG_H + +/* Defined if the compiler supports C99 style variadic macros with + __VA_ARGS__. */ +#undef HAS_C99_VARIADIC_MACROS + +/* Defined if the compiler supports GNU style variadic macros. */ +#undef HAS_GNU_VARIADIC_MACROS + +/* Define to 1 if you have the `clock_gettime' function. */ +#undef HAVE_CLOCK_GETTIME + +/* Define to 1 if you have the `clock_nanosleep' function. */ +#undef HAVE_CLOCK_NANOSLEEP + +/* Defined if the compiler provides C++11 header and increment, + decrement operations. */ +#undef HAVE_CXX11_ATOMICS + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the `fcntl' function. */ +#undef HAVE_FCNTL + +/* Define to 1 if you have the `flock' function. */ +#undef HAVE_FLOCK + +/* Define to 1 if you have the `ftime' function. */ +#undef HAVE_FTIME + +/* Define to 1 if the system has the `constructor' function attribute */ +#undef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR + +/* */ +#undef HAVE_GETADDRINFO + +/* */ +#undef HAVE_GETHOSTBYNAME_R + +/* Define to 1 if you have the `getpid' function. */ +#undef HAVE_GETPID + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the `gmtime_r' function. */ +#undef HAVE_GMTIME_R + +/* Define to 1 if you have the `htonl' function. */ +#undef HAVE_HTONL + +/* Define to 1 if you have the `htons' function. */ +#undef HAVE_HTONS + +/* Define to 1 if you have the `iconv' function. */ +#undef HAVE_ICONV + +/* Define to 1 if you have the `iconv_close' function. */ +#undef HAVE_ICONV_CLOSE + +/* Define to 1 if you have the `iconv_open' function. */ +#undef HAVE_ICONV_OPEN + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `advapi32' library (-ladvapi32). */ +#undef HAVE_LIBADVAPI32 + +/* Define to 1 if you have the `libiconv' function. */ +#undef HAVE_LIBICONV + +/* Define to 1 if you have the `libiconv_close' function. */ +#undef HAVE_LIBICONV_CLOSE + +/* Define to 1 if you have the `libiconv_open' function. */ +#undef HAVE_LIBICONV_OPEN + +/* Define to 1 if you have the `kernel32' library (-lkernel32). */ +#undef HAVE_LIBKERNEL32 + +/* Define to 1 if you have the `ws2_32' library (-lws2_32). */ +#undef HAVE_LIBWS2_32 + +/* Define to 1 if you have the `localtime_r' function. */ +#undef HAVE_LOCALTIME_R + +/* Define to 1 if you have the `lockf' function. */ +#undef HAVE_LOCKF + +/* Define to 1 if you have the `lstat' function. */ +#undef HAVE_LSTAT + +/* Define to 1 if you have the `mbstowcs' function. */ +#undef HAVE_MBSTOWCS + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `nanosleep' function. */ +#undef HAVE_NANOSLEEP + +/* Define to 1 if you have the `ntohl' function. */ +#undef HAVE_NTOHL + +/* Define to 1 if you have the `ntohs' function. */ +#undef HAVE_NTOHS + +/* Define to 1 if you have the `pipe' function. */ +#undef HAVE_PIPE + +/* Define to 1 if you have the `pipe2' function. */ +#undef HAVE_PIPE2 + +/* Define to 1 if you have the `poll' function. */ +#undef HAVE_POLL + +/* Define if you have POSIX threads libraries and header files. */ +#undef HAVE_PTHREAD + +/* Have PTHREAD_PRIO_INHERIT. */ +#undef HAVE_PTHREAD_PRIO_INHERIT + +/* Define to 1 if you have the `shutdown' function. */ +#undef HAVE_SHUTDOWN + +/* Define to 1 if you have the `stat' function. */ +#undef HAVE_STAT + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Defined if the compiler understands __thread or __declspec(thread) + construct. */ +#undef HAVE_TLS_SUPPORT + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if the system has the `init_priority' variable attribute */ +#undef HAVE_VAR_ATTRIBUTE_INIT_PRIORITY + +/* Define to 1 if you have the `vfprintf_s' function. */ +#undef HAVE_VFPRINTF_S + +/* Define to 1 if you have the `vfwprintf_s' function. */ +#undef HAVE_VFWPRINTF_S + +/* Define to 1 if you have the `vsnprintf' function. */ +#undef HAVE_VSNPRINTF + +/* Define to 1 if you have the `vsnwprintf' function. */ +#undef HAVE_VSNWPRINTF + +/* Define to 1 if you have the `vsprintf_s' function. */ +#undef HAVE_VSPRINTF_S + +/* Define to 1 if you have the `vswprintf_s' function. */ +#undef HAVE_VSWPRINTF_S + +/* Define to 1 if you have the `wcstombs' function. */ +#undef HAVE_WCSTOMBS + +/* Define to 1 if you have the `_vsnprintf_s' function. */ +#undef HAVE__VSNPRINTF_S + +/* Define to 1 if you have the `_vsnwprintf' function. */ +#undef HAVE__VSNWPRINTF + +/* Define to 1 if you have the `_vsnwprintf_s' function. */ +#undef HAVE__VSNWPRINTF_S + +/* Defined if the compiler supports __FUNCTION__ macro. */ +#undef HAVE___FUNCTION___MACRO + +/* Defined if the compiler supports __func__ symbol. */ +#undef HAVE___FUNC___SYMBOL + +/* Defined if the compiler supports __PRETTY_FUNCTION__ macro. */ +#undef HAVE___PRETTY_FUNCTION___MACRO + +/* Defined if the compiler provides __sync_add_and_fetch(). */ +#undef HAVE___SYNC_ADD_AND_FETCH + +/* Defined if the compiler provides __sync_sub_and_fetch(). */ +#undef HAVE___SYNC_SUB_AND_FETCH + +/* Defined for --enable-debugging builds. */ +#undef LOG4CPLUS_DEBUGGING + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) or __global construct. */ +#undef LOG4CPLUS_DECLSPEC_EXPORT + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) or __global construct. */ +#undef LOG4CPLUS_DECLSPEC_IMPORT + +/* Defined if the compiler understands __attribute__((visibility("hidden"))) + or __hidden construct. */ +#undef LOG4CPLUS_DECLSPEC_PRIVATE + +/* */ +#undef LOG4CPLUS_HAVE_ARPA_INET_H + +/* */ +#undef LOG4CPLUS_HAVE_C99_VARIADIC_MACROS + +/* */ +#undef LOG4CPLUS_HAVE_CLOCK_GETTIME + +/* */ +#undef LOG4CPLUS_HAVE_CLOCK_NANOSLEEP + +/* */ +#undef LOG4CPLUS_HAVE_CXX11_ATOMICS + +/* */ +#undef LOG4CPLUS_HAVE_ENAMETOOLONG + +/* */ +#undef LOG4CPLUS_HAVE_ERRNO_H + +/* */ +#undef LOG4CPLUS_HAVE_FCNTL + +/* */ +#undef LOG4CPLUS_HAVE_FCNTL_H + +/* */ +#undef LOG4CPLUS_HAVE_FLOCK + +/* */ +#undef LOG4CPLUS_HAVE_FTIME + +/* */ +#undef LOG4CPLUS_HAVE_FUNCTION_MACRO + +/* */ +#undef LOG4CPLUS_HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR + +/* */ +#undef LOG4CPLUS_HAVE_FUNC_SYMBOL + +/* */ +#undef LOG4CPLUS_HAVE_GETADDRINFO + +/* */ +#undef LOG4CPLUS_HAVE_GETHOSTBYNAME_R + +/* */ +#undef LOG4CPLUS_HAVE_GETPID + +/* */ +#undef LOG4CPLUS_HAVE_GETTID + +/* */ +#undef LOG4CPLUS_HAVE_GETTIMEOFDAY + +/* */ +#undef LOG4CPLUS_HAVE_GMTIME_R + +/* */ +#undef LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS + +/* */ +#undef LOG4CPLUS_HAVE_HTONL + +/* */ +#undef LOG4CPLUS_HAVE_HTONS + +/* */ +#undef LOG4CPLUS_HAVE_ICONV + +/* */ +#undef LOG4CPLUS_HAVE_ICONV_CLOSE + +/* */ +#undef LOG4CPLUS_HAVE_ICONV_H + +/* */ +#undef LOG4CPLUS_HAVE_ICONV_OPEN + +/* */ +#undef LOG4CPLUS_HAVE_LIMITS_H + +/* */ +#undef LOG4CPLUS_HAVE_LOCALTIME_R + +/* */ +#undef LOG4CPLUS_HAVE_LOCKF + +/* */ +#undef LOG4CPLUS_HAVE_LSTAT + +/* */ +#undef LOG4CPLUS_HAVE_MBSTOWCS + +/* */ +#undef LOG4CPLUS_HAVE_NANOSLEEP + +/* */ +#undef LOG4CPLUS_HAVE_NETDB_H + +/* */ +#undef LOG4CPLUS_HAVE_NETINET_IN_H + +/* */ +#undef LOG4CPLUS_HAVE_NETINET_TCP_H + +/* */ +#undef LOG4CPLUS_HAVE_NTOHL + +/* */ +#undef LOG4CPLUS_HAVE_NTOHS + +/* */ +#undef LOG4CPLUS_HAVE_PIPE + +/* */ +#undef LOG4CPLUS_HAVE_PIPE2 + +/* */ +#undef LOG4CPLUS_HAVE_POLL + +/* */ +#undef LOG4CPLUS_HAVE_POLL_H + +/* */ +#undef LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO + +/* */ +#undef LOG4CPLUS_HAVE_SHUTDOWN + +/* */ +#undef LOG4CPLUS_HAVE_STAT + +/* */ +#undef LOG4CPLUS_HAVE_STDARG_H + +/* */ +#undef LOG4CPLUS_HAVE_STDIO_H + +/* */ +#undef LOG4CPLUS_HAVE_STDLIB_H + +/* */ +#undef LOG4CPLUS_HAVE_SYSLOG_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_FILE_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_SOCKET_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_STAT_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_SYSCALL_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TIMEB_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TIME_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TYPES_H + +/* */ +#undef LOG4CPLUS_HAVE_TIME_H + +/* */ +#undef LOG4CPLUS_HAVE_TLS_SUPPORT + +/* */ +#undef LOG4CPLUS_HAVE_UNISTD_H + +/* */ +#undef LOG4CPLUS_HAVE_VAR_ATTRIBUTE_INIT_PRIORITY + +/* */ +#undef LOG4CPLUS_HAVE_VFPRINTF_S + +/* */ +#undef LOG4CPLUS_HAVE_VFWPRINTF_S + +/* */ +#undef LOG4CPLUS_HAVE_VSNPRINTF + +/* */ +#undef LOG4CPLUS_HAVE_VSNWPRINTF + +/* */ +#undef LOG4CPLUS_HAVE_VSPRINTF_S + +/* */ +#undef LOG4CPLUS_HAVE_VSWPRINTF_S + +/* */ +#undef LOG4CPLUS_HAVE_WCHAR_H + +/* */ +#undef LOG4CPLUS_HAVE_WCSTOMBS + +/* */ +#undef LOG4CPLUS_HAVE__VSNPRINTF_S + +/* */ +#undef LOG4CPLUS_HAVE__VSNWPRINTF + +/* */ +#undef LOG4CPLUS_HAVE__VSNWPRINTF_S + +/* */ +#undef LOG4CPLUS_HAVE___SYNC_ADD_AND_FETCH + +/* */ +#undef LOG4CPLUS_HAVE___SYNC_SUB_AND_FETCH + +/* Define if this is a single-threaded library. */ +#undef LOG4CPLUS_SINGLE_THREADED + +/* */ +#undef LOG4CPLUS_THREAD_LOCAL_VAR + +/* */ +#undef LOG4CPLUS_USE_PTHREADS + +/* Define when iconv() is available. */ +#undef LOG4CPLUS_WITH_ICONV + +/* Define for C99 compilers/standard libraries that support more than just the + "C" locale. */ +#undef LOG4CPLUS_WORKING_C_LOCALE + +/* Define for compilers/standard libraries that support more than just the "C" + locale. */ +#undef LOG4CPLUS_WORKING_LOCALE + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +#undef PTHREAD_CREATE_JOINABLE + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Defined to the actual TLS support construct. */ +#undef TLS_SUPPORT_CONSTRUCT + +/* Substitute for socklen_t */ +#undef socklen_t + +#endif // LOG4CPLUS_CONFIG_H diff --git a/sg_agent/thrid_party/logs/include/config.hxx b/sg_agent/thrid_party/logs/include/config.hxx new file mode 100644 index 0000000..608e762 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/config.hxx @@ -0,0 +1,182 @@ +// Copyright (C) 2009-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_CONFIG_HXX +#define LOG4CPLUS_CONFIG_HXX + +#if defined (_WIN32) +# include +#elif (defined(__MWERKS__) && defined(__MACOS__)) +# include +#else +# include +#endif + +#if ! defined (UNICODE) && ! defined (LOG4CPLUS_HAVE_VSNPRINTF_S) \ + && ! defined (LOG4CPLUS_HAVE__VSNPRINTF_S) \ + && ! defined (LOG4CPLUS_HAVE_VSNPRINTF) \ + && ! defined (LOG4CPLUS_HAVE__VSNPRINTF) +# undef LOG4CPLUS_USE_POOR_MANS_SNPRINTF +# define LOG4CPLUS_USE_POOR_MANS_SNPRINTF +#endif + +# if ! defined (LOG4CPLUS_WORKING_LOCALE) \ + && ! defined (LOG4CPLUS_WORKING_C_LOCALE) \ + && ! defined (LOG4CPLUS_WITH_ICONV) +# define LOG4CPLUS_POOR_MANS_CHCONV +#endif + +#ifndef LOG4CPLUS_DECLSPEC_EXPORT +#define LOG4CPLUS_DECLSPEC_EXPORT /* empty */ +#endif + +#ifndef LOG4CPLUS_DECLSPEC_IMPORT +#define LOG4CPLUS_DECLSPEC_IMPORT /* empty */ +#endif + +#ifndef LOG4CPLUS_DECLSPEC_PRIVATE +#define LOG4CPLUS_DECLSPEC_PRIVATE /* empty */ +#endif + +#define LOG4CPLUS_PRIVATE LOG4CPLUS_DECLSPEC_PRIVATE + +#if !defined(_WIN32) +# define LOG4CPLUS_USE_BSD_SOCKETS +# if !defined(LOG4CPLUS_SINGLE_THREADED) +# define LOG4CPLUS_USE_PTHREADS +# endif +# if defined (INSIDE_LOG4CPLUS) +# define LOG4CPLUS_EXPORT LOG4CPLUS_DECLSPEC_EXPORT +# else +# define LOG4CPLUS_EXPORT LOG4CPLUS_DECLSPEC_IMPORT +# endif // defined (INSIDE_LOG4CPLUS) + +#endif // !_WIN32 + +#if defined (LOG4CPLUS_INLINES_ARE_EXPORTED) \ + && defined (LOG4CPLUS_BUILD_DLL) +# define LOG4CPLUS_INLINE_EXPORT inline +#else +# define LOG4CPLUS_INLINE_EXPORT +#endif + +#if defined (UNICODE) +# if defined (_MSC_VER) && _MSC_VER >= 1400 +# define LOG4CPLUS_FSTREAM_ACCEPTS_WCHAR_T +# endif +# if defined (_MSC_VER) && _MSC_VER >= 1600 +# define LOG4CPLUS_HAVE_CODECVT_UTF8_FACET +# define LOG4CPLUS_HAVE_CODECVT_UTF16_FACET +# endif +#endif + +// C++11 stuff + +#if ! defined (__has_feature) +//! __has_feature(X) is Clangs way for testing features. +//! Define it to 0 if it does not exist. +# define __has_feature(X) 0 +#endif + +#if (defined (_MSC_VER) && _MSC_VER >= 1600) \ + || defined (__GXX_EXPERIMENTAL_CXX0X__) \ + || __cplusplus >= 201103L +# define LOG4CPLUS_HAVE_CXX11_SUPPORT +#endif + +#if defined (LOG4CPLUS_HAVE_CXX11_SUPPORT) \ + || __has_feature (cxx_rvalue_references) +# define LOG4CPLUS_HAVE_RVALUE_REFS +#endif + +#if ! defined (UNICODE) && defined (__GNUC__) && __GNUC__ >= 3 +# define LOG4CPLUS_FORMAT_ATTRIBUTE(archetype, format_index, first_arg_index) \ + __attribute__ ((format (archetype, format_index, first_arg_index))) +#else +# define LOG4CPLUS_FORMAT_ATTRIBUTE(archetype, fmt_index, first_arg_index) \ + /* empty */ +#endif + +#if defined (__GNUC__) && __GNUC__ >= 3 +# define LOG4CPLUS_ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) +# define LOG4CPLUS_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# define LOG4CPLUS_BUILTIN_EXPECT(exp, c) __builtin_expect ((exp), (c)) +#else +# if ! defined (LOG4CPLUS_ATTRIBUTE_NORETURN) +# define LOG4CPLUS_ATTRIBUTE_NORETURN /* empty */ +# endif +# define LOG4CPLUS_ATTRIBUTE_PURE /* empty */ +# define LOG4CPLUS_BUILTIN_EXPECT(exp, c) (exp) +#endif + +#define LOG4CPLUS_LIKELY(cond) LOG4CPLUS_BUILTIN_EXPECT(!! (cond), 1) +#define LOG4CPLUS_UNLIKELY(cond) LOG4CPLUS_BUILTIN_EXPECT(!! (cond), 0) + +#if defined (_MSC_VER) \ + || (defined (__BORLANDC__) && __BORLANDC__ >= 0x0650) \ + || (defined (__COMO__) && __COMO_VERSION__ >= 400) /* ??? */ \ + || (defined (__DMC__) && __DMC__ >= 0x700) /* ??? */ \ + || (defined (__clang__) && __clang_major__ >= 3) \ + || (defined (__GNUC__) && (__GNUC__ >= 4 \ + || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))) +# define LOG4CPLUS_HAVE_PRAGMA_ONCE +# pragma once +#endif + +#if defined (LOG4CPLUS_HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR) +# define LOG4CPLUS_CONSTRUCTOR_FUNC(prio) \ + __attribute__ ((__constructor__ ((prio)))) +#else +# define LOG4CPLUS_CONSTRUCTOR_FUNC(prio) /* empty */ +#endif + +#if defined (LOG4CPLUS_HAVE_VAR_ATTRIBUTE_INIT_PRIORITY) +# define LOG4CPLUS_INIT_PRIORITY(prio) \ + __attribute__ ((__init_priority__ ((prio)))) +#else +# define LOG4CPLUS_INIT_PRIORITY(prio) /* empty */ +#endif + +#define LOG4CPLUS_INIT_PRIORITY_BASE (65535 / 2) + +#include + +#if defined(__cplusplus) +namespace log4cplus +{ + +//! Per thread cleanup function. Users should call this function before +//! a thread ends its execution. It frees resources allocated in thread local +//! storage. It is important only for multi-threaded static library builds +//! of log4cplus and user threads. In all other cases the clean up is provided +//! automatically by other means. +LOG4CPLUS_EXPORT void threadCleanup (); + +//! Initializes log4cplus. +LOG4CPLUS_EXPORT void initialize (); + +} // namespace log4cplus + +#endif + +#endif // LOG4CPLUS_CONFIG_HXX diff --git a/sg_agent/thrid_party/logs/include/config/defines.hxx b/sg_agent/thrid_party/logs/include/config/defines.hxx new file mode 100644 index 0000000..b950678 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/config/defines.hxx @@ -0,0 +1,266 @@ +/* include/log4cplus/config/defines.hxx. Generated from defines.hxx.in by configure. */ +#ifndef LOG4CPLUS_CONFIG_DEFINES_HXX +#define LOG4CPLUS_CONFIG_DEFINES_HXX + +/* */ +#define LOG4CPLUS_HAVE_SYSLOG_H 1 + +/* */ +#define LOG4CPLUS_HAVE_ARPA_INET_H 1 + +/* */ +#define LOG4CPLUS_HAVE_NETINET_IN_H 1 + +/* */ +#define LOG4CPLUS_HAVE_NETINET_TCP_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_TIMEB_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_TIME_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_TYPES_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_STAT_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_SYSCALL_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_FILE_H 1 + +/* */ +#define LOG4CPLUS_HAVE_TIME_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_SOCKET_H 1 + +/* */ +#define LOG4CPLUS_HAVE_NETDB_H 1 + +/* */ +#define LOG4CPLUS_HAVE_UNISTD_H 1 + +/* */ +#define LOG4CPLUS_HAVE_FCNTL_H 1 + +/* */ +#define LOG4CPLUS_HAVE_STDARG_H 1 + +/* */ +#define LOG4CPLUS_HAVE_STDIO_H 1 + +/* */ +#define LOG4CPLUS_HAVE_STDLIB_H 1 + +/* */ +#define LOG4CPLUS_HAVE_ERRNO_H 1 + +/* */ +#define LOG4CPLUS_HAVE_WCHAR_H 1 + +/* */ +/* #undef LOG4CPLUS_HAVE_ICONV_H */ + +/* */ +#define LOG4CPLUS_HAVE_LIMITS_H 1 + +/* */ +#define LOG4CPLUS_HAVE_FTIME 1 + +/* */ +#define LOG4CPLUS_HAVE_GETADDRINFO 1 + +/* */ +#define LOG4CPLUS_HAVE_GETHOSTBYNAME_R 1 + +/* */ +#define LOG4CPLUS_HAVE_GETPID 1 + +/* */ +#define LOG4CPLUS_HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `clock_gettime' function. */ +#define LOG4CPLUS_HAVE_CLOCK_GETTIME 1 + +/* Define to 1 if you have the `nanosleep' function. */ +#define LOG4CPLUS_HAVE_NANOSLEEP 1 + +/* Define to 1 if you have the `clock_nanosleep' function. */ +#define LOG4CPLUS_HAVE_CLOCK_NANOSLEEP 1 + +/* */ +#define LOG4CPLUS_HAVE_GMTIME_R 1 + +/* */ +#define LOG4CPLUS_HAVE_HTONL 1 + +/* */ +#define LOG4CPLUS_HAVE_HTONS 1 + +/* */ +#define LOG4CPLUS_HAVE_LOCALTIME_R 1 + +/* */ +#define LOG4CPLUS_HAVE_LSTAT 1 + +/* */ +#define LOG4CPLUS_HAVE_FCNTL 1 + +/* */ +#define LOG4CPLUS_HAVE_LOCKF 1 + +/* */ +#define LOG4CPLUS_HAVE_FLOCK 1 + +/* */ +#define LOG4CPLUS_HAVE_NTOHL 1 + +/* */ +#define LOG4CPLUS_HAVE_NTOHS 1 + +/* Define to 1 if you have the `shutdown' function. */ +#define LOG4CPLUS_HAVE_SHUTDOWN 1 + +/* */ +#define LOG4CPLUS_HAVE_PIPE 1 + +/* */ +#define LOG4CPLUS_HAVE_PIPE2 1 + +/* */ +#define LOG4CPLUS_HAVE_POLL 1 + +/* */ +#define LOG4CPLUS_HAVE_POLL_H 1 + +/* */ +#define LOG4CPLUS_HAVE_STAT 1 + +/* Define if this is a single-threaded library. */ +/* #undef LOG4CPLUS_SINGLE_THREADED */ + +/* */ +/* #undef LOG4CPLUS_USE_PTHREADS */ + +/* Define for compilers/standard libraries that support more than just the "C" + locale. */ +/* #undef LOG4CPLUS_WORKING_LOCALE */ + +/* Define for C99 compilers/standard libraries that support more than just the + "C" locale. */ +/* #undef LOG4CPLUS_WORKING_C_LOCALE */ + +/* Define to int if undefined. */ +/* #undef socklen_t */ + +/* Defined for --enable-debugging builds. */ +/* #undef LOG4CPLUS_DEBUGGING */ + +/* Defined if the compiler understands __declspec(dllexport) or + __attribute__((visibility("default"))) construct. */ +#define LOG4CPLUS_DECLSPEC_EXPORT __attribute__ ((visibility("default"))) + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) construct. */ +#define LOG4CPLUS_DECLSPEC_IMPORT __attribute__ ((visibility("default"))) + +/* Defined if the compiler understands + __attribute__((visibility("hidden"))) construct. */ +#define LOG4CPLUS_DECLSPEC_PRIVATE __attribute__ ((visibility("hidden"))) + +/* */ +#define LOG4CPLUS_HAVE_TLS_SUPPORT 1 + +/* */ +#define LOG4CPLUS_THREAD_LOCAL_VAR __thread + +/* Defined if the host OS provides ENAMETOOLONG errno value. */ +#define LOG4CPLUS_HAVE_ENAMETOOLONG 1 + +/* Defined if the compiler provides __sync_add_and_fetch(). */ +#define LOG4CPLUS_HAVE___SYNC_ADD_AND_FETCH 1 + +/* Defined if the compiler provides __sync_sub_and_fetch(). */ +#define LOG4CPLUS_HAVE___SYNC_SUB_AND_FETCH 1 + +/* Defined if the compiler provides C++11 header and increment, + decrement operations. */ +/* #undef LOG4CPLUS_HAVE_CXX11_ATOMICS */ + +/* */ +#define LOG4CPLUS_HAVE_C99_VARIADIC_MACROS 1 + +/* */ +#define LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS 1 + +/* */ +#define LOG4CPLUS_HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the `vsnwprintf' function. */ +/* #undef LOG4CPLUS_HAVE_VSNWPRINTF */ + +/* Define to 1 if you have the `_vsnwprintf' function. */ +/* #undef LOG4CPLUS_HAVE__VSNWPRINTF */ + +/* */ +/* #undef LOG4CPLUS_HAVE__VSNPRINTF */ + +/* Define to 1 if you have the `vfprintf_s' function. */ +/* #undef LOG4CPLUS_HAVE_VFPRINTF_S */ + +/* Define to 1 if you have the `vfwprintf_s' function. */ +/* #undef LOG4CPLUS_HAVE_VFWPRINTF_S */ + +/* Define to 1 if you have the `vsprintf_s' function. */ +/* #undef LOG4CPLUS_HAVE_VSPRINTF_S */ + +/* Define to 1 if you have the `vswprintf_s' function. */ +/* #undef LOG4CPLUS_HAVE_VSWPRINTF_S */ + +/* Define to 1 if you have the `_vsnprintf_s' function. */ +/* #undef LOG4CPLUS_HAVE__VSNPRINTF_S */ + +/* Define to 1 if you have the `_vsnwprintf_s' function. */ +/* #undef LOG4CPLUS_HAVE__VSNWPRINTF_S */ + +/* Defined if the compiler supports __FUNCTION__ macro. */ +#define LOG4CPLUS_HAVE_FUNCTION_MACRO 1 + +/* Defined if the compiler supports __PRETTY_FUNCTION__ macro. */ +#define LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO 1 + +/* Defined if the compiler supports __func__ symbol. */ +#define LOG4CPLUS_HAVE_FUNC_SYMBOL 1 + +/* Define to 1 if you have the `mbstowcs' function. */ +#define LOG4CPLUS_HAVE_MBSTOWCS 1 + +/* Define to 1 if you have the `wcstombs' function. */ +#define LOG4CPLUS_HAVE_WCSTOMBS 1 + +/* Define to 1 if you have Linux style syscall(SYS_gettid). */ +#define LOG4CPLUS_HAVE_GETTID 1 + +/* Define when iconv() is available. */ +/* #undef LOG4CPLUS_WITH_ICONV */ + +/* Define to 1 if you have the `iconv' function. */ +/* #undef LOG4CPLUS_HAVE_ICONV */ + +/* Define to 1 if you have the `iconv_close' function. */ +/* #undef LOG4CPLUS_HAVE_ICONV_CLOSE */ + +/* Define to 1 if you have the `iconv_open' function. */ +/* #undef LOG4CPLUS_HAVE_ICONV_OPEN */ + +/* Define to 1 if the system has the `constructor' function attribute */ +#define LOG4CPLUS_HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR 1 + +/* Define to 1 if the system has the `init_priority' variable attribute */ +#define LOG4CPLUS_HAVE_VAR_ATTRIBUTE_INIT_PRIORITY 1 + +#endif // LOG4CPLUS_CONFIG_DEFINES_HXX diff --git a/sg_agent/thrid_party/logs/include/config/defines.hxx.in b/sg_agent/thrid_party/logs/include/config/defines.hxx.in new file mode 100644 index 0000000..2f4158e --- /dev/null +++ b/sg_agent/thrid_party/logs/include/config/defines.hxx.in @@ -0,0 +1,265 @@ +#ifndef LOG4CPLUS_CONFIG_DEFINES_HXX +#define LOG4CPLUS_CONFIG_DEFINES_HXX + +/* */ +#undef LOG4CPLUS_HAVE_SYSLOG_H + +/* */ +#undef LOG4CPLUS_HAVE_ARPA_INET_H + +/* */ +#undef LOG4CPLUS_HAVE_NETINET_IN_H + +/* */ +#undef LOG4CPLUS_HAVE_NETINET_TCP_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TIMEB_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TIME_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TYPES_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_STAT_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_SYSCALL_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_FILE_H + +/* */ +#undef LOG4CPLUS_HAVE_TIME_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_SOCKET_H + +/* */ +#undef LOG4CPLUS_HAVE_NETDB_H + +/* */ +#undef LOG4CPLUS_HAVE_UNISTD_H + +/* */ +#undef LOG4CPLUS_HAVE_FCNTL_H + +/* */ +#undef LOG4CPLUS_HAVE_STDARG_H + +/* */ +#undef LOG4CPLUS_HAVE_STDIO_H + +/* */ +#undef LOG4CPLUS_HAVE_STDLIB_H + +/* */ +#undef LOG4CPLUS_HAVE_ERRNO_H + +/* */ +#undef LOG4CPLUS_HAVE_WCHAR_H + +/* */ +#undef LOG4CPLUS_HAVE_ICONV_H + +/* */ +#undef LOG4CPLUS_HAVE_LIMITS_H + +/* */ +#undef LOG4CPLUS_HAVE_FTIME + +/* */ +#undef LOG4CPLUS_HAVE_GETADDRINFO + +/* */ +#undef LOG4CPLUS_HAVE_GETHOSTBYNAME_R + +/* */ +#undef LOG4CPLUS_HAVE_GETPID + +/* */ +#undef LOG4CPLUS_HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the `clock_gettime' function. */ +#undef LOG4CPLUS_HAVE_CLOCK_GETTIME + +/* Define to 1 if you have the `nanosleep' function. */ +#undef LOG4CPLUS_HAVE_NANOSLEEP + +/* Define to 1 if you have the `clock_nanosleep' function. */ +#undef LOG4CPLUS_HAVE_CLOCK_NANOSLEEP + +/* */ +#undef LOG4CPLUS_HAVE_GMTIME_R + +/* */ +#undef LOG4CPLUS_HAVE_HTONL + +/* */ +#undef LOG4CPLUS_HAVE_HTONS + +/* */ +#undef LOG4CPLUS_HAVE_LOCALTIME_R + +/* */ +#undef LOG4CPLUS_HAVE_LSTAT + +/* */ +#undef LOG4CPLUS_HAVE_FCNTL + +/* */ +#undef LOG4CPLUS_HAVE_LOCKF + +/* */ +#undef LOG4CPLUS_HAVE_FLOCK + +/* */ +#undef LOG4CPLUS_HAVE_NTOHL + +/* */ +#undef LOG4CPLUS_HAVE_NTOHS + +/* Define to 1 if you have the `shutdown' function. */ +#undef LOG4CPLUS_HAVE_SHUTDOWN + +/* */ +#undef LOG4CPLUS_HAVE_PIPE + +/* */ +#undef LOG4CPLUS_HAVE_PIPE2 + +/* */ +#undef LOG4CPLUS_HAVE_POLL + +/* */ +#undef LOG4CPLUS_HAVE_POLL_H + +/* */ +#undef LOG4CPLUS_HAVE_STAT + +/* Define if this is a single-threaded library. */ +#undef LOG4CPLUS_SINGLE_THREADED + +/* */ +#undef LOG4CPLUS_USE_PTHREADS + +/* Define for compilers/standard libraries that support more than just the "C" + locale. */ +#undef LOG4CPLUS_WORKING_LOCALE + +/* Define for C99 compilers/standard libraries that support more than just the + "C" locale. */ +#undef LOG4CPLUS_WORKING_C_LOCALE + +/* Define to int if undefined. */ +#undef socklen_t + +/* Defined for --enable-debugging builds. */ +#undef LOG4CPLUS_DEBUGGING + +/* Defined if the compiler understands __declspec(dllexport) or + __attribute__((visibility("default"))) construct. */ +#undef LOG4CPLUS_DECLSPEC_EXPORT + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) construct. */ +#undef LOG4CPLUS_DECLSPEC_IMPORT + +/* Defined if the compiler understands + __attribute__((visibility("hidden"))) construct. */ +#undef LOG4CPLUS_DECLSPEC_PRIVATE + +/* */ +#undef LOG4CPLUS_HAVE_TLS_SUPPORT + +/* */ +#undef LOG4CPLUS_THREAD_LOCAL_VAR + +/* Defined if the host OS provides ENAMETOOLONG errno value. */ +#undef LOG4CPLUS_HAVE_ENAMETOOLONG + +/* Defined if the compiler provides __sync_add_and_fetch(). */ +#undef LOG4CPLUS_HAVE___SYNC_ADD_AND_FETCH + +/* Defined if the compiler provides __sync_sub_and_fetch(). */ +#undef LOG4CPLUS_HAVE___SYNC_SUB_AND_FETCH + +/* Defined if the compiler provides C++11 header and increment, + decrement operations. */ +#undef LOG4CPLUS_HAVE_CXX11_ATOMICS + +/* */ +#undef LOG4CPLUS_HAVE_C99_VARIADIC_MACROS + +/* */ +#undef LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS + +/* */ +#undef LOG4CPLUS_HAVE_VSNPRINTF + +/* Define to 1 if you have the `vsnwprintf' function. */ +#undef LOG4CPLUS_HAVE_VSNWPRINTF + +/* Define to 1 if you have the `_vsnwprintf' function. */ +#undef LOG4CPLUS_HAVE__VSNWPRINTF + +/* */ +#undef LOG4CPLUS_HAVE__VSNPRINTF + +/* Define to 1 if you have the `vfprintf_s' function. */ +#undef LOG4CPLUS_HAVE_VFPRINTF_S + +/* Define to 1 if you have the `vfwprintf_s' function. */ +#undef LOG4CPLUS_HAVE_VFWPRINTF_S + +/* Define to 1 if you have the `vsprintf_s' function. */ +#undef LOG4CPLUS_HAVE_VSPRINTF_S + +/* Define to 1 if you have the `vswprintf_s' function. */ +#undef LOG4CPLUS_HAVE_VSWPRINTF_S + +/* Define to 1 if you have the `_vsnprintf_s' function. */ +#undef LOG4CPLUS_HAVE__VSNPRINTF_S + +/* Define to 1 if you have the `_vsnwprintf_s' function. */ +#undef LOG4CPLUS_HAVE__VSNWPRINTF_S + +/* Defined if the compiler supports __FUNCTION__ macro. */ +#undef LOG4CPLUS_HAVE_FUNCTION_MACRO + +/* Defined if the compiler supports __PRETTY_FUNCTION__ macro. */ +#undef LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO + +/* Defined if the compiler supports __func__ symbol. */ +#undef LOG4CPLUS_HAVE_FUNC_SYMBOL + +/* Define to 1 if you have the `mbstowcs' function. */ +#undef LOG4CPLUS_HAVE_MBSTOWCS + +/* Define to 1 if you have the `wcstombs' function. */ +#undef LOG4CPLUS_HAVE_WCSTOMBS + +/* Define to 1 if you have Linux style syscall(SYS_gettid). */ +#undef LOG4CPLUS_HAVE_GETTID + +/* Define when iconv() is available. */ +#undef LOG4CPLUS_WITH_ICONV + +/* Define to 1 if you have the `iconv' function. */ +#undef LOG4CPLUS_HAVE_ICONV + +/* Define to 1 if you have the `iconv_close' function. */ +#undef LOG4CPLUS_HAVE_ICONV_CLOSE + +/* Define to 1 if you have the `iconv_open' function. */ +#undef LOG4CPLUS_HAVE_ICONV_OPEN + +/* Define to 1 if the system has the `constructor' function attribute */ +#undef LOG4CPLUS_HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR + +/* Define to 1 if the system has the `init_priority' variable attribute */ +#undef LOG4CPLUS_HAVE_VAR_ATTRIBUTE_INIT_PRIORITY + +#endif // LOG4CPLUS_CONFIG_DEFINES_HXX diff --git a/sg_agent/thrid_party/logs/include/config/macosx.h b/sg_agent/thrid_party/logs/include/config/macosx.h new file mode 100644 index 0000000..448090c --- /dev/null +++ b/sg_agent/thrid_party/logs/include/config/macosx.h @@ -0,0 +1,37 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: config-macosx.h +// Created: 7/2003 +// Author: Christopher R. Bailey +// +// +// Copyright 2003-2013 Christopher R. Bailey +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_CONFIG_MACOSX_HEADER_ +#define LOG4CPLUS_CONFIG_MACOSX_HEADER_ + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if (defined(__APPLE__) || (defined(__MWERKS__) && defined(__MACOS__))) + +#define LOG4CPLUS_HAVE_GETTIMEOFDAY 1 +#define socklen_t int + +#endif // MACOSX +#endif // LOG4CPLUS_CONFIG_MACOSX_HEADER_ diff --git a/sg_agent/thrid_party/logs/include/config/stamp-h2 b/sg_agent/thrid_party/logs/include/config/stamp-h2 new file mode 100644 index 0000000..109f0fe --- /dev/null +++ b/sg_agent/thrid_party/logs/include/config/stamp-h2 @@ -0,0 +1 @@ +timestamp for include/log4cplus/config/defines.hxx diff --git a/sg_agent/thrid_party/logs/include/config/win32.h b/sg_agent/thrid_party/logs/include/config/win32.h new file mode 100644 index 0000000..2ade3b9 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/config/win32.h @@ -0,0 +1,210 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: config-win32.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_CONFIG_WIN32_HEADER_ +#define LOG4CPLUS_CONFIG_WIN32_HEADER_ + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (__MINGW32__) || defined (__MINGW64__) +# include <_mingw.h> +#endif + +#ifdef _WIN32 + +#if (defined (_MSC_VER) && _MSC_VER > 1400) \ + || (defined (__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR >= 3) +# define LOG4CPLUS_HAVE_INTRIN_H +#endif + +// Time related functions and headers. +#define LOG4CPLUS_HAVE_TIME_H +#define LOG4CPLUS_HAVE_SYS_TIMEB_H +#define LOG4CPLUS_HAVE_FTIME +#if defined (_MSC_VER) || defined (__BORLANDC__) +#define LOG4CPLUS_HAVE_GMTIME_S +#endif + +// Use Winsock on Windows. +#define LOG4CPLUS_USE_WINSOCK + +// Enable Win32DebugAppender +#define LOG4CPLUS_HAVE_OUTPUTDEBUGSTRING + +// Enable Win32ConsoleAppender. +#define LOG4CPLUS_HAVE_WIN32_CONSOLE + +#define LOG4CPLUS_HAVE_SYS_TYPES_H +#define LOG4CPLUS_HAVE_SYS_LOCKING_H +#define LOG4CPLUS_HAVE_FCNTL_H +#define LOG4CPLUS_HAVE_IO_H +#define LOG4CPLUS_HAVE_STDIO_H +#define LOG4CPLUS_HAVE_WCHAR_H +#define LOG4CPLUS_HAVE_STDARG_H +#define LOG4CPLUS_HAVE_STDLIB_H +#define LOG4CPLUS_HAVE_ERRNO_H +#define LOG4CPLUS_HAVE_SYS_STAT_H +#define LOG4CPLUS_HAVE_TIME_H +#define LOG4CPLUS_HAVE_STDLIB_H + +// MSVC has both and so does MinGW. +#define LOG4CPLUS_HAVE_VSNPRINTF +#define LOG4CPLUS_HAVE__VSNPRINTF +#define LOG4CPLUS_HAVE__VSNWPRINTF + +// Limit the use of foo_s() functions to builds using Visual Studio +// 2005 and its run time library. In MinGW land, limit the foo_s() +// functions to MinGw-w64 toolchain and __MSVCRT_VERSION__ >= 0x0900. +#if (defined (_MSC_VER) && _MSC_VER >= 1400) \ + || (defined (__MSVCRT_VERSION__) && __MSVCRT_VERSION__ >= 0x0900 \ + && defined (__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR >= 2) +// MS secure versions of vprintf(). +# define LOG4CPLUS_HAVE_VSPRINTF_S +# define LOG4CPLUS_HAVE_VSWPRINTF_S + +// MS secure versions of vfprintf(). +# define LOG4CPLUS_HAVE_VFPRINTF_S +# define LOG4CPLUS_HAVE_VFWPRINTF_S + +// MS secure versions of vsnprintf(). +# define LOG4CPLUS_HAVE_VSNPRINTF_S +# define LOG4CPLUS_HAVE__VSNPRINTF_S +# define LOG4CPLUS_HAVE__VSNWPRINTF_S + +// MS printf-like functions supporting positional parameters. +# define LOG4CPLUS_HAVE__VSPRINTF_P +# define LOG4CPLUS_HAVE__VSWPRINTF_P + +// MS secure version of _tsopen(). +# define LOG4CPLUS_HAVE__TSOPEN_S +#endif + +#define LOG4CPLUS_HAVE__TSOPEN + +#define LOG4CPLUS_DLLMAIN_HINSTANCE HINSTANCE +#define LOG4CPLUS_HAVE_NT_EVENT_LOG + +// log4cplus_EXPORTS is used by the CMake build system. DLL_EXPORT is +// used by the autotools build system. +#if (defined (log4cplus_EXPORTS) || defined (log4cplusU_EXPORTS) \ + || defined (DLL_EXPORT)) \ + && ! defined (LOG4CPLUS_STATIC) +# undef LOG4CPLUS_BUILD_DLL +# define LOG4CPLUS_BUILD_DLL +#endif + +#if ! defined (LOG4CPLUS_BUILD_DLL) +# undef LOG4CPLUS_STATIC +# define LOG4CPLUS_STATIC +#endif + +#if defined (LOG4CPLUS_STATIC) && defined (LOG4CPLUS_BUILD_DLL) +# error LOG4CPLUS_STATIC and LOG4CPLUS_BUILD_DLL cannot be defined both. +#endif + +#if defined (LOG4CPLUS_BUILD_DLL) +# if defined (INSIDE_LOG4CPLUS) +# define LOG4CPLUS_EXPORT __declspec(dllexport) +# else +# define LOG4CPLUS_EXPORT __declspec(dllimport) +# endif +#else +# define LOG4CPLUS_EXPORT +#endif + +#ifndef LOG4CPLUS_SINGLE_THREADED +# define LOG4CPLUS_USE_WIN32_THREADS +#endif + +#if defined (_WIN32_WINNT) && _WIN32_WINNT < 0x0600 +# define LOG4CPLUS_POOR_MANS_SHAREDMUTEX +#endif + +#if defined(_MSC_VER) + // Warning about: identifier was truncated to '255' characters in the debug information +# pragma warning( disable : 4786 ) + // Warning about: needs to have dll-interface to be used by clients of class +# pragma warning( disable : 4251 ) + +# define LOG4CPLUS_INLINES_ARE_EXPORTED + +# if _MSC_VER >= 1400 +# define LOG4CPLUS_WORKING_LOCALE +# define LOG4CPLUS_HAVE_FUNCTION_MACRO +# define LOG4CPLUS_HAVE_FUNCSIG_MACRO +# define LOG4CPLUS_HAVE_C99_VARIADIC_MACROS +# define LOG4CPLUS_ATTRIBUTE_NORETURN __declspec(noreturn) +# endif +# if _MSC_VER >= 1700 +# define LOG4CPLUS_HAVE_CXX11_ATOMICS +# endif +#endif + +#if defined (__GNUC__) +# undef LOG4CPLUS_INLINES_ARE_EXPORTED +# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) +# define LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO +# define LOG4CPLUS_HAVE_FUNC_SYMBOL +# endif +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) +# if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) +# define LOG4CPLUS_HAVE___SYNC_SUB_AND_FETCH +# define LOG4CPLUS_HAVE___SYNC_ADD_AND_FETCH +# endif +# endif +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) +# if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) +# define LOG4CPLUS_HAVE___ATOMIC_ADD_FETCH +# define LOG4CPLUS_HAVE___ATOMIC_SUB_FETCH +# endif +// This has worked for some versions of MinGW with GCC 4.7+ but it +// appears to be broken again in 4.8.x. Thus, we disable this for GCC +// completely forever. +// +//# define LOG4CPLUS_INLINES_ARE_EXPORTED +# endif +# define LOG4CPLUS_HAVE_FUNCTION_MACRO +# define LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS +# define LOG4CPLUS_HAVE_C99_VARIADIC_MACROS +# if defined (__MINGW32__) +# define LOG4CPLUS_WORKING_C_LOCALE +# endif +#endif + +#if defined (__BORLANDC__) && __BORLANDC__ >= 0x0650 +# define LOG4CPLUS_HAVE_FUNCTION_MACRO +# define LOG4CPLUS_HAVE_C99_VARIADIC_MACROS +#endif // __BORLANDC__ + +#if ! defined (LOG4CPLUS_DISABLE_DLL_RUNTIME_WARNING) +# if defined (LOG4CPLUS_STATIC) && defined (_MSC_VER) && ! defined (_DLL) +# pragma message("You are not using DLL C run time library. " \ + "You must call log4cplus::initialize() once before " \ + "you use any other log4cplus API.") +# endif +#endif + +#endif // _WIN32 +#endif // LOG4CPLUS_CONFIG_WIN32_HEADER_ diff --git a/sg_agent/thrid_party/logs/include/config/windowsh-inc.h b/sg_agent/thrid_party/logs/include/config/windowsh-inc.h new file mode 100644 index 0000000..b71a8e1 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/config/windowsh-inc.h @@ -0,0 +1,159 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: windowsh-inc.h +// Created: 4/2010 +// Author: Vaclav Zeman +// +// +// Copyright (C) 2010-2013, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// NOTE: This file is a fragment intentionally left without include guards. + +#if defined (_WIN32) +#undef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN + +#undef NOGDICAPMASKS +#define NOGDICAPMASKS + +#undef NOVIRTUALKEYCODES +#define NOVIRTUALKEYCODES + +#undef NOWINMESSAGES +#define NOWINMESSAGES + +#undef NOWINSTYLES +#define NOWINSTYLES + +#undef NOSYSMETRICS +#define NOSYSMETRICS + +#undef NOMENUS +#define NOMENUS + +#undef NOICONS +#define NOICONS + +#undef NOKEYSTATES +#define NOKEYSTATES + +#undef NOSYSCOMMANDS +#define NOSYSCOMMANDS + +#undef NORASTEROPS +#define NORASTEROPS + +#undef NOSHOWWINDOW +#define NOSHOWWINDOW + +#undef NOATOM +#define NOATOM + +#undef NOCLIPBOARD +#define NOCLIPBOARD + +#undef NOCOLOR +#define NOCOLOR + +#undef NOCTLMGR +#define NOCTLMGR + +#undef NODRAWTEXT +#define NODRAWTEXT + +#undef NOGDI +#define NOGDI + +#undef NOKERNEL +#define NOKERNEL + +#undef NOUSER +#define NOUSER + +#undef NONLS +#define NONLS + +#undef NOMB +#define NOMB + +#undef NOMEMMGR +#define NOMEMMGR + +#undef NOMETAFILE +#define NOMETAFILE + +#undef NOMINMAX +#define NOMINMAX + +#undef NOMSG +#define NOMSG + +#undef NOOPENFILE +#define NOOPENFILE + +#undef NOSCROLL +#define NOSCROLL + +#undef NOSERVICE +#define NOSERVICE + +#undef NOSOUND +#define NOSOUND + +#undef NOTEXTMETRIC +#define NOTEXTMETRIC + +#undef NOWH +#define NOWH + +#undef NOWINOFFSETS +#define NOWINOFFSETS + +#undef NOCOMM +#define NOCOMM + +#undef NOKANJI +#define NOKANJI + +#undef NOHELP +#define NOHELP + +#undef NOPROFILER +#define NOPROFILER + +#undef NODEFERWINDOWPOS +#define NODEFERWINDOWPOS + +#undef NOMCX +#define NOMCX + +#include +#include +#include +#if defined (LOG4CPLUS_HAVE_INTRIN_H) +#include +#endif +#endif + +// NOTE: This file is a fragment intentionally left without include guards. diff --git a/sg_agent/thrid_party/logs/include/configurator.h b/sg_agent/thrid_party/logs/include/configurator.h new file mode 100644 index 0000000..5cbb96f --- /dev/null +++ b/sg_agent/thrid_party/logs/include/configurator.h @@ -0,0 +1,374 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: configurator.h +// Created: 3/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_CONFIGURATOR_HEADER_ +#define LOG4CPLUS_CONFIGURATOR_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + +#include + + +namespace log4cplus +{ + class Hierarchy; + + + /** + * Provides configuration from an external file. See configure() for + * the expected format. + * + * All option values admit variable substitution. For + * example, if userhome environment property is set to + * /home/xyz and the File option is set to the string + * ${userhome}/test.log, then File option will be + * interpreted as the string /home/xyz/test.log. + * + * The syntax of variable substitution is similar to that of UNIX + * shells. The string between an opening "${" and + * closing "}" is interpreted as a key. Its value is + * searched in the environment properties. The corresponding value replaces + * the ${variableName} sequence. + * + * Configuration files also recognize include + * file.properties directive that allow composing + * configuration from multiple files. There is no cyclic includes + * detection mechanism to stop unbound recursion. + */ + class LOG4CPLUS_EXPORT PropertyConfigurator + { + public: + enum PCFlags + { + fRecursiveExpansion = (1 << 0) + , fShadowEnvironment = (1 << 1) + , fAllowEmptyVars = (1 << 2) + + // These encoding related options occupy 2 bits of the flags + // and are mutually exclusive. These flags are synchronized with + // PFlags in Properties. + + , fEncodingShift = 3 + , fEncodingMask = 0x3 + , fUnspecEncoding = (0 << fEncodingShift) +#if defined (LOG4CPLUS_HAVE_CODECVT_UTF8_FACET) && defined (UNICODE) + , fUTF8 = (1 << fEncodingShift) +#endif +#if (defined (LOG4CPLUS_HAVE_CODECVT_UTF16_FACET) || defined (_WIN32)) \ + && defined (UNICODE) + , fUTF16 = (2 << fEncodingShift) +#endif +#if defined (LOG4CPLUS_HAVE_CODECVT_UTF32_FACET) && defined (UNICODE) + , fUTF32 = (3 << fEncodingShift) +#endif + }; + + // ctor and dtor + PropertyConfigurator(const log4cplus::tstring& propertyFile, + Hierarchy& h = Logger::getDefaultHierarchy(), unsigned flags = 0); + PropertyConfigurator(const log4cplus::helpers::Properties& props, + Hierarchy& h = Logger::getDefaultHierarchy(), unsigned flags = 0); + PropertyConfigurator(log4cplus::tistream& propertyStream, + Hierarchy& h = Logger::getDefaultHierarchy(), unsigned flags = 0); + virtual ~PropertyConfigurator(); + + /** + * This method eliminates the need to create a temporary + * PropertyConfigurator to configure log4cplus. + * It is equivalent to the following:
+ * + * PropertyConfigurator config("filename"); + * config.configure(); + * + */ + static void doConfigure(const log4cplus::tstring& configFilename, + Hierarchy& h = Logger::getDefaultHierarchy(), unsigned flags = 0); + + /** + * Read configuration from a file. The existing configuration is + * not cleared nor reset. If you require a different behavior, + * then call {@link Hierarchy::resetConfiguration + * resetConfiguration} method before calling + * doConfigure. + * + * The configuration file consists of statements in the format + * key=value. The syntax of different configuration + * elements are discussed below. + * + *

Appender configuration

+ * + * Appender configuration syntax is: + *
+         * # For appender named appenderName, set its class.
+         * # Note: The appender name can contain dots.
+         * log4cplus.appender.appenderName=fully.qualified.name.of.appender.class
+         *
+         * # Set appender specific options.
+         * log4cplus.appender.appenderName.option1=value1
+         * ...
+         * log4cplus.appender.appenderName.optionN=valueN
+         * 
+ * + * For each named appender you can configure its {@link Layout}. The + * syntax for configuring an appender's layout is: + *
+         * log4cplus.appender.appenderName.layout=fully.qualified.name.of.layout.class
+         * log4cplus.appender.appenderName.layout.option1=value1
+         * ....
+         * log4cplus.appender.appenderName.layout.optionN=valueN
+         * 
+ * + *

Configuring loggers

+ * + * The syntax for configuring the root logger is: + *
+         * log4cplus.rootLogger=[LogLevel], appenderName, appenderName, ...
+         * 
+ * + * This syntax means that an optional LogLevel value can + * be supplied followed by appender names separated by commas. + * + * The LogLevel value can consist of the string values FATAL, + * ERROR, WARN, INFO, DEBUG or a custom LogLevel value. + * + * If a LogLevel value is specified, then the root LogLevel is set + * to the corresponding LogLevel. If no LogLevel value is specified, + * then the root LogLevel remains untouched. + * + * The root logger can be assigned multiple appenders. + * + * Each appenderName (separated by commas) will be added to + * the root logger. The named appender is defined using the + * appender syntax defined above. + * + * For non-root loggers the syntax is almost the same: + *
+         * log4cplus.logger.logger_name=[LogLevel|INHERITED], appenderName, appenderName, ...
+         * 
+ * + * The meaning of the optional LogLevel value is discussed above + * in relation to the root logger. In addition however, the value + * INHERITED can be specified meaning that the named logger should + * inherit its LogLevel from the logger hierarchy. + * + * By default loggers inherit their LogLevel from the + * hierarchy. However, if you set the LogLevel of a logger and + * later decide that that logger should inherit its LogLevel, then + * you should specify INHERITED as the value for the LogLevel value. + * + * Similar to the root logger syntax, each appenderName + * (separated by commas) will be attached to the named logger. + * + * See the appender + * additivity rule in the user manual for the meaning of the + * additivity flag. + * + * The user can override any of the {@link + * Hierarchy#disable} family of methods by setting the a key + * "log4cplus.disableOverride" to true or any value other + * than false. As in
log4cplus.disableOverride=true 
+ * + *

Example

+ * + * An example configuration is given below. + * + *
+         *
+         * # Set options for appender named "A1".
+         * # Appender "A1" will be a SyslogAppender
+         * log4cplus.appender.A1=log4cplus::SyslogAppender
+         *
+         * # The syslog daemon resides on www.abc.net
+         * log4cplus.appender.A1.SyslogHost=www.abc.net
+         *
+         * # A1's layout is a PatternLayout, using the conversion pattern
+         * # %r %-5p %c{2} %M.%L %x - %m\n. Thus, the log output will
+         * # include # the relative time since the start of the application in
+         * # milliseconds, followed by the LogLevel of the log request,
+         * # followed by the two rightmost components of the logger name,
+         * # followed by the callers method name, followed by the line number,
+         * # the nested disgnostic context and finally the message itself.
+         * # Refer to the documentation of {@link PatternLayout} for further information
+         * # on the syntax of the ConversionPattern key.
+         * log4cplus.appender.A1.layout=log4cplus::PatternLayout
+         * log4cplus.appender.A1.layout.ConversionPattern=%-4r %-5p %c{2} %M.%L %x - %m\n
+         *
+         * # Set options for appender named "A2"
+         * # A2 should be a RollingFileAppender, with maximum file size of 10 MB
+         * # using at most one backup file. A2's layout is TTCC, using the
+         * # ISO8061 date format with context printing enabled.
+         * log4cplus.appender.A2=log4cplus::RollingFileAppender
+         * log4cplus.appender.A2.MaxFileSize=10MB
+         * log4cplus.appender.A2.MaxBackupIndex=1
+         * log4cplus.appender.A2.layout=log4cplus::TTCCLayout
+         * log4cplus.appender.A2.layout.ContextPrinting=enabled
+         * log4cplus.appender.A2.layout.DateFormat=ISO8601
+         *
+         * # Root logger set to DEBUG using the A2 appender defined above.
+         * log4cplus.rootLogger=DEBUG, A2
+         *
+         * # Logger definitions:
+         * # The SECURITY logger inherits is LogLevel from root. However, it's output
+         * # will go to A1 appender defined above. It's additivity is non-cumulative.
+         * log4cplus.logger.SECURITY=INHERIT, A1
+         * log4cplus.additivity.SECURITY=false
+         *
+         * # Only warnings or above will be logged for the logger "SECURITY.access".
+         * # Output will go to A1.
+         * log4cplus.logger.SECURITY.access=WARN
+         *
+         *
+         * # The logger "class.of.the.day" inherits its LogLevel from the
+         * # logger hierarchy.  Output will go to the appender's of the root
+         * # logger, A2 in this case.
+         * log4cplus.logger.class.of.the.day=INHERIT
+         * 
+ * + * Refer to the setOption method in each Appender and + * Layout for class specific options. + * + * Use the # character at the beginning of a line + * for comments. + */ + virtual void configure(); + + /** + * \return The return value is reference to Properties + * container of properties with the "log4cplus." + * prefix removed and references to other properties and/or + * environment variables expanded. + */ + log4cplus::helpers::Properties const & getProperties () const; + + /** + * \return The return value is a reference to log4cplus::tstring + * containing filename of properties source file. It will be + * string "UNAVAILABLE" if the PropertyConfigurator instance has been + * constructed using one of the other constructors that do not take + * filename as parameter. + */ + log4cplus::tstring const & getPropertyFilename () const; + + protected: + // Methods + void init(); // called by the ctor + void reconfigure(); + void replaceEnvironVariables(); + void configureLoggers(); + void configureLogger(log4cplus::Logger logger, const log4cplus::tstring& config); + void configureAppenders(); + void configureAdditivity(); + + virtual Logger getLogger(const log4cplus::tstring& name); + virtual void addAppender(Logger &logger, log4cplus::SharedAppenderPtr& appender); + + // Types + typedef std::map AppenderMap; + + // Data + Hierarchy& h; + log4cplus::tstring propertyFilename; + log4cplus::helpers::Properties properties; + AppenderMap appenders; + unsigned flags; + + private: + // Disable copy + PropertyConfigurator(const PropertyConfigurator&); + PropertyConfigurator& operator=(PropertyConfigurator&); + }; + + + + /** + * Use this class to quickly configure the package. For file based + * configuration see PropertyConfigurator. BasicConfigurator + * automatically attaches ConsoleAppender to + * rootLogger, with output going to standard output, + * using DEBUG LogLevel value. The additional parameter + * logToStdErr may redirect the output to standard error. + */ + class LOG4CPLUS_EXPORT BasicConfigurator : public PropertyConfigurator { + public: + // ctor and dtor + BasicConfigurator(Hierarchy& h = Logger::getDefaultHierarchy(), + bool logToStdErr = false); + virtual ~BasicConfigurator(); + + /** + * This method eliminates the need to create a temporary + * BasicConfigurator object to configure log4cplus. + * It is equivalent to the following:
+ *
+         * BasicConfigurator config;
+         * config.configure();
+         * 
+ */ + static void doConfigure(Hierarchy& h = Logger::getDefaultHierarchy(), + bool logToStdErr = false); + + //! Property name for disable override. + static log4cplus::tstring const DISABLE_OVERRIDE_KEY; + + private: + // Disable copy + BasicConfigurator(const BasicConfigurator&); + BasicConfigurator& operator=(BasicConfigurator&); + }; + + +#if !defined(LOG4CPLUS_SINGLE_THREADED) + // Forward Declarations + class ConfigurationWatchDogThread; + + + class LOG4CPLUS_EXPORT ConfigureAndWatchThread { + public: + // ctor and dtor + ConfigureAndWatchThread(const log4cplus::tstring& propertyFile, + unsigned int millis = 60 * 1000); + virtual ~ConfigureAndWatchThread(); + + private: + // Disallow copying of instances of this class + ConfigureAndWatchThread(const ConfigureAndWatchThread&); + ConfigureAndWatchThread& operator=(const ConfigureAndWatchThread&); + + // Data + ConfigurationWatchDogThread * watchDogThread; + }; +#endif + +} // end namespace log4cplus + +#endif // LOG4CPLUS_CONFIGURATOR_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/consoleappender.h b/sg_agent/thrid_party/logs/include/consoleappender.h new file mode 100644 index 0000000..e31bdad --- /dev/null +++ b/sg_agent/thrid_party/logs/include/consoleappender.h @@ -0,0 +1,85 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: consoleappender.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_CONSOLE_APPENDER_HEADER_ +#define LOG4CPLUS_CONSOLE_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +namespace log4cplus { + /** + * ConsoleAppender appends log events to std::cout or + * std::cerr using a layout specified by the + * user. The default target is std::cout. + * + *

Properties

+ *
+ *
logToStdErr
+ *
When it is set true, the output stream will be + * std::cerr instead of std::cout.
+ * + *
ImmediateFlush
+ *
When it is set true, output stream will be flushed after + * each appended event.
+ * + *
+ * \sa Appender + */ + class LOG4CPLUS_EXPORT ConsoleAppender : public Appender { + public: + // Ctors + ConsoleAppender(bool logToStdErr = false, bool immediateFlush = false); + ConsoleAppender(const log4cplus::helpers::Properties & properties); + + // Dtor + ~ConsoleAppender(); + + // Methods + virtual void close(); + + //! This mutex is used by ConsoleAppender and helpers::LogLog + //! classes to synchronize output to console. + static log4cplus::thread::Mutex const & getOutputMutex(); + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + + // Data + bool logToStdErr; + /** + * Immediate flush means that the underlying output stream + * will be flushed at the end of each append operation. + */ + bool immediateFlush; + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_CONSOLE_APPENDER_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/fileappender.h b/sg_agent/thrid_party/logs/include/fileappender.h new file mode 100644 index 0000000..787b92e --- /dev/null +++ b/sg_agent/thrid_party/logs/include/fileappender.h @@ -0,0 +1,282 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: fileappender.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_FILE_APPENDER_HEADER_ +#define LOG4CPLUS_FILE_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + + +namespace log4cplus +{ + + /** + * Appends log events to a file. + * + *

Properties

+ *
+ *
File
+ *
This property specifies output file name.
+ * + *
ImmediateFlush
+ *
When it is set true, output stream will be flushed after + * each appended event.
+ * + *
Append
+ *
When it is set true, output file will be appended to + * instead of being truncated at opening.
+ * + *
ReopenDelay
+ *
This property sets a delay after which the appender will try + * to reopen log file again, after last logging failure. + *
+ * + *
BufferSize
+ *
Non-zero value of this property sets up buffering of output + * stream using a buffer of given size. + *
+ * + *
UseLockFile
+ *
Set this property to true if you want your output + * to go into a log file shared by multiple processes. When this + * property is set to true then log4cplus uses OS specific + * facilities (e.g., lockf()) to provide + * inter-process file locking. + * \sa Appender + *
+ * + *
LockFile
+ *
This property specifies lock file, file used for + * inter-process synchronization of log file access. When this + * property is not specified, the value is derived from + * File property by addition of ".lock" suffix. The + * property is only used when UseLockFile is set to true. + * \sa Appender + *
+ * + *
Locale
+ *
This property specifies a locale name that will be imbued + * into output stream. Locale can be specified either by system + * specific locale name, e.g., en_US.UTF-8, or by one of + * four recognized keywords: GLOBAL, DEFAULT + * (which is an alias for GLOBAL), USER and + * CLASSIC. When specified locale is not available, + * GLOBAL is used instead. It is possible to register + * additional locale keywords by registering an instance of + * spi::LocaleFactory in + * spi::LocaleFactoryRegistry. + * \sa spi::getLocaleFactoryRegistry() + *
+ * + *
+ */ + class LOG4CPLUS_EXPORT FileAppender : public Appender { + public: + // Ctors + FileAppender(const log4cplus::tstring& filename, + std::ios_base::openmode mode = std::ios_base::trunc, + bool immediateFlush = true); + FileAppender(const log4cplus::helpers::Properties& properties, + std::ios_base::openmode mode = std::ios_base::trunc); + + // Dtor + virtual ~FileAppender(); + + // Methods + virtual void close(); + + //! Redefine default locale for output stream. It may be a good idea to + //! provide UTF-8 locale in case UNICODE macro is defined. + virtual std::locale imbue(std::locale const& loc); + + //! \returns Locale imbued in fstream. + virtual std::locale getloc () const; + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + + void open(std::ios_base::openmode mode); + bool reopen(); + + // Data + /** + * Immediate flush means that the underlying writer or output stream + * will be flushed at the end of each append operation. Immediate + * flush is slower but ensures that each append request is actually + * written. If immediateFlush is set to + * false, then there is a good chance that the last few + * logs events are not actually written to persistent media if and + * when the application crashes. + * + * The immediateFlush variable is set to + * true by default. + */ + bool immediateFlush; + + /** + * When any append operation fails, reopenDelay says + * for how many seconds the next attempt to re-open the log file and + * resume logging will be delayed. If reopenDelay is zero, + * each failed append operation will cause log file to be re-opened. + * By default, reopenDelay is 1 second. + */ + int reopenDelay; + + unsigned long bufferSize; + log4cplus::tchar * buffer; + + log4cplus::tofstream out; + log4cplus::tstring filename; + log4cplus::tstring localeName; + + log4cplus::helpers::Time reopen_time; + + private: + LOG4CPLUS_PRIVATE void init(const log4cplus::tstring& filename, + std::ios_base::openmode mode, + const log4cplus::tstring& lockFileName); + + // Disallow copying of instances of this class + FileAppender(const FileAppender&); + FileAppender& operator=(const FileAppender&); + }; + + + + /** + * RollingFileAppender extends FileAppender to backup the log + * files when they reach a certain size. + * + *

Properties

+ *

Properties additional to {@link FileAppender}'s properties: + * + *

+ *
MaxFileSize
+ *
This property specifies maximal size of output file. The + * value is in bytes. It is possible to use MB and + * KB suffixes to specify the value in megabytes or + * kilobytes instead.
+ * + *
MaxBackupIndex
+ *
This property limits the number of backup output + * files; e.g. how many log.1, log.2 etc. files + * will be kept.
+ *
+ */ + class LOG4CPLUS_EXPORT RollingFileAppender : public FileAppender { + public: + // Ctors + RollingFileAppender(const log4cplus::tstring& filename, + long maxFileSize = 10*1024*1024, // 10 MB + int maxBackupIndex = 1, + bool immediateFlush = true); + RollingFileAppender(const log4cplus::helpers::Properties& properties); + + // Dtor + virtual ~RollingFileAppender(); + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + void rollover(bool alreadyLocked = false); + + // Data + long maxFileSize; + int maxBackupIndex; + + private: + LOG4CPLUS_PRIVATE void init(long maxFileSize, int maxBackupIndex); + }; + + + + enum DailyRollingFileSchedule { MONTHLY, WEEKLY, DAILY, + TWICE_DAILY, HOURLY, MINUTELY}; + + /** + * DailyRollingFileAppender extends {@link FileAppender} so that the + * underlying file is rolled over at a user chosen frequency. + * + *

Properties

+ *

Properties additional to {@link FileAppender}'s properties: + * + *

+ *
Schedule
+ *
This property specifies rollover schedule. The possible + * values are MONTHLY, WEEKLY, DAILY, + * TWICE_DAILY, HOURLY and + * MINUTELY.
+ * + *
MaxBackupIndex
+ *
This property limits how many backup files are kept per + * single logging period; e.g. how many log.2009-11-07.1, + * log.2009-11-07.2 etc. files are kept.
+ * + *
+ */ + class LOG4CPLUS_EXPORT DailyRollingFileAppender : public FileAppender { + public: + // Ctors + DailyRollingFileAppender(const log4cplus::tstring& filename, + DailyRollingFileSchedule schedule = DAILY, + bool immediateFlush = true, + int maxBackupIndex = 10); + DailyRollingFileAppender(const log4cplus::helpers::Properties& properties); + + // Dtor + virtual ~DailyRollingFileAppender(); + + // Methods + virtual void close(); + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + void rollover(bool alreadyLocked = false); + log4cplus::helpers::Time calculateNextRolloverTime(const log4cplus::helpers::Time& t) const; + log4cplus::tstring getFilename(const log4cplus::helpers::Time& t) const; + + // Data + DailyRollingFileSchedule schedule; + log4cplus::tstring scheduledFilename; + log4cplus::helpers::Time nextRolloverTime; + int maxBackupIndex; + + private: + LOG4CPLUS_PRIVATE void init(DailyRollingFileSchedule schedule); + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_FILE_APPENDER_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/fstreams.h b/sg_agent/thrid_party/logs/include/fstreams.h new file mode 100644 index 0000000..d0c0831 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/fstreams.h @@ -0,0 +1,56 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: fstreams.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_FSTREAMS_HEADER_ +#define LOG4CPLUS_FSTREAMS_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus +{ + + +typedef std::basic_ofstream tofstream; +typedef std::basic_ifstream tifstream; + +//! \def LOG4CPLUS_FSTREAM_PREFERED_FILE_NAME(X) +//! \brief Expands into expression that picks the right type for +//! std::fstream file name parameter. +#if defined (LOG4CPLUS_FSTREAM_ACCEPTS_WCHAR_T) && defined (UNICODE) +# define LOG4CPLUS_FSTREAM_PREFERED_FILE_NAME(X) (X) +#else +# define LOG4CPLUS_FSTREAM_PREFERED_FILE_NAME(X) (LOG4CPLUS_TSTRING_TO_STRING(X)) +#endif + + +} + +#endif // LOG4CPLUS_FSTREAMS_HEADER_ diff --git a/sg_agent/thrid_party/logs/include/helpers/appenderattachableimpl.h b/sg_agent/thrid_party/logs/include/helpers/appenderattachableimpl.h new file mode 100644 index 0000000..4cfaf3f --- /dev/null +++ b/sg_agent/thrid_party/logs/include/helpers/appenderattachableimpl.h @@ -0,0 +1,119 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: appenderattachableimpl.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_APPENDER_ATTACHABLE_IMPL_HEADER_ +#define LOG4CPLUS_HELPERS_APPENDER_ATTACHABLE_IMPL_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + +#include +#include + + +namespace log4cplus { + namespace helpers { + + /** + * This Interface is for attaching Appenders to objects. + */ + class LOG4CPLUS_EXPORT AppenderAttachableImpl + : public log4cplus::spi::AppenderAttachable + { + public: + // Data + thread::Mutex appender_list_mutex; + + // Ctors + AppenderAttachableImpl(); + + // Dtor + virtual ~AppenderAttachableImpl(); + + // Methods + /** + * Add an appender. If the appender is already in the list in + * won't be added again. + */ + virtual void addAppender(SharedAppenderPtr newAppender); + + /** + * Get all previously added appenders as an vectory. + */ + virtual SharedAppenderPtrList getAllAppenders(); + + /** + * Look for an attached appender named as name. + * + * Return the appender with that name if in the list. Return null + * otherwise. + */ + virtual SharedAppenderPtr getAppender(const log4cplus::tstring& name); + + /** + * Remove all previously added appenders. + */ + virtual void removeAllAppenders(); + + /** + * Remove the appender passed as parameter from the list of appenders. + */ + virtual void removeAppender(SharedAppenderPtr appender); + + /** + * Remove the appender with the name passed as parameter from the + * list of appenders. + */ + virtual void removeAppender(const log4cplus::tstring& name); + + /** + * Call the doAppend method on all attached appenders. + */ + int appendLoopOnAppenders(const spi::InternalLoggingEvent& event) const; + + protected: + // Types + typedef std::vector ListType; + + // Data + /** Array of appenders. */ + ListType appenderList; + + private: + AppenderAttachableImpl(AppenderAttachableImpl const &); + AppenderAttachableImpl & operator = (AppenderAttachableImpl const &); + }; // end class AppenderAttachableImpl + + } // end namespace helpers +} // end namespace log4cplus + +#endif // LOG4CPLUS_HELPERS_APPENDER_ATTACHABLE_IMPL_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/helpers/fileinfo.h b/sg_agent/thrid_party/logs/include/helpers/fileinfo.h new file mode 100644 index 0000000..725c940 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/helpers/fileinfo.h @@ -0,0 +1,59 @@ +// -*- C++ -*- +// +// Copyright (C) 2012-2013, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if ! defined (LOG4CPLUS_HELPERS_FILEINFO_H) +#define LOG4CPLUS_HELPERS_FILEINFO_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#ifdef LOG4CPLUS_HAVE_SYS_TYPES_H +#include +#endif + + +namespace log4cplus { namespace helpers { + +//! FileInfo structure is OS independent abstraction of the +//! stat() function. +struct LOG4CPLUS_EXPORT FileInfo +{ + helpers::Time mtime; + bool is_link; + off_t size; +}; + + +//! OS independent abstraction of stat() function. +LOG4CPLUS_EXPORT int getFileInfo (FileInfo * fi, tstring const & name); + + +} } // namespace log4cplus { namespace helpers { + +#endif // LOG4CPLUS_HELPERS_FILEINFO_H diff --git a/sg_agent/thrid_party/logs/include/helpers/lockfile.h b/sg_agent/thrid_party/logs/include/helpers/lockfile.h new file mode 100644 index 0000000..f451ff8 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/helpers/lockfile.h @@ -0,0 +1,68 @@ +// -*- C++ -*- +// +// Copyright (C) 2012-2013, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if ! defined (LOG4CPLUS_HELPERS_LOCKFILE_H) +#define LOG4CPLUS_HELPERS_LOCKFILE_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus { namespace helpers { + + +class LOG4CPLUS_EXPORT LockFile +{ +public: + LockFile (tstring const & lock_file); + ~LockFile (); + + void lock () const; + void unlock () const; + +private: + void open (int) const; + void close () const; + + struct Impl; + + tstring lock_file_name; + Impl * data; +}; + + +typedef log4cplus::thread::SyncGuard LockFileGuard; + + +} } // namespace log4cplus { namespace helpers { + + +#endif // LOG4CPLUS_HELPERS_LOCKFILE_H diff --git a/sg_agent/thrid_party/logs/include/helpers/loglog.h b/sg_agent/thrid_party/logs/include/helpers/loglog.h new file mode 100644 index 0000000..336f18f --- /dev/null +++ b/sg_agent/thrid_party/logs/include/helpers/loglog.h @@ -0,0 +1,145 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: loglog.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_LOGLOG +#define LOG4CPLUS_HELPERS_LOGLOG + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include + + +namespace log4cplus { + namespace helpers { + + /** + * This class used to output log statements from within the log4cplus package. + * + * Log4cplus components cannot make log4cplus logging calls. However, it is + * sometimes useful for the user to learn about what log4cplus is + * doing. You can enable log4cplus internal logging by defining the + * log4cplus.configDebug variable. + * + * All log4cplus internal debug calls go to cout + * where as internal error messages are sent to + * cerr. All internal messages are prepended with + * the string "log4clus: ". + */ + class LOG4CPLUS_EXPORT LogLog + { + public: + //! Return type of getLogLog(). + typedef LogLog * Ptr; + + /** + * Returns a reference to the LogLog singleton. + */ + static Ptr getLogLog(); + + + /** + * Allows to enable/disable log4cplus internal logging. + */ + void setInternalDebugging(bool enabled); + + /** + * In quite mode no LogLog generates strictly no output, not even + * for errors. + * + * @param quietMode A true for not + */ + void setQuietMode(bool quietMode); + + /** + * This method is used to output log4cplus internal debug + * statements. Output goes to std::cout. + */ + void debug(const log4cplus::tstring& msg) const; + void debug(tchar const * msg) const; + + /** + * This method is used to output log4cplus internal error + * statements. There is no way to disable error + * statements. Output goes to + * std::cerr. Optionally, this method can + * throw std::runtime_error exception too. + */ + void error(const log4cplus::tstring& msg, bool throw_flag = false) const; + void error(tchar const * msg, bool throw_flag = false) const; + + /** + * This method is used to output log4cplus internal warning + * statements. There is no way to disable warning statements. + * Output goes to std::cerr. + */ + void warn(const log4cplus::tstring& msg) const; + void warn(tchar const * msg) const; + + // Public ctor and dtor to be used only by internal::DefaultContext. + LogLog(); + virtual ~LogLog(); + + private: + enum TriState + { + TriUndef = -1, + TriFalse, + TriTrue + }; + + template + LOG4CPLUS_PRIVATE + void logging_worker (tostream & os, + bool (LogLog:: * cond) () const, tchar const *, + StringType const &, bool throw_flag = false) const; + + LOG4CPLUS_PRIVATE static void set_tristate_from_env (TriState *, + tchar const * envvar); + + LOG4CPLUS_PRIVATE bool get_quiet_mode () const; + LOG4CPLUS_PRIVATE bool get_not_quiet_mode () const; + LOG4CPLUS_PRIVATE bool get_debug_mode () const; + + // Data + mutable TriState debugEnabled; + mutable TriState quietMode; + thread::Mutex mutex; + + LOG4CPLUS_PRIVATE LogLog(const LogLog&); + LOG4CPLUS_PRIVATE LogLog & operator = (LogLog const &); + }; + + LOG4CPLUS_EXPORT LogLog & getLogLog (); + + } // end namespace helpers +} // end namespace log4cplus + + +#endif // LOG4CPLUS_HELPERS_LOGLOG + diff --git a/sg_agent/thrid_party/logs/include/helpers/logloguser.h b/sg_agent/thrid_party/logs/include/helpers/logloguser.h new file mode 100644 index 0000000..11b3f5e --- /dev/null +++ b/sg_agent/thrid_party/logs/include/helpers/logloguser.h @@ -0,0 +1,64 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: logloguser.h +// Created: 6/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_LOGLOG_USER +#define LOG4CPLUS_HELPERS_LOGLOG_USER + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + + +namespace log4cplus { + namespace helpers { + // forward declarations + class LogLog; + + /** + * This class used to simplify the use of the LogLog class. Any class + * that uses the LogLog class should extend this class and retrieve + * their reference to LogLog using the method provided. + */ + class LOG4CPLUS_EXPORT LogLogUser + { + public: + // ctor and dtor + LogLogUser(); + LogLogUser(const LogLogUser&); + virtual ~LogLogUser(); + + // public methods + LogLog& getLogLog() const; + + // operators + LogLogUser& operator=(const LogLogUser& rhs); + }; + + } // end namespace helpers +} // end namespace log4cplus + + +#endif // LOG4CPLUS_HELPERS_LOGLOG_USER + diff --git a/sg_agent/thrid_party/logs/include/helpers/pointer.h b/sg_agent/thrid_party/logs/include/helpers/pointer.h new file mode 100644 index 0000000..0b1b6fe --- /dev/null +++ b/sg_agent/thrid_party/logs/include/helpers/pointer.h @@ -0,0 +1,191 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: pointer.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +// Note: Some of this code uses ideas from "More Effective C++" by Scott +// Myers, Addison Wesley Longmain, Inc., (c) 1996, Chapter 29, pp. 183-213 +// + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_POINTERS_HEADER_ +#define LOG4CPLUS_HELPERS_POINTERS_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#if ! defined (LOG4CPLUS_SINGLE_THREADED) \ + && defined (LOG4CPLUS_HAVE_CXX11_ATOMICS) +#include +#endif + + +namespace log4cplus { + namespace helpers { + + /****************************************************************************** + * Class SharedObject (from pp. 204-205) * + ******************************************************************************/ + + class LOG4CPLUS_EXPORT SharedObject + { + public: + void addReference() const; + void removeReference() const; + + protected: + // Ctor + SharedObject() + : access_mutex() + , count(0) + { } + + SharedObject(const SharedObject&) + : access_mutex() + , count(0) + { } + + // Dtor + virtual ~SharedObject(); + + // Operators + SharedObject& operator=(const SharedObject&) { return *this; } + + public: + thread::Mutex access_mutex; + + private: +#if defined (LOG4CPLUS_SINGLE_THREADED) + typedef unsigned count_type; +#elif defined (LOG4CPLUS_HAVE_CXX11_ATOMICS) + typedef std::atomic count_type; +#elif defined (_WIN32) || defined (__CYGWIN__) + typedef long count_type; +#else + typedef unsigned count_type; +#endif + mutable count_type count; + }; + + + /****************************************************************************** + * Template Class SharedObjectPtr (from pp. 203, 206) * + ******************************************************************************/ + template + class SharedObjectPtr + { + public: + // Ctor + explicit + SharedObjectPtr(T* realPtr = 0) + : pointee(realPtr) + { + addref (); + } + + SharedObjectPtr(const SharedObjectPtr& rhs) + : pointee(rhs.pointee) + { + addref (); + } + +#if defined (LOG4CPLUS_HAVE_RVALUE_REFS) + SharedObjectPtr(SharedObjectPtr && rhs) + : pointee (std::move (rhs.pointee)) + { + rhs.pointee = 0; + } + + SharedObjectPtr & operator = (SharedObjectPtr && rhs) + { + rhs.swap (*this); + return *this; + } +#endif + + // Dtor + ~SharedObjectPtr() + { + if (pointee) + pointee->removeReference(); + } + + // Operators + bool operator==(const SharedObjectPtr& rhs) const { return (pointee == rhs.pointee); } + bool operator!=(const SharedObjectPtr& rhs) const { return (pointee != rhs.pointee); } + bool operator==(const T* rhs) const { return (pointee == rhs); } + bool operator!=(const T* rhs) const { return (pointee != rhs); } + T* operator->() const {assert (pointee); return pointee; } + T& operator*() const {assert (pointee); return *pointee; } + + SharedObjectPtr& operator=(const SharedObjectPtr& rhs) + { + return this->operator = (rhs.pointee); + } + + SharedObjectPtr& operator=(T* rhs) + { + SharedObjectPtr (rhs).swap (*this); + return *this; + } + + // Methods + T* get() const { return pointee; } + + void swap (SharedObjectPtr & other) throw () + { + std::swap (pointee, other.pointee); + } + + typedef T * (SharedObjectPtr:: * unspec_bool_type) () const; + operator unspec_bool_type () const + { + return pointee ? &SharedObjectPtr::get : 0; + } + + bool operator ! () const + { + return ! pointee; + } + + private: + // Methods + void addref() const + { + if (pointee) + pointee->addReference(); + } + + // Data + T* pointee; + }; + + } // end namespace helpers +} // end namespace log4cplus + + +#endif // LOG4CPLUS_HELPERS_POINTERS_HEADER_ diff --git a/sg_agent/thrid_party/logs/include/helpers/property.h b/sg_agent/thrid_party/logs/include/helpers/property.h new file mode 100644 index 0000000..e97c6d4 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/helpers/property.h @@ -0,0 +1,162 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: property.h +// Created: 2/2002 +// Author: Tad E. Smith +// +// +// Copyright 2002-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_PROPERTY_HEADER_ +#define LOG4CPLUS_HELPERS_PROPERTY_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + + +namespace log4cplus { + namespace helpers { + + //! \sa log4cplus::PropertyConfigurator + class LOG4CPLUS_EXPORT Properties { + public: + enum PFlags + { + // These encoding related options occupy 2 bits of the flags + // and are mutually exclusive. These flags are synchronized + // with PCFlags in PropertyConfigurator. + + fEncodingShift = 3 + , fEncodingMask = 0x3 + , fUnspecEncoding = (0 << fEncodingShift) +#if defined (LOG4CPLUS_HAVE_CODECVT_UTF8_FACET) && defined (UNICODE) + , fUTF8 = (1 << fEncodingShift) +#endif +#if (defined (LOG4CPLUS_HAVE_CODECVT_UTF16_FACET) || defined (_WIN32)) \ + && defined (UNICODE) + , fUTF16 = (2 << fEncodingShift) +#endif +#if defined (LOG4CPLUS_HAVE_CODECVT_UTF32_FACET) && defined (UNICODE) + , fUTF32 = (3 << fEncodingShift) +#endif + }; + + Properties(); + explicit Properties(log4cplus::tistream& input); + explicit Properties(const log4cplus::tstring& inputFile, unsigned flags = 0); + virtual ~Properties(); + + // constants + static const tchar PROPERTIES_COMMENT_CHAR; + + // methods + /** + * Tests to see if key can be found in this map. + */ + bool exists(const log4cplus::tstring& key) const; + bool exists(tchar const * key) const; + + /** + * Returns the number of entries in this map. + */ + std::size_t size() const + { + return data.size(); + } + + /** + * Searches for the property with the specified key in this property + * list. If the key is not found in this property list, the default + * property list, and its defaults, recursively, are then checked. + * The method returns null if the property is not found. + */ + log4cplus::tstring const & getProperty(const log4cplus::tstring& key) const; + log4cplus::tstring const & getProperty(tchar const * key) const; + + /** + * Searches for the property with the specified key in this property + * list. If the key is not found in this property list, the default + * property list, and its defaults, recursively, are then checked. + * The method returns the default value argument if the property is + * not found. + */ + log4cplus::tstring getProperty(const log4cplus::tstring& key, + const log4cplus::tstring& defaultVal) const; + + /** + * Returns all the keys in this property list. + */ + std::vector propertyNames() const; + + /** + * Inserts value into this map indexed by key. + */ + void setProperty(const log4cplus::tstring& key, const log4cplus::tstring& value); + + /** + * Removed the property index by key from this map. + */ + bool removeProperty(const log4cplus::tstring& key); + + /** + * Returns a subset of the "properties" whose keys start with + * "prefix". The returned "properties" have "prefix" trimmed from + * their keys. + */ + Properties getPropertySubset(const log4cplus::tstring& prefix) const; + + bool getInt (int & val, log4cplus::tstring const & key) const; + bool getUInt (unsigned & val, log4cplus::tstring const & key) const; + bool getLong (long & val, log4cplus::tstring const & key) const; + bool getULong (unsigned long & val, log4cplus::tstring const & key) const; + bool getBool (bool & val, log4cplus::tstring const & key) const; + + protected: + // Types + typedef std::map StringMap; + + // Methods + void init(log4cplus::tistream& input); + + // Data + StringMap data; + unsigned flags; + + private: + template + log4cplus::tstring const & get_property_worker ( + StringType const & key) const; + + template + bool get_type_val_worker (ValType & val, + log4cplus::tstring const & key) const; + }; + } // end namespace helpers + +} + + +#endif // LOG4CPLUS_HELPERS_PROPERTY_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/helpers/queue.h b/sg_agent/thrid_party/logs/include/helpers/queue.h new file mode 100644 index 0000000..eefaf2f --- /dev/null +++ b/sg_agent/thrid_party/logs/include/helpers/queue.h @@ -0,0 +1,158 @@ +// -*- C++ -*- +// Copyright (C) 2009-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_HELPERS_QUEUE_H +#define LOG4CPLUS_HELPERS_QUEUE_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + +#include +#include +#include +#include + + +namespace log4cplus { namespace thread { + + +//! Single consumer, multiple producers queue. +class LOG4CPLUS_EXPORT Queue + : public virtual helpers::SharedObject +{ +public: + //! Type of the state flags field. + typedef unsigned flags_type; + + //! Queue storage type. + typedef std::deque queue_storage_type; + + Queue (unsigned len = 100); + virtual ~Queue (); + + // Producers' methods. + + //! Puts event ev into queue, sets QUEUE flag and + //! sets internal event object into signaled state. If the EXIT + //! flags is already set upon entering the function, nothing is + //! inserted into the queue. The function can block on internal + //! semaphore if the queue has reached maximal allowed + //! length. Calling thread is unblocked either by consumer thread + //! removing item from queue or by any other thread calling + //! signal_exit(). + //! + //! \param ev spi::InternalLoggingEvent to be put into the queue. + //! \return Flags. + flags_type put_event (spi::InternalLoggingEvent const & ev); + + //! Sets EXIT flag and DRAIN flag and sets internal event object + //! into signaled state. + //! \param drain If true, DRAIN flag will be set, otherwise unset. + //! \return Flags, ERROR_BIT can be set upon error. + flags_type signal_exit (bool drain = true); + + // Consumer's methods. + + //! The get_events() function is used by queue's consumer. It + //! fills buf argument and sets EVENT flag in return + //! value. If EXIT flag is already set in flags member upon + //! entering the function then depending on DRAIN flag it either + //! fills buf argument or does not fill the argument, + //! if the queue is non-empty. The function blocks by waiting for + //! internal event object to be signaled if the queue is empty, + //! unless EXIT flag is set. The calling thread is unblocked when + //! items are added into the queue or when exit is signaled using + //! the signal_exit() function. + //! + //! + //! Upon error, return value has one of the error flags set. + //! + //! \param buf Pointer to storage of spi::InternalLoggingEvent + //! instances to be filled from queue. + //! \return Flags. + flags_type get_events (queue_storage_type * buf); + + //! Possible state flags. + enum Flags + { + //! EVENT flag is set in return value of get_event() call if + //! the ev argument is filled with event from the queue. + EVENT = 0x0001, + + //! QUEUE flag is set by producers when they put item into the + //! queue. + QUEUE = 0x0002, + + //! EXIT flag is set by signal_exit() call, signaling that the + //! queue worker thread should end itself. + EXIT = 0x0004, + + //! When DRAIN flag is set together with EXIT flag, the queue + //! worker thread will first drain the queue before exiting. + DRAIN = 0x0008, + + //! ERROR_BIT signals error. + ERROR_BIT = 0x0010, + + //! ERROR_AFTER signals error that has occured after queue has + //! already been touched. + ERROR_AFTER = 0x0020 + }; + +protected: + //! Queue storage. + queue_storage_type queue; + + //! Mutex protecting queue and flags. + Mutex mutex; + + //! Event on which consumer can wait if it finds queue empty. + ManualResetEvent ev_consumer; + + //! Semaphore that limits the queue length. + Semaphore sem; + + //! State flags. + flags_type flags; + +private: + Queue (Queue const &); + Queue & operator = (Queue const &); +}; + + +typedef helpers::SharedObjectPtr QueuePtr; + + +} } // namespace log4cplus { namespace thread { + + +#endif // LOG4CPLUS_SINGLE_THREADED + +#endif // LOG4CPLUS_HELPERS_QUEUE_H diff --git a/sg_agent/thrid_party/logs/include/helpers/sleep.h b/sg_agent/thrid_party/logs/include/helpers/sleep.h new file mode 100644 index 0000000..f3c5636 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/helpers/sleep.h @@ -0,0 +1,43 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: sleep.h +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_SLEEP_HEADER_ +#define LOG4CPLUS_HELPERS_SLEEP_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + + +namespace log4cplus { + namespace helpers { + LOG4CPLUS_EXPORT void sleep(unsigned long secs, + unsigned long nanosecs = 0); + LOG4CPLUS_EXPORT void sleepmillis(unsigned long millis); + } // end namespace helpers +} // end namespace log4cplus + +#endif // LOG4CPLUS_HELPERS_SLEEP_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/helpers/snprintf.h b/sg_agent/thrid_party/logs/include/helpers/snprintf.h new file mode 100644 index 0000000..f0dc949 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/helpers/snprintf.h @@ -0,0 +1,62 @@ +// -*- C++ -*- +// Copyright (C) 2010-2013, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_HELPERS_SNPRINTF_H +#define LOG4CPLUS_HELPERS_SNPRINTF_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include + + +namespace log4cplus { namespace helpers { + + +class LOG4CPLUS_EXPORT snprintf_buf +{ +public: + snprintf_buf (); + + tchar const * print (tchar const * fmt, ...) + LOG4CPLUS_FORMAT_ATTRIBUTE (__printf__, 2, 3); + + int print_va_list (tchar const * & str, tchar const * fmt, std::va_list) + LOG4CPLUS_FORMAT_ATTRIBUTE (__printf__, 3, 0); + +private: + std::vector buf; +}; + + +} } // namespace log4cplus { namespace helpers + + + +#endif // LOG4CPLUS_HELPERS_SNPRINTF_H diff --git a/sg_agent/thrid_party/logs/include/helpers/socket.h b/sg_agent/thrid_party/logs/include/helpers/socket.h new file mode 100644 index 0000000..eb52d84 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/helpers/socket.h @@ -0,0 +1,141 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: socket.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_SOCKET_HEADER_ +#define LOG4CPLUS_HELPERS_SOCKET_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus { + namespace helpers { + + enum SocketState { ok, + not_opened, + bad_address, + connection_failed, + broken_pipe, + invalid_access_mode, + message_truncated, + accept_interrupted + }; + + typedef std::ptrdiff_t SOCKET_TYPE; + + extern LOG4CPLUS_EXPORT SOCKET_TYPE const INVALID_SOCKET_VALUE; + + class LOG4CPLUS_EXPORT AbstractSocket { + public: + // ctor and dtor + AbstractSocket(); + AbstractSocket(SOCKET_TYPE sock, SocketState state, int err); + AbstractSocket(const AbstractSocket&); + virtual ~AbstractSocket() = 0; + + // methods + /// Close socket + virtual void close(); + virtual bool isOpen() const; + virtual void shutdown(); + AbstractSocket& operator=(const AbstractSocket& rhs); + + protected: + // Methods + virtual void copy(const AbstractSocket& rhs); + + // Data + SOCKET_TYPE sock; + SocketState state; + int err; + }; + + + + /** + * This class implements client sockets (also called just "sockets"). + * A socket is an endpoint for communication between two machines. + */ + class LOG4CPLUS_EXPORT Socket : public AbstractSocket { + public: + // ctor and dtor + Socket(); + Socket(SOCKET_TYPE sock, SocketState state, int err); + Socket(const tstring& address, unsigned short port, bool udp = false); + virtual ~Socket(); + + // methods + virtual bool read(SocketBuffer& buffer); + virtual bool write(const SocketBuffer& buffer); + virtual bool write(const std::string & buffer); + }; + + + + /** + * This class implements server sockets. A server socket waits for + * requests to come in over the network. It performs some operation + * based on that request, and then possibly returns a result to the + * requester. + */ + class LOG4CPLUS_EXPORT ServerSocket : public AbstractSocket { + public: + // ctor and dtor + ServerSocket(unsigned short port); + virtual ~ServerSocket(); + + Socket accept(); + void interruptAccept (); + + protected: + std::ptrdiff_t interruptHandles[2]; + }; + + + LOG4CPLUS_EXPORT SOCKET_TYPE openSocket(unsigned short port, SocketState& state); + LOG4CPLUS_EXPORT SOCKET_TYPE connectSocket(const log4cplus::tstring& hostn, + unsigned short port, bool udp, + SocketState& state); + LOG4CPLUS_EXPORT SOCKET_TYPE acceptSocket(SOCKET_TYPE sock, SocketState& state); + LOG4CPLUS_EXPORT int closeSocket(SOCKET_TYPE sock); + LOG4CPLUS_EXPORT int shutdownSocket(SOCKET_TYPE sock); + + LOG4CPLUS_EXPORT long read(SOCKET_TYPE sock, SocketBuffer& buffer); + LOG4CPLUS_EXPORT long write(SOCKET_TYPE sock, + const SocketBuffer& buffer); + LOG4CPLUS_EXPORT long write(SOCKET_TYPE sock, + const std::string & buffer); + + LOG4CPLUS_EXPORT tstring getHostname (bool fqdn); + LOG4CPLUS_EXPORT int setTCPNoDelay (SOCKET_TYPE, bool); + + } // end namespace helpers +} // end namespace log4cplus + +#endif // LOG4CPLUS_HELPERS_SOCKET_HEADER_ diff --git a/sg_agent/thrid_party/logs/include/helpers/socketbuffer.h b/sg_agent/thrid_party/logs/include/helpers/socketbuffer.h new file mode 100644 index 0000000..f8b9613 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/helpers/socketbuffer.h @@ -0,0 +1,79 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: socketbuffer.h +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_SOCKET_BUFFER_HEADER_ +#define LOG4CPLUS_HELPERS_SOCKET_BUFFER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + + +namespace log4cplus { +namespace helpers { + +/** + * + */ +class LOG4CPLUS_EXPORT SocketBuffer +{ +public: + explicit SocketBuffer(std::size_t max); + virtual ~SocketBuffer(); + + char *getBuffer() const { return buffer; } + std::size_t getMaxSize() const { return maxsize; } + std::size_t getSize() const { return size; } + void setSize(std::size_t s) { size = s; } + std::size_t getPos() const { return pos; } + + unsigned char readByte(); + unsigned short readShort(); + unsigned int readInt(); + tstring readString(unsigned char sizeOfChar); + + void appendByte(unsigned char val); + void appendShort(unsigned short val); + void appendInt(unsigned int val); + void appendString(const tstring& str); + void appendBuffer(const SocketBuffer& buffer); + +private: + // Data + std::size_t maxsize; + std::size_t size; + std::size_t pos; + char *buffer; + + SocketBuffer(SocketBuffer const & rhs); + SocketBuffer& operator= (SocketBuffer const& rhs); +}; + +} // end namespace helpers +} // end namespace log4cplus + +#endif // LOG4CPLUS_HELPERS_SOCKET_HEADER_ diff --git a/sg_agent/thrid_party/logs/include/helpers/stringhelper.h b/sg_agent/thrid_party/logs/include/helpers/stringhelper.h new file mode 100644 index 0000000..56d150c --- /dev/null +++ b/sg_agent/thrid_party/logs/include/helpers/stringhelper.h @@ -0,0 +1,212 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: stringhelper.h +// Created: 3/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_ +#define LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#include +#include + + +namespace log4cplus { + namespace helpers { + + /** + * Returns s in upper case. + */ + LOG4CPLUS_EXPORT log4cplus::tstring toUpper(const log4cplus::tstring& s); + + + /** + * Returns s in lower case. + */ + LOG4CPLUS_EXPORT log4cplus::tstring toLower(const log4cplus::tstring& s); + + + /** + * Tokenize s using c as the delimiter and + * put the resulting tokens in _result. If + * collapseTokens is false, multiple adjacent delimiters + * will result in zero length tokens. + * + * Example: + *
+         *   string s = // Set string with '.' as delimiters
+         *   list tokens;
+         *   tokenize(s, '.', back_insert_iterator >(tokens));
+         * 
+ */ + template + inline + void + tokenize(const StringType& s, typename StringType::value_type c, + OutputIter result, bool collapseTokens = true) + { + typedef typename StringType::size_type size_type; + size_type const slen = s.length(); + size_type first = 0; + size_type i = 0; + for (i=0; i < slen; ++i) + { + if (s[i] == c) + { + *result = StringType (s, first, i - first); + ++result; + if (collapseTokens) + while (i+1 < slen && s[i+1] == c) + ++i; + first = i + 1; + } + } + if (first != i) + *result = StringType (s, first, i - first); + } + + + template + struct ConvertIntegerToStringHelper; + + + template + struct ConvertIntegerToStringHelper + { + static inline + void + step1 (tchar * & it, intType & value) + { + // The sign of the result of the modulo operator is + // implementation defined. That's why we work with + // positive counterpart instead. Also, in twos + // complement arithmetic the smallest negative number + // does not have positive counterpart; the range is + // asymetric. That's why we handle the case of value + // == min() specially here. + if (value == (std::numeric_limits::min) ()) + { + intType const r = value / 10; + intType const a = (-r) * 10; + intType const mod = -(a + value); + value = -r; + + *(it - 1) = static_cast(LOG4CPLUS_TEXT('0') + mod); + --it; + } + else + value = -value; + } + + static inline + bool + is_negative (intType val) + { + return val < 0; + } + }; + + + template + struct ConvertIntegerToStringHelper + { + static inline + void + step1 (tchar * &, intType &) + { + // This will never be called for unsigned types. + } + + static inline + bool + is_negative (intType) + { + return false; + } + }; + + + template + inline + void + convertIntegerToString (tstring & str, intType value) + { + typedef std::numeric_limits intTypeLimits; + typedef ConvertIntegerToStringHelper + HelperType; + + tchar buffer[intTypeLimits::digits10 + 2]; + // We define buffer_size from buffer using sizeof operator + // to appease HP aCC compiler. + const std::size_t buffer_size = sizeof (buffer) / sizeof (tchar); + + tchar * it = &buffer[buffer_size]; + tchar const * const buf_end = it; + + if (value == 0) + { + --it; + *it = LOG4CPLUS_TEXT('0'); + } + + bool const negative = HelperType::is_negative (value); + if (negative) + HelperType::step1 (it, value); + + for (; value != 0; --it) + { + intType mod = value % 10; + value = value / 10; + *(it - 1) = static_cast(LOG4CPLUS_TEXT('0') + mod); + } + + if (negative) + { + --it; + *it = LOG4CPLUS_TEXT('-'); + } + + str.assign (static_cast(it), buf_end); + } + + + template + inline + tstring + convertIntegerToString (intType value) + { + tstring result; + convertIntegerToString (result, value); + return result; + } + + } // namespace helpers + +} // namespace log4cplus + +#endif // LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_ diff --git a/sg_agent/thrid_party/logs/include/helpers/thread-config.h b/sg_agent/thrid_party/logs/include/helpers/thread-config.h new file mode 100644 index 0000000..4f9e063 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/helpers/thread-config.h @@ -0,0 +1,61 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: thread-config.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_THREAD_CONFIG_HEADER_ +#define LOG4CPLUS_HELPERS_THREAD_CONFIG_HEADER_ + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (LOG4CPLUS_USE_PTHREADS) +# if defined (__APPLE__) +# define LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE +# endif + +#elif defined(LOG4CPLUS_USE_WIN32_THREADS) +# if defined (_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 +# define LOG4CPLUS_USE_SRW_LOCK +# else +# define LOG4CPLUS_POOR_MANS_SHAREDMUTEX +# endif +# undef LOG4CPLUS_HAVE_TLS_SUPPORT +# undef LOG4CPLUS_THREAD_LOCAL_VAR +# if defined (_MSC_VER) && _WIN32_WINNT >= 0x0600 +// The __declspec(thread) functionality is not compatible with LoadLibrary(). +// For more information why see and "Windows and TLS" note in README. +// . +# define LOG4CPLUS_HAVE_TLS_SUPPORT 1 +# define LOG4CPLUS_THREAD_LOCAL_VAR __declspec(thread) +# endif + +#elif defined(LOG4CPLUS_SINGLE_THREADED) +# undef LOG4CPLUS_HAVE_TLS_SUPPORT +# undef LOG4CPLUS_THREAD_LOCAL_VAR + +#else +# error "You Must define a Threading model" + +#endif + + +#endif // LOG4CPLUS_HELPERS_THREAD_CONFIG_HEADER_ diff --git a/sg_agent/thrid_party/logs/include/helpers/timehelper.h b/sg_agent/thrid_party/logs/include/helpers/timehelper.h new file mode 100644 index 0000000..06b3281 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/helpers/timehelper.h @@ -0,0 +1,179 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: timehelper.h +// Created: 6/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_TIME_HELPER_HEADER_ +#define LOG4CPLUS_HELPERS_TIME_HELPER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#if defined (LOG4CPLUS_HAVE_TIME_H) +#include +#endif + +#include + + +namespace log4cplus { + +namespace helpers { + + +using std::time_t; +using std::tm; + + +/** + * This class represents a Epoch time with microsecond accuracy. + */ +class LOG4CPLUS_EXPORT Time { +public: + Time(); + Time(time_t tv_sec, long tv_usec); + explicit Time(time_t time); + + /** + * Returns the current time using the gettimeofday() + * method if it is available on the current platform. (Not on + * WIN32.) + */ + static Time gettimeofday(); + + // Methods + /** + * Returns seconds value. + */ + time_t sec() const { return tv_sec; } + + /** + * Returns microseconds value. + */ + long usec() const { return tv_usec; } + + /** + * Sets the seconds value. + */ + void sec(time_t s) { tv_sec = s; } + + /** + * Sets the microseconds value. + */ + void usec(long us) { tv_usec = us; } + + /** + * Sets this Time using the mktime function. + */ + time_t setTime(tm* t); + + /** + * Returns this Time as a time_t value. + */ + time_t getTime() const LOG4CPLUS_ATTRIBUTE_PURE; + + /** + * Populates tm using the gmtime() + * function. + */ + void gmtime(tm* t) const; + + /** + * Populates tm using the localtime() + * function. + */ + void localtime(tm* t) const; + + /** + * Returns a string with a "formatted time" specified by + * fmt. It used the strftime() + * function to do this. + * + * Look at your platform's strftime() documentation + * for the formatting options available. + * + * The following additional options are provided:
+ * %q - 3 character field that provides milliseconds + * %Q - 7 character field that provides fractional + * milliseconds. + */ + log4cplus::tstring getFormattedTime(const log4cplus::tstring& fmt, + bool use_gmtime = false) const; + + // Operators + Time& operator+=(const Time& rhs); + Time& operator-=(const Time& rhs); + Time& operator/=(long rhs); + Time& operator*=(long rhs); + +private: + // Data + time_t tv_sec; /* seconds */ + long tv_usec; /* microseconds */ +}; + + +LOG4CPLUS_EXPORT const log4cplus::helpers::Time operator+ + (const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs); +LOG4CPLUS_EXPORT const log4cplus::helpers::Time operator- + (const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs); +LOG4CPLUS_EXPORT const log4cplus::helpers::Time operator/ + (const log4cplus::helpers::Time& lhs, + long rhs); +LOG4CPLUS_EXPORT const log4cplus::helpers::Time operator* + (const log4cplus::helpers::Time& lhs, + long rhs); + +LOG4CPLUS_EXPORT bool operator<(const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs) + LOG4CPLUS_ATTRIBUTE_PURE; +LOG4CPLUS_EXPORT bool operator<=(const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs) + LOG4CPLUS_ATTRIBUTE_PURE; + +LOG4CPLUS_EXPORT bool operator>(const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs) + LOG4CPLUS_ATTRIBUTE_PURE; +LOG4CPLUS_EXPORT bool operator>=(const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs) + LOG4CPLUS_ATTRIBUTE_PURE; + +LOG4CPLUS_EXPORT bool operator==(const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs) + LOG4CPLUS_ATTRIBUTE_PURE; +LOG4CPLUS_EXPORT bool operator!=(const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs) + LOG4CPLUS_ATTRIBUTE_PURE; + +} // namespace helpers + +} // namespace log4cplus + + +#endif // LOG4CPLUS_HELPERS_TIME_HELPER_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/hierarchy.h b/sg_agent/thrid_party/logs/include/hierarchy.h new file mode 100644 index 0000000..2c023a9 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/hierarchy.h @@ -0,0 +1,325 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: hierarchy.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HIERARCHY_HEADER_ +#define LOG4CPLUS_HIERARCHY_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include + + +namespace log4cplus { + // Forward Declarations + class HierarchyLocker; + + /** + * This class is specialized in retrieving loggers by name and + * also maintaining the logger hierarchy. + * + * The casual user should not have to deal with this class + * directly. However, if you are in an environment where + * multiple applications run in the same process, then read on. + * + * The structure of the logger hierarchy is maintained by the + * {@link #getInstance} method. The hierarchy is such that children + * link to their parent but parents do not have any pointers to their + * children. Moreover, loggers can be instantiated in any order, in + * particular descendant before ancestor. + * + * In case a descendant is created before a particular ancestor, + * then it creates a provision node for the ancestor and adds itself + * to the provision node. Other descendants of the same ancestor add + * themselves to the previously created provision node. + */ + class LOG4CPLUS_EXPORT Hierarchy + { + public: + // DISABLE_OFF should be set to a value lower than all possible + // priorities. + static const LogLevel DISABLE_OFF; + static const LogLevel DISABLE_OVERRIDE; + + // Ctors + /** + * Create a new Logger hierarchy. + */ + Hierarchy(); + + // Dtor + virtual ~Hierarchy(); + + // Methods + /** + * This call will clear all logger definitions from the internal + * hashtable. Invoking this method will irrevocably mess up the + * logger hierarchy. + * + * You should really know what you are doing before + * invoking this method. + */ + virtual void clear(); + + /** + * Returns true if the named logger exists + * (in the default hierarchy). + * + * @param name The name of the logger to search for. + */ + virtual bool exists(const log4cplus::tstring& name); + + /** + * Similar to {@link #disable(LogLevel)} except that the LogLevel + * argument is given as a log4cplus::tstring. + */ + virtual void disable(const log4cplus::tstring& loglevelStr); + + /** + * Disable all logging requests of LogLevel equal to or + * below the ll parameter p, for + * all loggers in this hierarchy. Logging requests of + * higher LogLevel then p remain unaffected. + * + * Nevertheless, if the + * BasicConfigurator::DISABLE_OVERRIDE_KEY property is set to + * true, then logging requests are evaluated as usual. + * + * The "disable" family of methods are there for speed. They + * allow printing methods such as debug, info, etc. to return + * immediately after an integer comparison without walking the + * logger hierarchy. In most modern computers an integer + * comparison is measured in nanoseconds where as a logger walk is + * measured in units of microseconds. + */ + virtual void disable(LogLevel ll); + + /** + * Disable all logging requests regardless of logger and LogLevel. + * This method is equivalent to calling {@link #disable} with the + * argument FATAL_LOG_LEVEL, the highest possible LogLevel. + */ + virtual void disableAll(); + + /** + * Disable all Debug logging requests regardless of logger. + * This method is equivalent to calling {@link #disable} with the + * argument DEBUG_LOG_LEVEL. + */ + virtual void disableDebug(); + + /** + * Disable all Info logging requests regardless of logger. + * This method is equivalent to calling {@link #disable} with the + * argument INFO_LOG_LEVEL. + */ + virtual void disableInfo(); + + /** + * Undoes the effect of calling any of {@link #disable}, {@link + * #disableAll}, {@link #disableDebug} and {@link #disableInfo} + * methods. More precisely, invoking this method sets the Logger + * class internal variable called disable to its + * default "off" value. + */ + virtual void enableAll(); + + /** + * Return a new logger instance named as the first parameter using + * the default factory. + * + * If a logger of that name already exists, then it will be + * returned. Otherwise, a new logger will be instantiated and + * then linked with its existing ancestors as well as children. + * + * @param name The name of the logger to retrieve. + */ + virtual Logger getInstance(const log4cplus::tstring& name); + + /** + * Return a new logger instance named as the first parameter using + * factory. + * + * If a logger of that name already exists, then it will be + * returned. Otherwise, a new logger will be instantiated by the + * factory parameter and linked with its existing + * ancestors as well as children. + * + * @param name The name of the logger to retrieve. + * @param factory The factory that will make the new logger instance. + */ + virtual Logger getInstance(const log4cplus::tstring& name, spi::LoggerFactory& factory); + + /** + * Returns all the currently defined loggers in this hierarchy. + * + * The root logger is not included in the returned list. + */ + virtual LoggerList getCurrentLoggers(); + + /** + * Is the LogLevel specified by level enabled? + */ + virtual bool isDisabled(LogLevel level); + + /** + * Get the root of this hierarchy. + */ + virtual Logger getRoot() const; + + /** + * Reset all values contained in this hierarchy instance to their + * default. This removes all appenders from all loggers, sets + * the LogLevel of all non-root loggers to NOT_SET_LOG_LEVEL, + * sets their additivity flag to true and sets the LogLevel + * of the root logger to DEBUG_LOG_LEVEL. Moreover, message disabling + * is set its default "off" value. + * + * Existing loggers are not removed. They are just reset. + * + * This method should be used sparingly and with care as it will + * block all logging until it is completed.

+ */ + virtual void resetConfiguration(); + + /** + * Set the default LoggerFactory instance. + */ + virtual void setLoggerFactory(std::auto_ptr factory); + + /** + * Returns the default LoggerFactory instance. + */ + virtual spi::LoggerFactory* getLoggerFactory(); + + /** + * Shutting down a hierarchy will safely close and remove + * all appenders in all loggers including the root logger. + * + * Some appenders such as SocketAppender need to be closed before the + * application exits. Otherwise, pending logging events might be + * lost. + * + * The shutdown method is careful to close nested + * appenders before closing regular appenders. This is allows + * configurations where a regular appender is attached to a logger + * and again to a nested appender. + */ + virtual void shutdown(); + + private: + // Types + typedef std::vector ProvisionNode; + typedef std::map ProvisionNodeMap; + typedef std::map LoggerMap; + + // Methods + /** + * This is the implementation of the getInstance() method. + * NOTE: This method does not lock the hashtable_mutex. + */ + LOG4CPLUS_PRIVATE + virtual Logger getInstanceImpl(const log4cplus::tstring& name, + spi::LoggerFactory& factory); + + /** + * This is the implementation of the getCurrentLoggers(). + * NOTE: This method does not lock the hashtable_mutex. + */ + LOG4CPLUS_PRIVATE + virtual void initializeLoggerList(LoggerList& list) const; + + /** + * This method loops through all the *potential* parents of + * logger'. There 3 possible cases: + * + * 1) No entry for the potential parent of 'logger' exists + * + * We create a ProvisionNode for this potential parent and insert + * 'logger' in that provision node. + * + * 2) There is an entry of type Logger for the potential parent. + * + * The entry is 'logger's nearest existing parent. We update logger's + * parent field with this entry. We also break from the loop + * because updating our parent's parent is our parent's + * responsibility. + * + * 3) There entry is of type ProvisionNode for this potential parent. + * + * We add 'logger' to the list of children for this potential parent. + */ + LOG4CPLUS_PRIVATE void updateParents(Logger const & logger); + + /** + * We update the links for all the children that placed themselves + * in the provision node 'pn'. The second argument 'logger' is a + * reference for the newly created Logger, parent of all the + * children in 'pn' + * + * We loop on all the children 'c' in 'pn': + * + * If the child 'c' has been already linked to a child of + * 'logger' then there is no need to update 'c'. + * + * Otherwise, we set logger's parent field to c's parent and set + * c's parent field to logger. + */ + LOG4CPLUS_PRIVATE void updateChildren(ProvisionNode& pn, + Logger const & logger); + + // Data + thread::Mutex hashtable_mutex; + std::auto_ptr defaultFactory; + ProvisionNodeMap provisionNodes; + LoggerMap loggerPtrs; + Logger root; + + int disableValue; + + bool emittedNoAppenderWarning; + + // Disallow copying of instances of this class + Hierarchy(const Hierarchy&); + Hierarchy& operator=(const Hierarchy&); + + // Friends + friend class log4cplus::spi::LoggerImpl; + friend class log4cplus::HierarchyLocker; + }; + + + LOG4CPLUS_EXPORT Hierarchy & getDefaultHierarchy (); + + +} // end namespace log4cplus + +#endif // LOG4CPLUS_HIERARCHY_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/hierarchylocker.h b/sg_agent/thrid_party/logs/include/hierarchylocker.h new file mode 100644 index 0000000..ed27664 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/hierarchylocker.h @@ -0,0 +1,80 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: hierarchylocker.h +// Created: 8/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HIERARCHY_LOCKER_HEADER_ +#define LOG4CPLUS_HIERARCHY_LOCKER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include + + +namespace log4cplus +{ + + class Hierarchy; + + + /** + * This is used to lock a Hierarchy. The dtor unlocks the Hierarchy. + */ + class LOG4CPLUS_EXPORT HierarchyLocker { + public: + // ctor & dtor + HierarchyLocker(Hierarchy& h); + ~HierarchyLocker(); + + /** + * Calls the resetConfiguration() method on the locked Hierarchy. + */ + void resetConfiguration(); + + /** + * Calls the getInstance() method on the locked Hierarchy. + */ + Logger getInstance(const log4cplus::tstring& name); + + /** + * Calls the getInstance() method on the locked Hierarchy. + */ + Logger getInstance(const log4cplus::tstring& name, spi::LoggerFactory& factory); + + void addAppender(Logger &logger, log4cplus::SharedAppenderPtr& appender); + + private: + // Data + Hierarchy& h; + log4cplus::thread::MutexGuard hierarchyLocker; + LoggerList loggerList; + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_HIERARCHY_LOCKER_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/internal/cygwin-win32.h b/sg_agent/thrid_party/logs/include/internal/cygwin-win32.h new file mode 100644 index 0000000..ab5a744 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/internal/cygwin-win32.h @@ -0,0 +1,54 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: cygwin-win32.h +// Created: 7/2011 +// Author: Vaclav Zeman +// +// Copyright (C) 2011-2013, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if ! defined (LOG4CPLUS_CONFIG_CYGWIN_WIN32_H) +#define LOG4CPLUS_CONFIG_CYGWIN_WIN32_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (__CYGWIN__) + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + + +namespace log4cplus { namespace cygwin { + +unsigned long get_current_win32_thread_id (); + +} } // namespace log4cplus { namespace cygwin { + + +#endif // defined (__CYGWIN__) +#endif // LOG4CPLUS_CONFIG_CYGWIN_WIN32_H diff --git a/sg_agent/thrid_party/logs/include/internal/env.h b/sg_agent/thrid_party/logs/include/internal/env.h new file mode 100644 index 0000000..8c9a364 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/internal/env.h @@ -0,0 +1,87 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: env.h +// Created: 7/2010 +// Author: Vaclav Haisman +// +// +// Copyright (C) 2010-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_INTERNAL_ENV_H +#define LOG4CPLUS_INTERNAL_ENV_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#if defined (_WIN32) +#include +#endif +#ifdef LOG4CPLUS_HAVE_SYS_TYPES_H +#include +#endif +#ifdef LOG4CPLUS_HAVE_UNISTD_H +#include +#endif + + +namespace log4cplus { namespace internal { + + +bool get_env_var (tstring & value, tstring const & name); +bool parse_bool (bool & val, tstring const & str); + +inline +#if defined (_WIN32) +DWORD +get_process_id () +{ + return GetCurrentProcessId (); +} + +#elif defined (LOG4CPLUS_HAVE_GETPID) +pid_t +get_process_id () +{ + return getpid (); +} + +#else +int +get_process_id () +{ + return 0; +} + +#endif + + +} } // namespace log4cplus { namespace internal { + + +#endif // LOG4CPLUS_INTERNAL_ENV_H diff --git a/sg_agent/thrid_party/logs/include/internal/internal.h b/sg_agent/thrid_party/logs/include/internal/internal.h new file mode 100644 index 0000000..3b467ef --- /dev/null +++ b/sg_agent/thrid_party/logs/include/internal/internal.h @@ -0,0 +1,243 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: internal.h +// Created: 1/2009 +// Author: Vaclav Haisman +// +// +// Copyright (C) 2009-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/** @file + * This header contains declaration internal to log4cplus. They must never be + * visible from user accesible headers or exported in DLL/shared libray. + */ + + +#ifndef LOG4CPLUS_INTERNAL_INTERNAL_HEADER_ +#define LOG4CPLUS_INTERNAL_INTERNAL_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace log4cplus { + +namespace internal { + + +//! Canonical empty string. It is used when the need to return empty string +//! by reference arises. +extern log4cplus::tstring const empty_str; + + +struct gft_scratch_pad +{ + gft_scratch_pad (); + ~gft_scratch_pad (); + + void + reset () + { + uc_q_str_valid = false; + q_str_valid = false; + s_str_valid = false; + ret.clear (); + } + + log4cplus::tstring q_str; + log4cplus::tstring uc_q_str; + log4cplus::tstring s_str; + log4cplus::tstring ret; + log4cplus::tstring fmt; + log4cplus::tstring tmp; + std::vector buffer; + bool uc_q_str_valid; + bool q_str_valid; + bool s_str_valid; +}; + + +struct appender_sratch_pad +{ + appender_sratch_pad (); + ~appender_sratch_pad (); + + tostringstream oss; + tstring str; + std::string chstr; +}; + + +//! Per thread data. +struct per_thread_data +{ + per_thread_data (); + ~per_thread_data (); + + tostringstream macros_oss; + tostringstream layout_oss; + DiagnosticContextStack ndc_dcs; + MappedDiagnosticContextMap mdc_map; + log4cplus::tstring thread_name; + log4cplus::tstring thread_name2; + gft_scratch_pad gft_sp; + appender_sratch_pad appender_sp; + log4cplus::tstring faa_str; + log4cplus::tstring ll_str; + spi::InternalLoggingEvent forced_log_ev; + std::FILE * fnull; + log4cplus::helpers::snprintf_buf snprintf_buf; +}; + + +per_thread_data * alloc_ptd (); + +// TLS key whose value is pointer struct per_thread_data. +extern log4cplus::thread::impl::tls_key_type tls_storage_key; + + +#if ! defined (LOG4CPLUS_SINGLE_THREADED) \ + && defined (LOG4CPLUS_THREAD_LOCAL_VAR) + +extern LOG4CPLUS_THREAD_LOCAL_VAR per_thread_data * ptd; + + +inline +void +set_ptd (per_thread_data * p) +{ + ptd = p; +} + + +inline +per_thread_data * +get_ptd (bool alloc = true) +{ + if (LOG4CPLUS_UNLIKELY (! ptd && alloc)) + return alloc_ptd (); + + // The assert() does not belong here. get_ptd() might be called by + // cleanup code that can handle the returned NULL pointer. + //assert (ptd); + + return ptd; +} + + +#else // defined (LOG4CPLUS_THREAD_LOCAL_VAR) + + +inline +void +set_ptd (per_thread_data * p) +{ + thread::impl::tls_set_value (tls_storage_key, p); +} + + +inline +per_thread_data * +get_ptd (bool alloc = true) +{ + per_thread_data * ptd + = reinterpret_cast( + thread::impl::tls_get_value (tls_storage_key)); + + if (LOG4CPLUS_UNLIKELY (! ptd && alloc)) + return alloc_ptd (); + + return ptd; +} + + +#endif // defined (LOG4CPLUS_THREAD_LOCAL_VAR) + + +inline +tstring & +get_thread_name_str () +{ + return get_ptd ()->thread_name; +} + + +inline +tstring & +get_thread_name2_str () +{ + return get_ptd ()->thread_name2; +} + + +inline +gft_scratch_pad & +get_gft_scratch_pad () +{ + return get_ptd ()->gft_sp; +} + + +inline +appender_sratch_pad & +get_appender_sp () +{ + return get_ptd ()->appender_sp; +} + + +} // namespace internal { + + +namespace detail +{ + +LOG4CPLUS_EXPORT void clear_tostringstream (tostringstream &); + +} // namespace detail + + +} // namespace log4cplus { + + +#endif // LOG4CPLUS_INTERNAL_INTERNAL_HEADER_ diff --git a/sg_agent/thrid_party/logs/include/internal/socket.h b/sg_agent/thrid_party/logs/include/internal/socket.h new file mode 100644 index 0000000..e1402e3 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/internal/socket.h @@ -0,0 +1,118 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: socket.h +// Created: 1/2010 +// Author: Vaclav Haisman +// +// +// Copyright (C) 2010-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/** @file + * This header contains declaration internal to log4cplus. They must never be + * visible from user accesible headers or exported in DLL/shared libray. + */ + + +#ifndef LOG4CPLUS_INTERNAL_SOCKET_H_ +#define LOG4CPLUS_INTERNAL_SOCKET_H_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + +#if defined(_WIN32) +#include +#endif +#include + +#include +#ifdef LOG4CPLUS_HAVE_ERRNO_H +#include +#endif + + +namespace log4cplus { + +namespace helpers { + + +#if defined(_WIN32) +typedef SOCKET os_socket_type; +#else +typedef int os_socket_type; +#endif + + +os_socket_type const INVALID_OS_SOCKET_VALUE +#if defined(_WIN32) + = INVALID_SOCKET; +#else + = -1; +#endif + + +static inline +os_socket_type +to_os_socket (SOCKET_TYPE const & x) +{ + return static_cast(x); +} + + +static inline +SOCKET_TYPE +to_log4cplus_socket (os_socket_type const & x) +{ + return static_cast(x); +} + + +static inline +void +set_last_socket_error (int err) +{ + errno = err; +} + + +static inline +int +get_last_socket_error () +{ + return errno; +} + + +} // namespace helpers { + +} // namespace log4cplus { + + +#endif // LOG4CPLUS_INTERNAL_SOCKET_H_ diff --git a/sg_agent/thrid_party/logs/include/layout.h b/sg_agent/thrid_party/logs/include/layout.h new file mode 100644 index 0000000..16a6d31 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/layout.h @@ -0,0 +1,622 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: Layout.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_LAYOUT_HEADER_ +#define LOG4CPLUS_LAYOUT_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include + +#include + + +namespace log4cplus { + + // Forward Declarations + namespace pattern + { + + class PatternConverter; + + } + + + namespace helpers + { + + class Properties; + class Time; + + } + + + namespace spi + { + + class InternalLoggingEvent; + + } + + + /** + * This class is used to layout strings sent to an {@link + * log4cplus::Appender}. + */ + class LOG4CPLUS_EXPORT Layout + { + public: + Layout(); + Layout(const helpers::Properties& properties); + virtual ~Layout() = 0; + + virtual void formatAndAppend(log4cplus::tostream& output, + const log4cplus::spi::InternalLoggingEvent& event) = 0; + + protected: + LogLevelManager& llmCache; + + private: + // Disable copy + Layout(const Layout&); + Layout& operator=(Layout const &); + }; + + + + /** + * SimpleLayout consists of the LogLevel of the log statement, + * followed by " - " and then the log message itself. For example, + * + *
+     *         DEBUG - Hello world
+     * 
+ * + * {@link PatternLayout} offers a much more powerful alternative. + */ + class LOG4CPLUS_EXPORT SimpleLayout + : public Layout + { + public: + SimpleLayout(); + SimpleLayout(const log4cplus::helpers::Properties& properties); + virtual ~SimpleLayout(); + + virtual void formatAndAppend(log4cplus::tostream& output, + const log4cplus::spi::InternalLoggingEvent& event); + + private: + // Disallow copying of instances of this class + SimpleLayout(const SimpleLayout&); + SimpleLayout& operator=(const SimpleLayout&); + }; + + + + /** + * TTCC layout format consists of time, thread, Logger and nested + * diagnostic context information, hence the name. + * + * The time format depends on the DateFormat used. Use the + * Use_gmtime to specify whether messages should be logged using + * localtime or gmtime. + * + * Here is an example TTCCLayout output: + * + *
+     * 176 [main] INFO  org.apache.log4j.examples.Sort - Populating an array of 2 elements in reverse order.
+     * 225 [main] INFO  org.apache.log4j.examples.SortAlgo - Entered the sort method.
+     * 262 [main] DEBUG org.apache.log4j.examples.SortAlgo.OUTER i=1 - Outer loop.
+     * 276 [main] DEBUG org.apache.log4j.examples.SortAlgo.SWAP i=1 j=0 - Swapping intArray[0] = 1 and intArray[1] = 0
+     * 290 [main] DEBUG org.apache.log4j.examples.SortAlgo.OUTER i=0 - Outer loop.
+     * 304 [main] INFO  org.apache.log4j.examples.SortAlgo.DUMP - Dump of interger array:
+     * 317 [main] INFO  org.apache.log4j.examples.SortAlgo.DUMP - Element [0] = 0
+     * 331 [main] INFO  org.apache.log4j.examples.SortAlgo.DUMP - Element [1] = 1
+     * 343 [main] INFO  org.apache.log4j.examples.Sort - The next log statement should be an error message.
+     * 346 [main] ERROR org.apache.log4j.examples.SortAlgo.DUMP - Tried to dump an uninitialized array.
+     * 467 [main] INFO  org.apache.log4j.examples.Sort - Exiting main method.
+     * 
+ * + * The first field is the number of milliseconds elapsed since the + * start of the program. The second field is the thread outputting the + * log statement. The third field is the LogLevel, the fourth field is + * the logger to which the statement belongs. + * + * The fifth field (just before the '-') is the nested diagnostic + * context. Note the nested diagnostic context may be empty as in the + * first two statements. The text after the '-' is the message of the + * statement. + * + * PatternLayout offers a much more flexible alternative. + */ + class LOG4CPLUS_EXPORT TTCCLayout + : public Layout + { + public: + // Ctor and dtor + TTCCLayout(bool use_gmtime = false); + TTCCLayout(const log4cplus::helpers::Properties& properties); + virtual ~TTCCLayout(); + + virtual void formatAndAppend(log4cplus::tostream& output, + const log4cplus::spi::InternalLoggingEvent& event); + + protected: + log4cplus::tstring dateFormat; + bool use_gmtime; + + private: + // Disallow copying of instances of this class + TTCCLayout(const TTCCLayout&); + TTCCLayout& operator=(const TTCCLayout&); + }; + + + LOG4CPLUS_EXPORT helpers::Time const & getTTCCLayoutTimeBase (); + + + /** + * A flexible layout configurable with pattern string. + * + * The goal of this class is to format a InternalLoggingEvent and return + * the results as a string. The results depend on the conversion + * pattern. + * + * The conversion pattern is closely related to the conversion + * pattern of the printf function in C. A conversion pattern is + * composed of literal text and format control expressions called + * conversion specifiers. + * + * You are free to insert any literal text within the conversion + * pattern. + * + * Each conversion specifier starts with a percent sign (%%) and is + * followed by optional format modifiers and a conversion + * character. The conversion character specifies the type of + * data, e.g. Logger, LogLevel, date, thread name. The format + * modifiers control such things as field width, padding, left and + * right justification. The following is a simple example. + * + * Let the conversion pattern be "%-5p [%t]: %m%n" and assume + * that the log4cplus environment was set to use a PatternLayout. Then the + * statements + *
+     * Logger root = Logger.getRoot();
+     * LOG4CPLUS_DEBUG(root, "Message 1");
+     * LOG4CPLUS_WARN(root, "Message 2");
+     * 
+ * would yield the output + *
+     * DEBUG [main]: Message 1
+     * WARN  [main]: Message 2  
+     * 
+ * + * Note that there is no explicit separator between text and + * conversion specifiers. The pattern parser knows when it has reached + * the end of a conversion specifier when it reads a conversion + * character. In the example above the conversion specifier + * "%-5p" means the LogLevel of the logging event should be left + * justified to a width of five characters. + * + * The recognized conversion characters are + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Conversion CharacterEffect
bUsed to output file name component of path name. + * E.g. main.cxx from path ../../main.cxx.
cUsed to output the logger of the logging event. The + * logger conversion specifier can be optionally followed by + * precision specifier, that is a decimal constant in + * brackets. + * + * If a precision specifier is given, then only the corresponding + * number of right most components of the logger name will be + * printed. By default the logger name is printed in full. + * + * For example, for the logger name "a.b.c" the pattern + * %c{2} will output "b.c". + * + *
dUsed to output the date of the logging event in UTC. + * + * The date conversion specifier may be followed by a date format + * specifier enclosed between braces. For example, %%d{%%H:%%M:%%s} + * or %%d{%%d %%b %%Y %%H:%%M:%%s}. If no date format + * specifier is given then %%d{%%d %%m %%Y %%H:%%M:%%s} + * is assumed. + * + * The Following format options are possible: + *
    + *
  • %%a -- Abbreviated weekday name
  • + *
  • %%A -- Full weekday name
  • + *
  • %%b -- Abbreviated month name
  • + *
  • %%B -- Full month name
  • + *
  • %%c -- Standard date and time string
  • + *
  • %%d -- Day of month as a decimal(1-31)
  • + *
  • %%H -- Hour(0-23)
  • + *
  • %%I -- Hour(1-12)
  • + *
  • %%j -- Day of year as a decimal(1-366)
  • + *
  • %%m -- Month as decimal(1-12)
  • + *
  • %%M -- Minute as decimal(0-59)
  • + *
  • %%p -- Locale's equivalent of AM or PM
  • + *
  • %%q -- milliseconds as decimal(0-999) -- Log4CPLUS specific + *
  • %%Q -- fractional milliseconds as decimal(0-999.999) -- Log4CPLUS specific + *
  • %%S -- Second as decimal(0-59)
  • + *
  • %%U -- Week of year, Sunday being first day(0-53)
  • + *
  • %%w -- Weekday as a decimal(0-6, Sunday being 0)
  • + *
  • %%W -- Week of year, Monday being first day(0-53)
  • + *
  • %%x -- Standard date string
  • + *
  • %%X -- Standard time string
  • + *
  • %%y -- Year in decimal without century(0-99)
  • + *
  • %%Y -- Year including century as decimal
  • + *
  • %%Z -- Time zone name
  • + *
  • %% -- The percent sign
  • + *
+ * + * Lookup the documentation for the strftime() function + * found in the <ctime> header for more information. + *
DUsed to output the date of the logging event in local time. + * + * All of the above information applies. + *
EUsed to output the value of a given environment variable. The + * name of is supplied as an argument in brackets. If the variable does + * exist then empty string will be used. + * + * For example, the pattern %E{HOME} will output the contents + * of the HOME environment variable. + *
FUsed to output the file name where the logging request was + * issued. + * + * NOTE Unlike log4j, there is no performance penalty for + * calling this method.
hUsed to output the hostname of this system (as returned + * by gethostname(2)). + * + * NOTE The hostname is only retrieved once at + * initialization. + * + *
HUsed to output the fully-qualified domain name of this + * system (as returned by gethostbyname(2) for the hostname + * returned by gethostname(2)). + * + * NOTE The hostname is only retrieved once at + * initialization. + * + *
lEquivalent to using "%F:%L" + * + * NOTE: Unlike log4j, there is no performance penalty for + * calling this method. + * + *
LUsed to output the line number from where the logging request + * was issued. + * + * NOTE: Unlike log4j, there is no performance penalty for + * calling this method. + * + *
mUsed to output the application supplied message associated with + * the logging event.
MUsed to output function name using + * __FUNCTION__ or similar macro. + * + * NOTE The __FUNCTION__ macro is not + * standard but it is common extension provided by all compilers + * (as of 2010). In case it is missing or in case this feature + * is disabled using the + * LOG4CPLUS_DISABLE_FUNCTION_MACRO macro, %M + * expands to an empty string.
nOutputs the platform dependent line separator character or + * characters. + *
pUsed to output the LogLevel of the logging event.
rUsed to output miliseconds since program start + * of the logging event.
tUsed to output the name of the thread that generated the + * logging event.
TUsed to output alternative name of the thread that generated the + * logging event.
iUsed to output the process ID of the process that generated the + * logging event.
xUsed to output the NDC (nested diagnostic context) associated + * with the thread that generated the logging event. + *
XUsed to output the MDC (mapped diagnostic context) + * associated with the thread that generated the logging + * event. It takes optional key parameter. Without the key + * paramter (%%X), it outputs the whole MDC map. With the key + * (%%X{key}), it outputs just the key's value. + *
"%%"The sequence "%%" outputs a single percent sign. + *
+ * + * By default the relevant information is output as is. However, + * with the aid of format modifiers it is possible to change the + * minimum field width, the maximum field width and justification. + * + * The optional format modifier is placed between the percent sign + * and the conversion character. + * + * The first optional format modifier is the left justification + * flag which is just the minus (-) character. Then comes the + * optional minimum field width modifier. This is a decimal + * constant that represents the minimum number of characters to + * output. If the data item requires fewer characters, it is padded on + * either the left or the right until the minimum width is + * reached. The default is to pad on the left (right justify) but you + * can specify right padding with the left justification flag. The + * padding character is space. If the data item is larger than the + * minimum field width, the field is expanded to accommodate the + * data. The value is never truncated. + * + * This behavior can be changed using the maximum field + * width modifier which is designated by a period followed by a + * decimal constant. If the data item is longer than the maximum + * field, then the extra characters are removed from the + * beginning of the data item and not from the end. For + * example, it the maximum field width is eight and the data item is + * ten characters long, then the first two characters of the data item + * are dropped. This behavior deviates from the printf function in C + * where truncation is done from the end. + * + * Below are various format modifier examples for the logger + * conversion specifier. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Format modifierleft justifyminimum widthmaximum widthcomment
%20cfalse20noneLeft pad with spaces if the logger name is less than 20 + * characters long. + *
%-20c true 20 none Right pad with + * spaces if the logger name is less than 20 characters long. + *
%.30cNAnone30Truncate from the beginning if the logger name is longer than 30 + * characters. + *
%20.30cfalse2030Left pad with spaces if the logger name is shorter than 20 + * characters. However, if logger name is longer than 30 characters, + * then truncate from the beginning. + *
%-20.30ctrue2030Right pad with spaces if the logger name is shorter than 20 + * characters. However, if logger name is longer than 30 characters, + * then truncate from the beginning. + *
+ * + * Below are some examples of conversion patterns. + * + *
+ * + *
"%r [%t] %-5p %c %x - %m%n" + *
This is essentially the TTCC layout. + * + *
"%-6r [%15.15t] %-5p %30.30c %x - %m%n" + * + *
Similar to the TTCC layout except that the relative time is + * right padded if less than 6 digits, thread name is right padded if + * less than 15 characters and truncated if longer and the logger + * name is left padded if shorter than 30 characters and truncated if + * longer. + * + *
+ * + * The above text is largely inspired from Peter A. Darnell and + * Philip E. Margolis' highly recommended book "C -- a Software + * Engineering Approach", ISBN 0-387-97389-3. + * + *

Properties

+ * + *
+ *
NDCMaxDepth
+ *
This property limits how many deepest NDC components will + * be printed by %%x specifier.
+ * + *
ConversionPattern
+ *
This property specifies conversion pattern.
+ *
+ * + */ + class LOG4CPLUS_EXPORT PatternLayout + : public Layout + { + public: + // Ctors and dtor + PatternLayout(const log4cplus::tstring& pattern); + PatternLayout(const log4cplus::helpers::Properties& properties); + virtual ~PatternLayout(); + + virtual void formatAndAppend(log4cplus::tostream& output, + const log4cplus::spi::InternalLoggingEvent& event); + + protected: + void init(const log4cplus::tstring& pattern, unsigned ndcMaxDepth = 0); + + // Data + log4cplus::tstring pattern; + std::vector parsedPattern; + + private: + // Disallow copying of instances of this class + PatternLayout(const PatternLayout&); + PatternLayout& operator=(const PatternLayout&); + }; + + + +} // end namespace log4cplus + +#endif // LOG4CPLUS_LAYOUT_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/log4judpappender.h b/sg_agent/thrid_party/logs/include/log4judpappender.h new file mode 100644 index 0000000..51302c7 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/log4judpappender.h @@ -0,0 +1,86 @@ +// -*- C++ -*- +// Module: LOG4CPLUS +// File: log4judpappender.h +// Created: 7/2012 +// Author: Siva Chandran P +// +// +// Copyright 2012-2013 Siva Chandran P +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_LOG4J_UDP_APPENDER_HEADER_ +#define LOG4CPLUS_LOG4J_UDP_APPENDER_HEADER_ + +#include +#include +#include + +namespace log4cplus { + + /** + * Sends log events as Log4j XML to a remote a log server. + * + * The Log4jUdpAppender has the following properties: + * + *
    + *
  • Remote logging is non-intrusive as far as the log event + * is concerned. In other words, the event will be logged with + * the same time stamp, NDC, location info as if it were logged + * locally by the client.
  • + * + *
  • Remote logging uses the UDP protocol.
  • + *
+ * + *

Properties

+ *
+ *
host
+ *
Remote host name to connect and send events to.
+ * + *
port
+ *
Port on remote host to send events to.
+ * + *
+ */ + class LOG4CPLUS_EXPORT Log4jUdpAppender : public Appender { + public: + // Ctors + Log4jUdpAppender(const log4cplus::tstring& host, int port); + Log4jUdpAppender(const log4cplus::helpers::Properties & properties); + + // Dtor + ~Log4jUdpAppender(); + + // Methods + virtual void close(); + + protected: + void openSocket(); + virtual void append(const spi::InternalLoggingEvent& event); + + // Data + log4cplus::helpers::Socket socket; + log4cplus::tstring host; + int port; + + private: + // Disallow copying of instances of this class + Log4jUdpAppender(const Log4jUdpAppender&); + Log4jUdpAppender& operator=(const Log4jUdpAppender&); + }; +} // end namespace log4cplus + +#endif // LOG4CPLUS_LOG4J_UDP_APPENDER_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/logger.h b/sg_agent/thrid_party/logs/include/logger.h new file mode 100644 index 0000000..d039761 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/logger.h @@ -0,0 +1,321 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: logger.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file + * This header defines the Logger class and the logging macros. */ + +#ifndef LOG4CPLUS_LOGGERHEADER_ +#define LOG4CPLUS_LOGGERHEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + +#include + + +namespace log4cplus +{ + // Forward declarations + + class Appender; + class Hierarchy; + class HierarchyLocker; + class DefaultLoggerFactory; + + namespace spi + { + + class LoggerImpl; + + } + + + /** \typedef std::vector LoggerList + * This is a list of {@link Logger Loggers}. */ + typedef std::vector LoggerList; + + + /** + * This is the central class in the log4cplus package. One of the + * distintive features of log4cplus are hierarchical loggers and their + * evaluation. + * + * See the user manual for an + * introduction on this class. + */ + class LOG4CPLUS_EXPORT Logger + : public log4cplus::spi::AppenderAttachable + { + public: + // Static Methods + /** + * Returns true if the named logger exists + * (in the default hierarchy). + * + * @param name The name of the logger to search for. + */ + static bool exists(const log4cplus::tstring& name); + + /* + * Returns all the currently defined loggers in the default + * hierarchy. + * + * The root logger is not included in the returned + * list. + */ + static LoggerList getCurrentLoggers(); + + /** + * Return the default Hierarchy instance. + */ + static Hierarchy& getDefaultHierarchy(); + + /** + * Retrieve a logger with name name. If the named + * logger already exists, then the existing instance will be returned. + * Otherwise, a new instance is created. + * + * By default, loggers do not have a set LogLevel but inherit + * it from the hierarchy. This is one of the central features of + * log4cplus. + * + * @param name The name of the logger to retrieve. + */ + static Logger getInstance(const log4cplus::tstring& name); + + /** + * Like getInstance() except that the type of logger + * instantiated depends on the type returned by the {@link + * spi::LoggerFactory#makeNewLoggerInstance} method of the + * factory parameter. + * + * This method is intended to be used by sub-classes. + * + * @param name The name of the logger to retrieve. + * @param factory A {@link spi::LoggerFactory} implementation that will + * actually create a new Instance. + */ + static Logger getInstance(const log4cplus::tstring& name, spi::LoggerFactory& factory); + + /** + * Return the root of the default logger hierrachy. + * + * The root logger is always instantiated and available. It's + * name is "root". + * + * Nevertheless, calling {@link #getInstance + * Logger.getInstance("root")} does not retrieve the root logger + * but a logger just under root named "root". + */ + static Logger getRoot(); + + /** + * Calling this method will safely close and remove all + * appenders in all the loggers including root contained in the + * default hierachy. + * + * Some appenders such as SocketAppender need to be closed before the + * application exits. Otherwise, pending logging events might be + * lost. + * + * The shutdown method is careful to close nested + * appenders before closing regular appenders. This is allows + * configurations where a regular appender is attached to a logger + * and again to a nested appender. + */ + static void shutdown(); + + // Non-Static Methods + /** + * If assertionVal parameter is false, then + * logs msg with FATAL_LOG_LEVEL log level. + * + * @param assertionVal Truth value of assertion condition. + * @param msg The message to print if assertion is + * false. + */ + void assertion(bool assertionVal, const log4cplus::tstring& msg) const; + + /** + * Close all attached appenders implementing the AppenderAttachable + * interface. + */ + void closeNestedAppenders() const; + + /** + * Check whether this logger is enabled for a given + * LogLevel passed as parameter. + * + * @return boolean True if this logger is enabled for ll. + */ + bool isEnabledFor(LogLevel ll) const; + + /** + * This generic form is intended to be used by wrappers. + */ + void log(LogLevel ll, const log4cplus::tstring& message, + const char* file=NULL, int line=-1) const; + + void log(spi::InternalLoggingEvent const &) const; + + /** + * This method creates a new logging event and logs the event + * without further checks. + */ + void forcedLog(LogLevel ll, const log4cplus::tstring& message, + const char* file=NULL, int line=-1) const; + + void forcedLog(spi::InternalLoggingEvent const &) const; + + /** + * Call the appenders in the hierrachy starting at + * this. If no appenders could be found, emit a + * warning. + * + * This method calls all the appenders inherited from the + * hierarchy circumventing any evaluation of whether to log or not + * to log the particular log request. + * + * @param event the event to log. + */ + void callAppenders(const spi::InternalLoggingEvent& event) const; + + /** + * Starting from this logger, search the logger hierarchy for a + * "set" LogLevel and return it. Otherwise, return the LogLevel of the + * root logger. + * + * The Logger class is designed so that this method executes as + * quickly as possible. + */ + LogLevel getChainedLogLevel() const; + + /** + * Returns the assigned LogLevel, if any, for this Logger. + * + * @return LogLevel - the assigned LogLevel, can be NOT_SET_LOG_LEVEL. + */ + LogLevel getLogLevel() const; + + /** + * Set the LogLevel of this Logger. + */ + void setLogLevel(LogLevel ll); + + /** + * Return the the {@link Hierarchy} where this Logger instance is + * attached. + */ + Hierarchy& getHierarchy() const; + + /** + * Return the logger name. + */ + log4cplus::tstring const & getName() const; + + /** + * Get the additivity flag for this Logger instance. + */ + bool getAdditivity() const; + + /** + * Set the additivity flag for this Logger instance. + */ + void setAdditivity(bool additive); + + // AppenderAttachable Methods + virtual void addAppender(SharedAppenderPtr newAppender); + + virtual SharedAppenderPtrList getAllAppenders(); + + virtual SharedAppenderPtr getAppender(const log4cplus::tstring& name); + + virtual void removeAllAppenders(); + + virtual void removeAppender(SharedAppenderPtr appender); + + virtual void removeAppender(const log4cplus::tstring& name); + + Logger (); + Logger(const Logger& rhs); + Logger& operator=(const Logger& rhs); +#if defined (LOG4CPLUS_HAVE_RVALUE_REFS) + Logger (Logger && rhs); + Logger & operator = (Logger && rhs); +#endif + virtual ~Logger(); + + void swap (Logger &); + + /** + * Used to retrieve the parent of this Logger in the + * Logger tree. + */ + Logger getParent() const; + + protected: + // Data + /** This is a pointer to the implementation class. */ + spi::LoggerImpl * value; + + private: + // Ctors + /** + * This constructor created a new Logger instance + * with a pointer to a Logger implementation. + * + * You should not create loggers directly. + * + * @param ptr A pointer to the Logger implementation. This value + * cannot be NULL. + */ + LOG4CPLUS_PRIVATE Logger(spi::LoggerImpl * ptr); + + // Friends + friend class log4cplus::spi::LoggerImpl; + friend class log4cplus::Hierarchy; + friend class log4cplus::HierarchyLocker; + friend class log4cplus::DefaultLoggerFactory; + }; + + + /** + * This class is used to create the default implementation of + * the Logger class + */ + class LOG4CPLUS_EXPORT DefaultLoggerFactory : public spi::LoggerFactory { + public: + Logger makeNewLoggerInstance(const log4cplus::tstring& name, Hierarchy& h); + }; + + +} // end namespace log4cplus + + +#endif // LOG4CPLUS_LOGGERHEADER_ diff --git a/sg_agent/thrid_party/logs/include/loggingmacros.h b/sg_agent/thrid_party/logs/include/loggingmacros.h new file mode 100644 index 0000000..4e108b8 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/loggingmacros.h @@ -0,0 +1,457 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: loggingmacros.h +// Created: 8/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file + * This header defines the logging macros. */ + +#ifndef LOG4CPLUS_LOGGING_MACROS_HEADER_ +#define LOG4CPLUS_LOGGING_MACROS_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include + + +#if defined(_MSC_VER) +#define LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + __pragma (warning (push)) \ + __pragma (warning (disable:4127)) + +#define LOG4CPLUS_RESTORE_DOWHILE_WARNING() \ + __pragma (warning (pop)) + +#else +#define LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() /* empty */ +#define LOG4CPLUS_RESTORE_DOWHILE_WARNING() /* empty */ + +#endif + +#define LOG4CPLUS_DOWHILE_NOTHING() \ + LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + do { } while (0) \ + LOG4CPLUS_RESTORE_DOWHILE_WARNING() + +#if defined(LOG4CPLUS_DISABLE_FATAL) && !defined(LOG4CPLUS_DISABLE_ERROR) +#define LOG4CPLUS_DISABLE_ERROR +#endif +#if defined(LOG4CPLUS_DISABLE_ERROR) && !defined(LOG4CPLUS_DISABLE_WARN) +#define LOG4CPLUS_DISABLE_WARN +#endif +#if defined(LOG4CPLUS_DISABLE_WARN) && !defined(LOG4CPLUS_DISABLE_INFO) +#define LOG4CPLUS_DISABLE_INFO +#endif +#if defined(LOG4CPLUS_DISABLE_INFO) && !defined(LOG4CPLUS_DISABLE_DEBUG) +#define LOG4CPLUS_DISABLE_DEBUG +#endif +#if defined(LOG4CPLUS_DISABLE_DEBUG) && !defined(LOG4CPLUS_DISABLE_TRACE) +#define LOG4CPLUS_DISABLE_TRACE +#endif + + +namespace log4cplus +{ + +namespace detail +{ + + +inline +Logger +macros_get_logger (Logger const & logger) +{ + return logger; +} + + +inline +Logger const & +macros_get_logger (Logger & logger) +{ + return logger; +} + + +#if defined (LOG4CPLUS_HAVE_RVALUE_REFS) +inline +Logger +macros_get_logger (Logger && logger) +{ + return std::move (logger); +} + +#endif + + +inline +Logger +macros_get_logger (tstring const & logger) +{ + return Logger::getInstance (logger); +} + + +inline +Logger +macros_get_logger (tchar const * logger) +{ + return Logger::getInstance (logger); +} + + +LOG4CPLUS_EXPORT void clear_tostringstream (tostringstream &); + + +LOG4CPLUS_EXPORT log4cplus::tostringstream & get_macro_body_oss (); +LOG4CPLUS_EXPORT log4cplus::helpers::snprintf_buf & get_macro_body_snprintf_buf (); +LOG4CPLUS_EXPORT void macro_forced_log (log4cplus::Logger const &, + log4cplus::LogLevel, log4cplus::tstring const &, char const *, int, + char const *); + + +} // namespace detail + +} // namespace log4cplus + + +#if ! defined (LOG4CPLUS_DISABLE_FUNCTION_MACRO) \ + && ! defined (LOG4CPLUS_MACRO_FUNCTION) +# if defined (LOG4CPLUS_HAVE_FUNCSIG_MACRO) +# define LOG4CPLUS_MACRO_FUNCTION() __FUNCSIG__ +# elif defined (LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO) +# define LOG4CPLUS_MACRO_FUNCTION() __PRETTY_FUNCTION__ +# elif defined (LOG4CPLUS_HAVE_FUNCTION_MACRO) +# define LOG4CPLUS_MACRO_FUNCTION() __FUNCTION__ +# elif defined (LOG4CPLUS_HAVE_FUNC_SYMBOL) +# define LOG4CPLUS_MACRO_FUNCTION() __func__ +# endif +#endif + +#if ! defined (LOG4CPLUS_MACRO_FUNCTION) +# define LOG4CPLUS_MACRO_FUNCTION() 0 +#endif + +// Make TRACE and DEBUG log level unlikely and INFO, WARN, ERROR and +// FATAL log level likely. +#define LOG4CPLUS_MACRO_TRACE_LOG_LEVEL(pred) \ + LOG4CPLUS_UNLIKELY (pred) +#define LOG4CPLUS_MACRO_DEBUG_LOG_LEVEL(pred) \ + LOG4CPLUS_UNLIKELY (pred) +#define LOG4CPLUS_MACRO_INFO_LOG_LEVEL(pred) \ + LOG4CPLUS_LIKELY (pred) +#define LOG4CPLUS_MACRO_WARN_LOG_LEVEL(pred) \ + LOG4CPLUS_LIKELY (pred) +#define LOG4CPLUS_MACRO_ERROR_LOG_LEVEL(pred) \ + LOG4CPLUS_LIKELY (pred) +#define LOG4CPLUS_MACRO_FATAL_LOG_LEVEL(pred) \ + LOG4CPLUS_LIKELY (pred) + + +//! Dispatch to LOG4CPLUS_MACRO_LOGLEVEL_* depending on log level. +#define LOG4CPLUS_MACRO_LOGLEVEL_PRED(pred, logLevel) \ + LOG4CPLUS_MACRO_ ## logLevel (pred) + + +// Either use temporary instances of ostringstream +// and snprintf_buf, or use thread-local instances. +#if defined (LOG4CPLUS_MACRO_DISABLE_TLS) +# define LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM(var) \ + log4cplus::tostringstream var + +# define LOG4CPLUS_MACRO_INSTANTIATE_SNPRINTF_BUF(var) \ + log4cplus::helpers::snprintf_buf var + +#else +# define LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM(var) \ + log4cplus::tostringstream & var \ + = log4cplus::detail::get_macro_body_oss () + +# define LOG4CPLUS_MACRO_INSTANTIATE_SNPRINTF_BUF(var) \ + log4cplus::helpers::snprintf_buf & var \ + = log4cplus::detail::get_macro_body_snprintf_buf () + +#endif + + +#define LOG4CPLUS_MACRO_BODY(logger, logEvent, logLevel) \ + LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + do { \ + log4cplus::Logger const & _l \ + = log4cplus::detail::macros_get_logger (logger); \ + if (LOG4CPLUS_MACRO_LOGLEVEL_PRED ( \ + _l.isEnabledFor (log4cplus::logLevel), logLevel)) { \ + LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM (_log4cplus_buf); \ + _log4cplus_buf << logEvent; \ + log4cplus::detail::macro_forced_log (_l, \ + log4cplus::logLevel, _log4cplus_buf.str(), \ + __FILE__, __LINE__, LOG4CPLUS_MACRO_FUNCTION ()); \ + } \ + } while (0) \ + LOG4CPLUS_RESTORE_DOWHILE_WARNING() + + +#define LOG4CPLUS_MACRO_STR_BODY(logger, logEvent, logLevel) \ + LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + do { \ + log4cplus::Logger const & _l \ + = log4cplus::detail::macros_get_logger (logger); \ + if (LOG4CPLUS_MACRO_LOGLEVEL_PRED ( \ + _l.isEnabledFor (log4cplus::logLevel), logLevel)) { \ + log4cplus::detail::macro_forced_log (_l, \ + log4cplus::logLevel, logEvent, \ + __FILE__, __LINE__, LOG4CPLUS_MACRO_FUNCTION ()); \ + } \ + } while(0) \ + LOG4CPLUS_RESTORE_DOWHILE_WARNING() + +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_MACRO_FMT_BODY(logger, logLevel, ...) \ + LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + do { \ + log4cplus::Logger const & _l \ + = log4cplus::detail::macros_get_logger (logger); \ + if (LOG4CPLUS_MACRO_LOGLEVEL_PRED ( \ + _l.isEnabledFor (log4cplus::logLevel), logLevel)) { \ + LOG4CPLUS_MACRO_INSTANTIATE_SNPRINTF_BUF (_snpbuf); \ + log4cplus::tchar const * _logEvent \ + = _snpbuf.print (__VA_ARGS__); \ + log4cplus::detail::macro_forced_log (_l, \ + log4cplus::logLevel, _logEvent, \ + __FILE__, __LINE__, LOG4CPLUS_MACRO_FUNCTION ()); \ + } \ + } while(0) \ + LOG4CPLUS_RESTORE_DOWHILE_WARNING() + +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_MACRO_FMT_BODY(logger, logLevel, logArgs...) \ + LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + do { \ + log4cplus::Logger const & _l \ + = log4cplus::detail::macros_get_logger (logger); \ + if (LOG4CPLUS_MACRO_LOGLEVEL_PRED ( \ + _l.isEnabledFor (log4cplus::logLevel), logLevel)) { \ + LOG4CPLUS_MACRO_INSTANTIATE_SNPRINTF_BUF (_snpbuf); \ + log4cplus::tchar const * _logEvent \ + = _snpbuf.print (logArgs); \ + log4cplus::detail::macro_forced_log (_l, \ + log4cplus::logLevel, _logEvent, \ + __FILE__, __LINE__, LOG4CPLUS_MACRO_FUNCTION ()); \ + } \ + } while(0) \ + LOG4CPLUS_RESTORE_DOWHILE_WARNING() + +#endif + + +/** + * @def LOG4CPLUS_TRACE(logger, logEvent) This macro creates a + * TraceLogger to log a TRACE_LOG_LEVEL message to logger + * upon entry and exiting of a method. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_TRACE) +#define LOG4CPLUS_TRACE_METHOD(logger, logEvent) \ + log4cplus::TraceLogger _log4cplus_trace_logger(logger, logEvent, \ + __FILE__, __LINE__); +#define LOG4CPLUS_TRACE(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, TRACE_LOG_LEVEL) +#define LOG4CPLUS_TRACE_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, TRACE_LOG_LEVEL) + +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_TRACE_FMT(logger, ...) \ + LOG4CPLUS_MACRO_FMT_BODY (logger, TRACE_LOG_LEVEL, __VA_ARGS__) +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_TRACE_FMT(logger, logArgs...) \ + LOG4CPLUS_MACRO_FMT_BODY(logger, TRACE_LOG_LEVEL, logArgs) +#endif + +#else +#define LOG4CPLUS_TRACE_METHOD(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_TRACE(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_TRACE_STR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_TRACE_FMT(logger, logFmt, ...) LOG4CPLUS_DOWHILE_NOTHING() +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_TRACE_FMT(logger, logFmt, logArgs...) LOG4CPLUS_DOWHILE_NOTHING() +#endif + +#endif + +/** + * @def LOG4CPLUS_DEBUG(logger, logEvent) This macro is used to log a + * DEBUG_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_DEBUG) +#define LOG4CPLUS_DEBUG(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, DEBUG_LOG_LEVEL) +#define LOG4CPLUS_DEBUG_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, DEBUG_LOG_LEVEL) + +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_DEBUG_FMT(logger, ...) \ + LOG4CPLUS_MACRO_FMT_BODY (logger, DEBUG_LOG_LEVEL, __VA_ARGS__) +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_DEBUG_FMT(logger, logArgs...) \ + LOG4CPLUS_MACRO_FMT_BODY(logger, DEBUG_LOG_LEVEL, logArgs) +#endif + +#else +#define LOG4CPLUS_DEBUG(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_DEBUG_STR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_DEBUG_FMT(logger, ...) LOG4CPLUS_DOWHILE_NOTHING() +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_DEBUG_FMT(logger, logArgs...) LOG4CPLUS_DOWHILE_NOTHING() +#endif + +#endif + +/** + * @def LOG4CPLUS_INFO(logger, logEvent) This macro is used to log a + * INFO_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_INFO) +#define LOG4CPLUS_INFO(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, INFO_LOG_LEVEL) +#define LOG4CPLUS_INFO_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, INFO_LOG_LEVEL) + +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_INFO_FMT(logger, ...) \ + LOG4CPLUS_MACRO_FMT_BODY (logger, INFO_LOG_LEVEL, __VA_ARGS__) +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_INFO_FMT(logger, logArgs...) \ + LOG4CPLUS_MACRO_FMT_BODY(logger, INFO_LOG_LEVEL, logArgs) +#endif + +#else +#define LOG4CPLUS_INFO(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_INFO_STR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_INFO_FMT(logger, ...) LOG4CPLUS_DOWHILE_NOTHING() +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_INFO_FMT(logger, logArgs...) LOG4CPLUS_DOWHILE_NOTHING() +#endif + +#endif + +/** + * @def LOG4CPLUS_WARN(logger, logEvent) This macro is used to log a + * WARN_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_WARN) +#define LOG4CPLUS_WARN(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, WARN_LOG_LEVEL) +#define LOG4CPLUS_WARN_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, WARN_LOG_LEVEL) + +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_WARN_FMT(logger, ...) \ + LOG4CPLUS_MACRO_FMT_BODY (logger, WARN_LOG_LEVEL, __VA_ARGS__) +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_WARN_FMT(logger, logArgs...) \ + LOG4CPLUS_MACRO_FMT_BODY(logger, WARN_LOG_LEVEL, logArgs) +#endif + +#else +#define LOG4CPLUS_WARN(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_WARN_STR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_WARN_FMT(logger, ...) LOG4CPLUS_DOWHILE_NOTHING() +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_WARN_FMT(logger, logArgs...) LOG4CPLUS_DOWHILE_NOTHING() +#endif + +#endif + +/** + * @def LOG4CPLUS_ERROR(logger, logEvent) This macro is used to log a + * ERROR_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_ERROR) +#define LOG4CPLUS_ERROR(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, ERROR_LOG_LEVEL) +#define LOG4CPLUS_ERROR_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, ERROR_LOG_LEVEL) + +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_ERROR_FMT(logger, ...) \ + LOG4CPLUS_MACRO_FMT_BODY (logger, ERROR_LOG_LEVEL, __VA_ARGS__) +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_ERROR_FMT(logger, logArgs...) \ + LOG4CPLUS_MACRO_FMT_BODY(logger, ERROR_LOG_LEVEL, logArgs) +#endif + +#else +#define LOG4CPLUS_ERROR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_ERROR_STR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_ERROR_FMT(logger, ...) LOG4CPLUS_DOWHILE_NOTHING() +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_ERROR_FMT(logger, logArgs...) LOG4CPLUS_DOWHILE_NOTHING() +#endif + +#endif + +/** + * @def LOG4CPLUS_FATAL(logger, logEvent) This macro is used to log a + * FATAL_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_FATAL) +#define LOG4CPLUS_FATAL(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, FATAL_LOG_LEVEL) +#define LOG4CPLUS_FATAL_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, FATAL_LOG_LEVEL) + +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_FATAL_FMT(logger, ...) \ + LOG4CPLUS_MACRO_FMT_BODY (logger, FATAL_LOG_LEVEL, __VA_ARGS__) +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_FATAL_FMT(logger, logArgs...) \ + LOG4CPLUS_MACRO_FMT_BODY(logger, FATAL_LOG_LEVEL, logArgs) +#endif + +#else +#define LOG4CPLUS_FATAL(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_FATAL_STR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_FATAL_FMT(logger, ...) LOG4CPLUS_DOWHILE_NOTHING() +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_FATAL_FMT(logger, logArgs...) LOG4CPLUS_DOWHILE_NOTHING() +#endif + +#endif + +#endif /* LOG4CPLUS_LOGGING_MACROS_HEADER_ */ diff --git a/sg_agent/thrid_party/logs/include/loglevel.h b/sg_agent/thrid_party/logs/include/loglevel.h new file mode 100644 index 0000000..d7e0db2 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/loglevel.h @@ -0,0 +1,209 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: loglevel.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file + * This header defines the LogLevel type. + */ + +#ifndef LOG4CPLUS_LOGLEVEL_HEADER_ +#define LOG4CPLUS_LOGLEVEL_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus { + + /** + * \typedef int LogLevel + * Defines the minimum set of priorities recognized by the system, + * that is {@link #FATAL_LOG_LEVEL}, {@link #ERROR_LOG_LEVEL}, {@link + * #WARN_LOG_LEVEL}, {@link #INFO_LOG_LEVEL}, {@link #DEBUG_LOG_LEVEL}, + * and {@link #TRACE_LOG_LEVEL}. + */ + typedef int LogLevel; + + /** \var const LogLevel OFF_LOG_LEVEL + * The OFF_LOG_LEVEL LogLevel is used during configuration to + * turn off logging. */ + const LogLevel OFF_LOG_LEVEL = 60000; + + /** \var const LogLevel FATAL_LOG_LEVEL + * The FATAL_LOG_LEVEL LogLevel designates very severe error + * events that will presumably lead the application to abort. */ + const LogLevel FATAL_LOG_LEVEL = 50000; + + /** \var const LogLevel ERROR_LOG_LEVEL + * The ERROR_LOG_LEVEL LogLevel designates error events that + * might still allow the application to continue running. */ + const LogLevel ERROR_LOG_LEVEL = 40000; + + /** \var const LogLevel WARN_LOG_LEVEL + * The WARN_LOG_LEVEL LogLevel designates potentially harmful + * situations. */ + const LogLevel WARN_LOG_LEVEL = 30000; + + /** \var const LogLevel INFO_LOG_LEVEL + * The INFO_LOG_LEVEL LogLevel designates informational + * messages that highlight the progress of the application at + * coarse-grained level. */ + const LogLevel INFO_LOG_LEVEL = 20000; + + /** \var const LogLevel DEBUG_LOG_LEVEL + * The DEBUG_LOG_LEVEL LogLevel designates fine-grained + * informational events that are most useful to debug an application. */ + const LogLevel DEBUG_LOG_LEVEL = 10000; + + /** \var const LogLevel TRACE_LOG_LEVEL + * The TRACE_LOG_LEVEL LogLevel is used to "trace" entry + * and exiting of methods. */ + const LogLevel TRACE_LOG_LEVEL = 0; + + /** \var const LogLevel ALL_LOG_LEVEL + * The ALL_LOG_LEVEL LogLevel is used during configuration to + * turn on all logging. */ + const LogLevel ALL_LOG_LEVEL = TRACE_LOG_LEVEL; + + /** \var const LogLevel NOT_SET_LOG_LEVEL + * The NOT_SET_LOG_LEVEL LogLevel is used to indicated that + * no particular LogLevel is desired and that the default should be used. + */ + const LogLevel NOT_SET_LOG_LEVEL = -1; + + + /** + * This method type defined the signature of methods that convert LogLevels + * into strings. + * + * Note: Must return an empty tstring for unrecognized values. + */ + typedef log4cplus::tstring const & (*LogLevelToStringMethod)(LogLevel); + + //! This function type is for log4cplus 1.0.x callbacks. + typedef log4cplus::tstring (*LogLevelToStringMethod_1_0) (LogLevel); + + + /** + * This method type defined the signature of methods that convert strings + * into LogLevels. + * + * Note: Must return NOT_SET_LOG_LEVEL for unrecognized values. + */ + typedef LogLevel (*StringToLogLevelMethod)(const log4cplus::tstring&); + + + + /** + * This class is used to "manage" LogLevel definitions. This class is also + * how "derived" LogLevels are created. Here are the steps to creating a + * "derived" LogLevel: + *
    + *
  1. Create a LogLevel constant (greater than 0)
  2. + *
  3. Define a string to represent that constant
  4. + *
  5. Implement a LogLevelToStringMethod method.
  6. + *
  7. Implement a StringToLogLevelMethod method.
  8. + *
  9. create a "static initializer" that registers those 2 methods + * with the LogLevelManager singleton.
  10. + *
+ */ + class LOG4CPLUS_EXPORT LogLevelManager { + public: + LogLevelManager(); + ~LogLevelManager(); + + /** + * This method is called by all Layout classes to convert a LogLevel + * into a string. + * + * Note: It traverses the list of LogLevelToStringMethod + * to do this, so all "derived" LogLevels are recognized as well. + */ + log4cplus::tstring const & toString(LogLevel ll) const; + + /** + * This method is called by all classes internally to log4cplus to + * convert a string into a LogLevel. + * + * Note: It traverses the list of StringToLogLevelMethod + * to do this, so all "derived" LogLevels are recognized as well. + */ + LogLevel fromString(const log4cplus::tstring& s) const; + + /** + * When creating a "derived" LogLevel, a LogLevelToStringMethod + * should be defined and registered with the LogLevelManager by calling + * this method. + * + * @see pushFromStringMethod + */ + void pushToStringMethod(LogLevelToStringMethod newToString); + + //! For compatibility with log4cplus 1.0.x. + void pushToStringMethod(LogLevelToStringMethod_1_0 newToString); + + /** + * When creating a "derived" LogLevel, a StringToLogLevelMethod + * should be defined and registered with the LogLevelManager by calling + * this method. + * + * @see pushToStringMethod + */ + void pushFromStringMethod(StringToLogLevelMethod newFromString); + + private: + // Data + struct LogLevelToStringMethodRec + { + union + { + LogLevelToStringMethod func; + LogLevelToStringMethod_1_0 func_1_0; + }; + bool use_1_0; + }; + + typedef std::vector LogLevelToStringMethodList; + LogLevelToStringMethodList toStringMethods; + + typedef std::vector StringToLogLevelMethodList; + StringToLogLevelMethodList fromStringMethods; + + // Disable Copy + LogLevelManager(const LogLevelManager&); + LogLevelManager& operator=(const LogLevelManager&); + }; + + /** + * Returns the singleton LogLevelManager. + */ + LOG4CPLUS_EXPORT LogLevelManager& getLogLevelManager(); + +} + + +#endif // LOG4CPLUS_LOGLEVEL_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/mdc.h b/sg_agent/thrid_party/logs/include/mdc.h new file mode 100644 index 0000000..ff23774 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/mdc.h @@ -0,0 +1,77 @@ +// -*- C++ -*- +// Copyright (C) 2010-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_MDC_H_HEADER +#define LOG4CPLUS_MDC_H_HEADER + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#include + + +namespace log4cplus +{ + + +typedef std::map MappedDiagnosticContextMap; + + +class LOG4CPLUS_EXPORT MDC +{ +public: + /** + * Clear any nested diagnostic information if any. This method is + * useful in cases where the same thread can be potentially used + * over and over in different unrelated contexts. + */ + void clear(); + + void put (tstring const & key, tstring const & value); + bool get (tstring * value, tstring const & key) const; + void remove (tstring const & key); + + MappedDiagnosticContextMap const & getContext () const; + + // Public ctor and dtor but only to be used by internal::DefaultContext. + MDC (); + virtual ~MDC (); + +private: + LOG4CPLUS_PRIVATE static MappedDiagnosticContextMap * getPtr (); +}; + + +LOG4CPLUS_EXPORT MDC & getMDC (); + + +} // namespace log4cplus + + +#endif // LOG4CPLUS_MDC_H_HEADER diff --git a/sg_agent/thrid_party/logs/include/ndc.h b/sg_agent/thrid_party/logs/include/ndc.h new file mode 100644 index 0000000..26e1b59 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/ndc.h @@ -0,0 +1,332 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: ndc.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file + * This header defined the NDC class. + */ + +#ifndef _LO4CPLUS_NDC_HEADER_ +#define _LO4CPLUS_NDC_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#include +#include + + +namespace log4cplus { + // Forward declarations + struct DiagnosticContext; + typedef std::deque DiagnosticContextStack; + + /** + * The NDC class implements nested diagnostic contexts as + * defined by Neil Harrison in the article "Patterns for Logging + * Diagnostic Messages" part of the book "Pattern Languages of + * Program Design 3" edited by Martin et al. + * + * A Nested Diagnostic Context, or NDC in short, is an instrument + * to distinguish interleaved log output from different sources. Log + * output is typically interleaved when a server handles multiple + * clients near-simultaneously. + * + * Interleaved log output can still be meaningful if each log entry + * from different contexts had a distinctive stamp. This is where NDCs + * come into play. + * + * Note that NDCs are managed on a per thread + * basis. NDC operations such as {@link #push}, {@link + * #pop}, {@link #clear}, {@link #getDepth} and {@link #setMaxDepth} + * affect the NDC of the current thread only. NDCs of other + * threads remain unaffected. + * + * For example, a server can build a per client request NDC + * consisting the clients host name and other information contained in + * the the request. Cookies are another source of distinctive + * information. To build an NDC one uses the {@link #push} + * operation. Simply put, + * + *
    + *
  • Contexts can be nested. + * + *
  • When entering a context, call getNDC().push(). As a + * side effect, if there is no nested diagnostic context for the + * current thread, this method will create it. + * + *
  • When leaving a context, call getNDC().pop(). + * + *
  • When exiting a thread make sure to call {@link #remove + * NDC.remove()}. + *
+ * + * There is no penalty for forgetting to match each + * push operation with a corresponding pop, + * except the obvious mismatch between the real application context + * and the context set in the NDC. Use of the {@link NDCContextCreator} + * class can automate this process and make your code exception-safe. + * + * If configured to do so, {@link log4cplus::PatternLayout} and + * {@link log4cplus::TTCCLayout} instances automatically retrieve + * the nested diagnostic context for the current thread without + * any user intervention. Hence, even if a server is serving + * multiple clients simultaneously, the logs emanating from the + * same code (belonging to the same logger) can still be + * distinguished because each client request will have a different + * NDC tag. + * + * Heavy duty systems should call the {@link #remove} method when + * leaving the run method of a thread. This ensures that the memory + * used by the thread can be freed. + * + * A thread may inherit the nested diagnostic context of another + * (possibly parent) thread using the {@link #inherit inherit} + * method. A thread may obtain a copy of its NDC with the {@link + * #cloneStack cloneStack} method and pass the reference to any other + * thread, in particular to a child. + */ + class LOG4CPLUS_EXPORT NDC + { + public: + /** + * Clear any nested diagnostic information if any. This method is + * useful in cases where the same thread can be potentially used + * over and over in different unrelated contexts. + * + * This method is equivalent to calling the {@link #setMaxDepth} + * method with a zero maxDepth argument. + */ + void clear(); + + /** + * Clone the diagnostic context for the current thread. + * + * Internally a diagnostic context is represented as a stack. A + * given thread can supply the stack (i.e. diagnostic context) to a + * child thread so that the child can inherit the parent thread's + * diagnostic context. + * + * The child thread uses the {@link #inherit inherit} method to + * inherit the parent's diagnostic context. + * + * @return Stack A clone of the current thread's diagnostic context. + */ + DiagnosticContextStack cloneStack() const; + + /** + * Inherit the diagnostic context of another thread. + * + * The parent thread can obtain a reference to its diagnostic + * context using the {@link #cloneStack} method. It should + * communicate this information to its child so that it may inherit + * the parent's diagnostic context. + * + * The parent's diagnostic context is cloned before being + * inherited. In other words, once inherited, the two diagnostic + * contexts can be managed independently. + * + * @param stack The diagnostic context of the parent thread. + */ + void inherit(const DiagnosticContextStack& stack); + + /** + * Used when printing the diagnostic context. + */ + log4cplus::tstring const & get() const; + + /** + * Get the current nesting depth of this diagnostic context. + * + * @see #setMaxDepth + */ + std::size_t getDepth() const; + + /** + * Clients should call this method before leaving a diagnostic + * context. + * + * The returned value is the value that was pushed last. If no + * context is available, then the empty string "" is + * returned. If each call to push() is paired with a call to + * pop() (even in presence of thrown exceptions), the last + * pop() call frees the memory used by NDC for this + * thread. Otherwise, remove() must be called at the end of + * the thread to free the memory used by NDC for the thread. + * + * @return String The innermost diagnostic context. + * + * @see NDCContextCreator, remove(), push() + */ + log4cplus::tstring pop(); + + /** + * Same as pop() but without the return value. + */ + void pop_void (); + + /** + * Looks at the last diagnostic context at the top of this NDC + * without removing it. + * + * The returned value is the value that was pushed last. If no + * context is available, then the empty string "" is returned. + * + * @return String The innermost diagnostic context. + */ + log4cplus::tstring const & peek() const; + + /** + * Push new diagnostic context information for the current thread. + * + * The contents of the message parameter is + * determined solely by the client. Each call to push() should + * be paired with a call to pop(). + * + * @param message The new diagnostic context information. + * + * @see NDCContextCreator, pop(), remove() + */ + void push(const log4cplus::tstring& message); + void push(tchar const * message); + + /** + * Remove the diagnostic context for this thread. + * + * Each thread that created a diagnostic context by calling + * push() should call this method before exiting. Otherwise, + * the memory used by the thread cannot be reclaimed. It is + * possible to omit this call if and only if each push() call + * is always paired with a pop() call (even in presence of + * thrown exceptions). Then the memory used by NDC will be + * returned by the last pop() call and a call to remove() will + * be no-op. + */ + void remove(); + + /** + * Set maximum depth of this diagnostic context. If the current + * depth is smaller or equal to maxDepth, then no + * action is taken. + * + * This method is a convenient alternative to multiple {@link + * #pop} calls. Moreover, it is often the case that at the end of + * complex call sequences, the depth of the NDC is + * unpredictable. The setMaxDepth method circumvents + * this problem. + * + * For example, the combination + *
+         *    void foo() {
+         *       std::size_t depth = NDC.getDepth();
+         *
+         *       ... complex sequence of calls
+         *
+         *       NDC.setMaxDepth(depth);
+         *    }
+         * 
+ * + * ensures that between the entry and exit of foo the depth of the + * diagnostic stack is conserved. + * + * Note: Use of the {@link NDCContextCreator} class will solve + * this particular problem. + * + * @see #getDepth + */ + void setMaxDepth(std::size_t maxDepth); + + // Public ctor but only to be used by internal::DefaultContext. + NDC(); + + // Dtor + virtual ~NDC(); + + private: + // Methods + LOG4CPLUS_PRIVATE static DiagnosticContextStack* getPtr(); + + template + LOG4CPLUS_PRIVATE + void push_worker (StringType const &); + + // Disallow construction (and copying) except by getNDC() + NDC(const NDC&); + NDC& operator=(const NDC&); + }; + + + /** + * Return a reference to the singleton object. + */ + LOG4CPLUS_EXPORT NDC& getNDC(); + + + /** + * This is the internal object that is stored on the NDC stack. + */ + struct LOG4CPLUS_EXPORT DiagnosticContext + { + // Ctors + DiagnosticContext(const log4cplus::tstring& message, + DiagnosticContext const * parent); + DiagnosticContext(tchar const * message, + DiagnosticContext const * parent); + DiagnosticContext(const log4cplus::tstring& message); + DiagnosticContext(tchar const * message); + DiagnosticContext(DiagnosticContext const &); + DiagnosticContext & operator = (DiagnosticContext const &); + +#if defined (LOG4CPLUS_HAVE_RVALUE_REFS) + DiagnosticContext(DiagnosticContext &&); + DiagnosticContext & operator = (DiagnosticContext &&); +#endif + + void swap (DiagnosticContext &); + + // Data + log4cplus::tstring message; /*!< The message at this context level. */ + log4cplus::tstring fullMessage; /*!< The entire message stack. */ + }; + + + /** + * This class ensures that a {@link NDC#push} call is always matched with + * a {@link NDC#pop} call even in the face of exceptions. + */ + class LOG4CPLUS_EXPORT NDCContextCreator { + public: + /** Pushes msg onto the NDC stack. */ + NDCContextCreator(const log4cplus::tstring& msg); + NDCContextCreator(tchar const * msg); + + /** Pops the NDC stack. */ + ~NDCContextCreator(); + }; + +} // end namespace log4cplus + + +#endif // _LO4CPLUS_NDC_HEADER_ diff --git a/sg_agent/thrid_party/logs/include/nteventlogappender.h b/sg_agent/thrid_party/logs/include/nteventlogappender.h new file mode 100644 index 0000000..9ea3a89 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/nteventlogappender.h @@ -0,0 +1,84 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: nteventlogappender.h +// Created: 4/2003 +// Author: Michael CATANZARITI +// +// Copyright 2003-2013 Michael CATANZARITI +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_NT_EVENT_LOG_APPENDER_HEADER_ +#define LOG4CPLUS_NT_EVENT_LOG_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (LOG4CPLUS_HAVE_NT_EVENT_LOG) + +#include +#include + + +namespace log4cplus { + + /** + * Appends log events to NT EventLog. + */ + class LOG4CPLUS_EXPORT NTEventLogAppender : public Appender { + public: + // ctors + NTEventLogAppender(const log4cplus::tstring& server, + const log4cplus::tstring& log, + const log4cplus::tstring& source); + NTEventLogAppender(const log4cplus::helpers::Properties & properties); + + // dtor + virtual ~NTEventLogAppender(); + + // public Methods + virtual void close(); + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + virtual WORD getEventType(const spi::InternalLoggingEvent& event); + virtual WORD getEventCategory(const spi::InternalLoggingEvent& event); + void init(); + + /* + * Add this source with appropriate configuration keys to the registry. + */ + void addRegistryInfo(); + + // Data + log4cplus::tstring server; + log4cplus::tstring log; + log4cplus::tstring source; + HANDLE hEventLog; + SID* pCurrentUserSID; + + private: + // Disallow copying of instances of this class + NTEventLogAppender(const NTEventLogAppender&); + NTEventLogAppender& operator=(const NTEventLogAppender&); + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_HAVE_NT_EVENT_LOG +#endif //LOG4CPLUS_NT_EVENT_LOG_APPENDER_HEADER_ diff --git a/sg_agent/thrid_party/logs/include/nullappender.h b/sg_agent/thrid_party/logs/include/nullappender.h new file mode 100644 index 0000000..15456fc --- /dev/null +++ b/sg_agent/thrid_party/logs/include/nullappender.h @@ -0,0 +1,65 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: nullappender.h +// Created: 6/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_NULL_APPENDER_HEADER_ +#define LOG4CPLUS_NULL_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + + +namespace log4cplus { + + /** + * Appends log events to a file. + */ + class LOG4CPLUS_EXPORT NullAppender : public Appender { + public: + // Ctors + NullAppender(); + NullAppender(const log4cplus::helpers::Properties&); + + // Dtor + virtual ~NullAppender(); + + // Methods + virtual void close(); + + protected: + virtual void append(const log4cplus::spi::InternalLoggingEvent& event); + + private: + // Disallow copying of instances of this class + NullAppender(const NullAppender&); + NullAppender& operator=(const NullAppender&); + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_NULL_APPENDER_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/qt4debugappender.h b/sg_agent/thrid_party/logs/include/qt4debugappender.h new file mode 100644 index 0000000..8908a6e --- /dev/null +++ b/sg_agent/thrid_party/logs/include/qt4debugappender.h @@ -0,0 +1,103 @@ +// -*- C++ -*- +// Module: Log4cplus +// File: qt4debugappender.h +// Created: 5/2012 +// Author: Vaclav Zeman +// +// +// Copyright (C) 2012-2013, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// + +/** @file */ + +#ifndef LOG4CPLUS_QT4DEBUGAPPENDER_H +#define LOG4CPLUS_QT4DEBUGAPPENDER_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#if defined (_WIN32) + #if defined (log4cplusqt4debugappender_EXPORTS) \ + || defined (log4cplusqt4debugappenderU_EXPORTS) \ + || defined (DLL_EXPORT) + #undef LOG4CPLUS_QT4DEBUGAPPENDER_BUILD_DLL + #define LOG4CPLUS_QT4DEBUGAPPENDER_BUILD_DLL + #endif + #if defined (LOG4CPLUS_QT4DEBUGAPPENDER_BUILD_DLL) + #if defined (INSIDE_LOG4CPLUS_QT4DEBUGAPPENDER) + #define LOG4CPLUS_QT4DEBUGAPPENDER_EXPORT __declspec(dllexport) + #else + #define LOG4CPLUS_QT4DEBUGAPPENDER_EXPORT __declspec(dllimport) + #endif + #else + #define LOG4CPLUS_QT4DEBUGAPPENDER_EXPORT + #endif +#else + #if defined (INSIDE_LOG4CPLUS_QT4DEBUGAPPENDER) + #define LOG4CPLUS_QT4DEBUGAPPENDER_EXPORT LOG4CPLUS_DECLSPEC_EXPORT + #else + #define LOG4CPLUS_QT4DEBUGAPPENDER_EXPORT LOG4CPLUS_DECLSPEC_IMPORT + #endif // defined (INSIDE_LOG4CPLUS_QT4DEBUGAPPENDER) +#endif // !_WIN32 + + +namespace log4cplus +{ + + +class LOG4CPLUS_QT4DEBUGAPPENDER_EXPORT Qt4DebugAppender + : public Appender +{ +public: + Qt4DebugAppender (); + explicit Qt4DebugAppender (helpers::Properties const &); + virtual ~Qt4DebugAppender (); + + virtual void close (); + + static void registerAppender (); + +protected: + virtual void append (spi::InternalLoggingEvent const &); + +private: + Qt4DebugAppender (Qt4DebugAppender const &); + Qt4DebugAppender & operator = (Qt4DebugAppender const &); +}; + + +typedef helpers::SharedObjectPtr Qt4DebugAppenderPtr; + + +} // namespace log4cplus + + +#endif // LOG4CPLUS_QT4DEBUGAPPENDER_H diff --git a/sg_agent/thrid_party/logs/include/socketappender.h b/sg_agent/thrid_party/logs/include/socketappender.h new file mode 100644 index 0000000..a288c51 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/socketappender.h @@ -0,0 +1,170 @@ +// -*- C++ -*- +// Module: LOG4CPLUS +// File: socketappender.h +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SOCKET_APPENDER_HEADER_ +#define LOG4CPLUS_SOCKET_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + + +namespace log4cplus +{ + + +#ifndef UNICODE + std::size_t const LOG4CPLUS_MAX_MESSAGE_SIZE = 8*1024; +#else + std::size_t const LOG4CPLUS_MAX_MESSAGE_SIZE = 2*8*1024; +#endif + + + /** + * Sends {@link spi::InternalLoggingEvent} objects to a remote a log server. + * + * The SocketAppender has the following properties: + * + *
    + * + *
  • Remote logging is non-intrusive as far as the log event + * is concerned. In other words, the event will be logged with + * the same time stamp, NDC, location info as if it were logged + * locally by the client. + * + *
  • SocketAppenders do not use a layout. + * + *
  • Remote logging uses the TCP protocol. Consequently, if + * the server is reachable, then log events will eventually arrive + * at the server. + * + *
  • If the remote server is down, the logging requests are + * simply dropped. However, if and when the server comes back up, + * then event transmission is resumed transparently. This + * transparent reconneciton is performed by a connector + * thread which periodically attempts to connect to the server. + * + *
  • Logging events are automatically buffered by the + * native TCP implementation. This means that if the link to server + * is slow but still faster than the rate of (log) event production + * by the client, the client will not be affected by the slow + * network connection. However, if the network connection is slower + * then the rate of event production, then the client can only + * progress at the network rate. In particular, if the network link + * to the the server is down, the client will be blocked. + * + *
  • On the other hand, if the network link is up, but the server + * is down, the client will not be blocked when making log requests + * but the log events will be lost due to server unavailability. + *
+ * + *

Properties

+ *
+ *
host
+ *
Remote host name to connect and send events to.
+ * + *
port
+ *
Port on remote host to send events to.
+ * + *
ServerName
+ *
Host name of event's origin prepended to each event.
+ * + *
+ */ + class LOG4CPLUS_EXPORT SocketAppender : public Appender { + public: + // Ctors + SocketAppender(const log4cplus::tstring& host, unsigned short port, + const log4cplus::tstring& serverName = tstring()); + SocketAppender(const log4cplus::helpers::Properties & properties); + + // Dtor + ~SocketAppender(); + + // Methods + virtual void close(); + + protected: + void openSocket(); + void initConnector (); + virtual void append(const spi::InternalLoggingEvent& event); + + // Data + log4cplus::helpers::Socket socket; + log4cplus::tstring host; + unsigned int port; + log4cplus::tstring serverName; + +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + class LOG4CPLUS_EXPORT ConnectorThread; + friend class ConnectorThread; + + class LOG4CPLUS_EXPORT ConnectorThread + : public thread::AbstractThread + { + public: + ConnectorThread (SocketAppender &); + virtual ~ConnectorThread (); + + virtual void run(); + + void terminate (); + void trigger (); + + protected: + SocketAppender & sa; + thread::ManualResetEvent trigger_ev; + bool exit_flag; + }; + + volatile bool connected; + helpers::SharedObjectPtr connector; +#endif + + private: + // Disallow copying of instances of this class + SocketAppender(const SocketAppender&); + SocketAppender& operator=(const SocketAppender&); + }; + + namespace helpers { + LOG4CPLUS_EXPORT + void convertToBuffer (SocketBuffer & buffer, + const log4cplus::spi::InternalLoggingEvent& event, + const log4cplus::tstring& serverName); + + LOG4CPLUS_EXPORT + log4cplus::spi::InternalLoggingEvent readFromBuffer(SocketBuffer& buffer); + } // end namespace helpers + +} // end namespace log4cplus + +#endif // LOG4CPLUS_SOCKET_APPENDER_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/spi/appenderattachable.h b/sg_agent/thrid_party/logs/include/spi/appenderattachable.h new file mode 100644 index 0000000..986bf9b --- /dev/null +++ b/sg_agent/thrid_party/logs/include/spi/appenderattachable.h @@ -0,0 +1,90 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: appenderattachable.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_APPENDER_ATTACHABLE_HEADER_ +#define LOG4CPLUS_SPI_APPENDER_ATTACHABLE_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + +namespace log4cplus { + // Forward Declarations + typedef helpers::SharedObjectPtr SharedAppenderPtr; + typedef std::vector SharedAppenderPtrList; + + namespace spi { + + /** + * This Interface is for attaching Appenders to objects. + */ + class LOG4CPLUS_EXPORT AppenderAttachable { + public: + // Methods + /** + * Add an appender. + */ + virtual void addAppender(SharedAppenderPtr newAppender) = 0; + + /** + * Get all previously added appenders as an Enumeration. + */ + virtual SharedAppenderPtrList getAllAppenders() = 0; + + /** + * Get an appender by name. + */ + virtual SharedAppenderPtr getAppender(const log4cplus::tstring& name) = 0; + + /** + * Remove all previously added appenders. + */ + virtual void removeAllAppenders() = 0; + + /** + * Remove the appender passed as parameter from the list of appenders. + */ + virtual void removeAppender(SharedAppenderPtr appender) = 0; + + /** + * Remove the appender with the name passed as parameter from the + * list of appenders. + */ + virtual void removeAppender(const log4cplus::tstring& name) = 0; + + // Dtor + virtual ~AppenderAttachable() = 0; + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif // LOG4CPLUS_SPI_APPENDER_ATTACHABLE_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/spi/factory.h b/sg_agent/thrid_party/logs/include/spi/factory.h new file mode 100644 index 0000000..709edf5 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/spi/factory.h @@ -0,0 +1,273 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: factory.h +// Created: 2/2002 +// Author: Tad E. Smith +// +// +// Copyright 2002-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_FACTORY_HEADER_ +#define LOG4CPLUS_SPI_FACTORY_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace log4cplus { + namespace spi { + + /** + * This is the base class for all factories. + */ + class LOG4CPLUS_EXPORT BaseFactory { + public: + virtual ~BaseFactory() = 0; + + /** + * Returns the typename of the objects this factory creates. + */ + virtual log4cplus::tstring const & getTypeName() const = 0; + }; + + + /** + * This abstract class defines the "Factory" interface to create "Appender" + * objects. + */ + class LOG4CPLUS_EXPORT AppenderFactory : public BaseFactory { + public: + typedef Appender ProductType; + typedef SharedAppenderPtr ProductPtr; + + AppenderFactory(); + virtual ~AppenderFactory() = 0; + + /** + * Create an "Appender" object. + */ + virtual SharedAppenderPtr createObject(const log4cplus::helpers::Properties& props) = 0; + }; + + + + /** + * This abstract class defines the "Factory" interface to create "Layout" + * objects. + */ + class LOG4CPLUS_EXPORT LayoutFactory : public BaseFactory { + public: + typedef Layout ProductType; + typedef std::auto_ptr ProductPtr; + + LayoutFactory(); + virtual ~LayoutFactory() = 0; + + /** + * Create a "Layout" object. + */ + virtual std::auto_ptr createObject(const log4cplus::helpers::Properties& props) = 0; + }; + + + + /** + * This abstract class defines the "Factory" interface to create "Appender" + * objects. + */ + class LOG4CPLUS_EXPORT FilterFactory : public BaseFactory { + public: + typedef Filter ProductType; + typedef FilterPtr ProductPtr; + + FilterFactory(); + virtual ~FilterFactory() = 0; + + /** + * Create a "Filter" object. + */ + virtual FilterPtr createObject(const log4cplus::helpers::Properties& props) = 0; + }; + + + /** + * This abstract class defines the "Factory" interface to + * create std::locale instances. + */ + class LOG4CPLUS_EXPORT LocaleFactory + : public BaseFactory + { + public: + typedef std::locale ProductType; + typedef std::locale ProductPtr; + + LocaleFactory(); + virtual ~LocaleFactory() = 0; + + //! \returns std::locale instance + virtual ProductPtr createObject ( + const log4cplus::helpers::Properties & props) = 0; + }; + + + /** + * This template class is used as a "Factory Registry". Objects are + * "entered" into the registry with a "name" using the + * put() method. (The registry then owns the object.) + * These object can then be retrieved using the get() + * method. + * + * Note: This class is Thread-safe. + */ + template + class LOG4CPLUS_EXPORT FactoryRegistry : ObjectRegistryBase { + public: + typedef T product_type; + + virtual ~FactoryRegistry() { + clear(); + } + + // public methods + /** + * Used to enter an object into the registry. (The registry now + * owns object.) + */ + bool put(std::auto_ptr object) { + bool putValResult = putVal(object->getTypeName(), object.get()); + object.release(); + return putValResult; + } + + /** + * Used to retrieve an object from the registry. (The registry + * owns the returned pointer.) + */ + T* get(const log4cplus::tstring& name) const { + return static_cast(getVal(name)); + } + + protected: + virtual void deleteObject(void *object) const { + delete static_cast(object); + } + }; + + + typedef FactoryRegistry AppenderFactoryRegistry; + typedef FactoryRegistry LayoutFactoryRegistry; + typedef FactoryRegistry FilterFactoryRegistry; + typedef FactoryRegistry LocaleFactoryRegistry; + + + /** + * Returns the "singleton" AppenderFactoryRegistry. + */ + LOG4CPLUS_EXPORT AppenderFactoryRegistry& getAppenderFactoryRegistry(); + + /** + * Returns the "singleton" LayoutFactoryRegistry. + */ + LOG4CPLUS_EXPORT LayoutFactoryRegistry& getLayoutFactoryRegistry(); + + /** + * Returns the "singleton" FilterFactoryRegistry. + */ + LOG4CPLUS_EXPORT FilterFactoryRegistry& getFilterFactoryRegistry(); + + /** + * Returns the "singleton" LocaleFactoryRegistry. + */ + LOG4CPLUS_EXPORT LocaleFactoryRegistry& getLocaleFactoryRegistry(); + + + template + class LocalFactoryBase + : public ProductFactoryBase + { + public: + LocalFactoryBase (tchar const * n) + : name (n) + { } + + virtual log4cplus::tstring const & getTypeName() const + { + return name; + } + + private: + log4cplus::tstring name; + }; + + + template + class FactoryTempl + : public LocalFactoryBase + { + public: + typedef typename ProductFactoryBase::ProductPtr ProductPtr; + + FactoryTempl (tchar const * n) + : LocalFactoryBase (n) + { } + + virtual ProductPtr createObject (helpers::Properties const & props) + { + return ProductPtr (new LocalProduct (props)); + } + }; + + + #define LOG4CPLUS_REG_PRODUCT(reg, productprefix, productname, productns, productfact) \ + reg.put ( \ + std::auto_ptr ( \ + new log4cplus::spi::FactoryTempl ( \ + LOG4CPLUS_TEXT(productprefix) \ + LOG4CPLUS_TEXT(#productname)))) + + #define LOG4CPLUS_REG_APPENDER(reg, appendername) \ + LOG4CPLUS_REG_PRODUCT (reg, "log4cplus::", appendername, log4cplus::, \ + log4cplus::spi::AppenderFactory) + + #define LOG4CPLUS_REG_LAYOUT(reg, layoutname) \ + LOG4CPLUS_REG_PRODUCT (reg, "log4cplus::", layoutname, log4cplus::, \ + log4cplus::spi::LayoutFactory) + + #define LOG4CPLUS_REG_FILTER(reg, filtername) \ + LOG4CPLUS_REG_PRODUCT (reg, "log4cplus::spi::", filtername, log4cplus::spi::, \ + log4cplus::spi::FilterFactory) + + #define LOG4CPLUS_REG_LOCALE(reg, name, factory) \ + reg.put (std::auto_ptr ( \ + new factory (name))) + } // namespace spi +} + + +#endif // LOG4CPLUS_SPI_FACTORY_HEADER_ diff --git a/sg_agent/thrid_party/logs/include/spi/filter.h b/sg_agent/thrid_party/logs/include/spi/filter.h new file mode 100644 index 0000000..1febd23 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/spi/filter.h @@ -0,0 +1,287 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: filter.h +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 1999-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file + * This header defines Filter and all of it's subclasses. */ + +#ifndef LOG4CPLUS_SPI_FILTER_HEADER_ +#define LOG4CPLUS_SPI_FILTER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus { + + namespace helpers + { + + class Properties; + + } + + namespace spi { + + + enum FilterResult { DENY, /**< The log event must be dropped immediately + * without consulting with the remaining + * filters, if any, in the chain. */ + NEUTRAL, /**< This filter is neutral with respect to + * the log event; the remaining filters, if + * if any, should be consulted for a final + * decision. */ + ACCEPT /**< The log event must be logged immediately + * without consulting with the remaining + * filters, if any, in the chain. */ + }; + + // Forward Declarations + class Filter; + class InternalLoggingEvent; + + + /** + * This method is used to filter an InternalLoggingEvent. + * + * Note: filter can be NULL. + */ + LOG4CPLUS_EXPORT FilterResult checkFilter(const Filter* filter, + const InternalLoggingEvent& event); + + typedef helpers::SharedObjectPtr FilterPtr; + + + /** + * Users should extend this class to implement customized logging + * event filtering. Note that the {@link Logger} and {@link + * Appender} classes have built-in filtering rules. It is suggested + * that you first use and understand the built-in rules before rushing + * to write your own custom filters. + * + * This abstract class assumes and also imposes that filters be + * organized in a linear chain. The {@link #decide + * decide(LoggingEvent)} method of each filter is called sequentially, + * in the order of their addition to the chain. + * + * If the value {@link #DENY} is returned, then the log event is + * dropped immediately without consulting with the remaining + * filters. + * + * If the value {@link #NEUTRAL} is returned, then the next filter + * in the chain is consulted. If there are no more filters in the + * chain, then the log event is logged. Thus, in the presence of no + * filters, the default behaviour is to log all logging events. + * + * If the value {@link #ACCEPT} is returned, then the log + * event is logged without consulting the remaining filters. + * + * The philosophy of log4cplus filters is largely inspired from the + * Linux ipchains. + */ + class LOG4CPLUS_EXPORT Filter + : public virtual log4cplus::helpers::SharedObject + { + public: + // ctor and dtor + Filter(); + virtual ~Filter(); + + // Methods + /** + * Appends filter to the end of this filter chain. + */ + void appendFilter(FilterPtr filter); + + /** + * If the decision is DENY, then the event will be + * dropped. If the decision is NEUTRAL, then the next + * filter, if any, will be invoked. If the decision is ACCEPT then + * the event will be logged without consulting with other filters in + * the chain. + * + * @param event The LoggingEvent to decide upon. + * @return The decision of the filter. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const = 0; + + // Data + /** + * Points to the next filter in the filter chain. + */ + FilterPtr next; + }; + + + + /** + * This filter drops all logging events. + * + * You can add this filter to the end of a filter chain to + * switch from the default "accept all unless instructed otherwise" + * filtering behaviour to a "deny all unless instructed otherwise" + * behaviour. + */ + class LOG4CPLUS_EXPORT DenyAllFilter : public Filter { + public: + DenyAllFilter (); + DenyAllFilter (const log4cplus::helpers::Properties&); + + /** + * Always returns the {@link #DENY} regardless of the + * {@link InternalLoggingEvent} parameter. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const; + }; + + + /** + * This is a very simple filter based on LogLevel matching. + * + * The filter admits two options LogLevelToMatch and + * AcceptOnMatch. If there is an exact match between the value + * of the LogLevelToMatch option and the LogLevel of the {@link + * spi::InternalLoggingEvent}, then the {@link #decide} method returns + * {@link #ACCEPT} in case the AcceptOnMatch option value is set + * to true, if it is false then {@link #DENY} + * is returned. If there is no match, {@link #NEUTRAL} is returned. + */ + class LOG4CPLUS_EXPORT LogLevelMatchFilter : public Filter { + public: + LogLevelMatchFilter(); + LogLevelMatchFilter(const log4cplus::helpers::Properties& p); + + /** + * Return the decision of this filter. + * + * Returns {@link #NEUTRAL} if the LogLevelToMatch + * option is not set or if there is no match. Otherwise, if + * there is a match, then the returned decision is {@link #ACCEPT} + * if the AcceptOnMatch property is set to true. + * The returned decision is {@link #DENY} if the AcceptOnMatch + * property is set to false. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const; + + private: + // Methods + LOG4CPLUS_PRIVATE void init(); + + // Data + /** Do we return ACCEPT when a match occurs. Default is true. */ + bool acceptOnMatch; + LogLevel logLevelToMatch; + }; + + + + /** + * This is a very simple filter based on LogLevel matching, which can be + * used to reject messages with LogLevels outside a certain range. + * + * The filter admits three options LogLevelMin, LogLevelMax + * and AcceptOnMatch. + * + * If the LogLevel of the Logging event is not between Min and Max + * (inclusive), then {@link #DENY} is returned. + * + * If the Logging event LogLevel is within the specified range, then if + * AcceptOnMatch is true, {@link #ACCEPT} is returned, and if + * AcceptOnMatch is false, {@link #NEUTRAL} is returned. + * + * If LogLevelMin is not defined, then there is no + * minimum acceptable LogLevel (ie a LogLevel is never rejected for + * being too "low"/unimportant). If LogLevelMax is not + * defined, then there is no maximum acceptable LogLevel (ie a + * LogLevel is never rejected for beeing too "high"/important). + * + * Refer to the {@link + * Appender#setThreshold setThreshold} method + * available to all appenders for a more convenient way to + * filter out events by LogLevel. + */ + class LOG4CPLUS_EXPORT LogLevelRangeFilter : public Filter { + public: + // ctors + LogLevelRangeFilter(); + LogLevelRangeFilter(const log4cplus::helpers::Properties& p); + + /** + * Return the decision of this filter. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const; + + private: + // Methods + LOG4CPLUS_PRIVATE void init(); + + // Data + /** Do we return ACCEPT when a match occurs. Default is true. */ + bool acceptOnMatch; + LogLevel logLevelMin; + LogLevel logLevelMax; + }; + + + + /** + * This is a very simple filter based on string matching. + * + * The filter admits two options StringToMatch and + * AcceptOnMatch. If there is a match between the value of the + * StringToMatch option and the message of the Logging event, + * then the {@link #decide} method returns {@link #ACCEPT} if + * the AcceptOnMatch option value is true, if it is false then + * {@link #DENY} is returned. If there is no match, {@link #NEUTRAL} + * is returned. + */ + class LOG4CPLUS_EXPORT StringMatchFilter : public Filter { + public: + // ctors + StringMatchFilter(); + StringMatchFilter(const log4cplus::helpers::Properties& p); + + /** + * Returns {@link #NEUTRAL} is there is no string match. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const; + + private: + // Methods + LOG4CPLUS_PRIVATE void init(); + + // Data + /** Do we return ACCEPT when a match occurs. Default is true. */ + bool acceptOnMatch; + log4cplus::tstring stringToMatch; + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif /* LOG4CPLUS_SPI_FILTER_HEADER_ */ + + diff --git a/sg_agent/thrid_party/logs/include/spi/loggerfactory.h b/sg_agent/thrid_party/logs/include/spi/loggerfactory.h new file mode 100644 index 0000000..ad735f1 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/spi/loggerfactory.h @@ -0,0 +1,60 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: loggerfactory.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_LOGGER_FACTORY_HEADER +#define LOG4CPLUS_SPI_LOGGER_FACTORY_HEADER + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + + +namespace log4cplus { + // Forward Declarations + class Logger; + class Hierarchy; + + namespace spi { + /** + * Implement this interface to create new instances of Logger or + * a sub-class of Logger. + */ + class LOG4CPLUS_EXPORT LoggerFactory { + public: + /** + * Creates a new Logger object. + */ + virtual Logger makeNewLoggerInstance(const log4cplus::tstring& name, + Hierarchy& h) = 0; + virtual ~LoggerFactory() = 0; + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif // LOG4CPLUS_SPI_LOGGER_FACTORY_HEADER + diff --git a/sg_agent/thrid_party/logs/include/spi/loggerimpl.h b/sg_agent/thrid_party/logs/include/spi/loggerimpl.h new file mode 100644 index 0000000..c7e4633 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/spi/loggerimpl.h @@ -0,0 +1,219 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: loggerimpl.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_LOGGER_HEADER_ +#define LOG4CPLUS_SPI_LOGGER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include + + +namespace log4cplus { + class DefaultLoggerFactory; + + namespace spi { + + /** + * This is the central class in the log4cplus package. One of the + * distintive features of log4cplus are hierarchical loggers and their + * evaluation. + * + * See the user manual for an + * introduction on this class. + */ + class LOG4CPLUS_EXPORT LoggerImpl + : public virtual log4cplus::helpers::SharedObject, + public log4cplus::helpers::AppenderAttachableImpl + { + public: + typedef helpers::SharedObjectPtr SharedLoggerImplPtr; + + // Methods + + /** + * Call the appenders in the hierrachy starting at + * this. If no appenders could be found, emit a + * warning. + * + * This method calls all the appenders inherited from the + * hierarchy circumventing any evaluation of whether to log or not + * to log the particular log request. + * + * @param event The event to log. + */ + virtual void callAppenders(const InternalLoggingEvent& event); + + /** + * Close all attached appenders implementing the AppenderAttachable + * interface. + */ + virtual void closeNestedAppenders(); + + /** + * Check whether this logger is enabled for a given LogLevel passed + * as parameter. + * + * @return boolean True if this logger is enabled for ll. + */ + virtual bool isEnabledFor(LogLevel ll) const; + + /** + * This generic form is intended to be used by wrappers. + */ + virtual void log(LogLevel ll, const log4cplus::tstring& message, + const char* file=NULL, int line=-1); + + virtual void log(spi::InternalLoggingEvent const &); + + /** + * Starting from this logger, search the logger hierarchy for a + * "set" LogLevel and return it. Otherwise, return the LogLevel of the + * root logger. + * + * The Logger class is designed so that this method executes as + * quickly as possible. + */ + virtual LogLevel getChainedLogLevel() const; + + /** + * Returns the assigned LogLevel, if any, for this Logger. + * + * @return LogLevel - the assigned LogLevel. + */ + LogLevel getLogLevel() const { return this->ll; } + + /** + * Set the LogLevel of this Logger. + */ + void setLogLevel(LogLevel _ll) { this->ll = _ll; } + + /** + * Return the the {@link Hierarchy} where this Logger + * instance is attached. + */ + virtual Hierarchy& getHierarchy() const; + + /** + * Return the logger name. + */ + log4cplus::tstring const & getName() const { return name; } + + /** + * Get the additivity flag for this Logger instance. + */ + bool getAdditivity() const; + + /** + * Set the additivity flag for this Logger instance. + */ + void setAdditivity(bool additive); + + virtual ~LoggerImpl(); + + protected: + // Ctors + /** + * This constructor created a new Logger instance and + * sets its name. + * + * It is intended to be used by sub-classes only. You should not + * create loggers directly. + * + * @param name The name of the logger. + * @param h Hierarchy + */ + LoggerImpl(const log4cplus::tstring& name, Hierarchy& h); + + + // Methods + /** + * This method creates a new logging event and logs the event + * without further checks. + */ + virtual void forcedLog(LogLevel ll, + const log4cplus::tstring& message, + const char* file=NULL, + int line=-1); + + virtual void forcedLog(spi::InternalLoggingEvent const & ev); + + + // Data + /** The name of this logger */ + log4cplus::tstring name; + + /** + * The assigned LogLevel of this logger. + */ + LogLevel ll; + + /** + * The parent of this logger. All loggers have at least one + * ancestor which is the root logger. + */ + SharedLoggerImplPtr parent; + + /** + * Additivity is set to true by default, that is children inherit + * the appenders of their ancestors by default. If this variable is + * set to false then the appenders found in the + * ancestors of this logger are not used. However, the children + * of this logger will inherit its appenders, unless the children + * have their additivity flag set to false too. See + * the user manual for more details. + */ + bool additive; + + private: + // Data + /** Loggers need to know what Hierarchy they are in. */ + Hierarchy& hierarchy; + + // Disallow copying of instances of this class + LoggerImpl(const LoggerImpl&); + LoggerImpl& operator=(const LoggerImpl&); + + // Friends + friend class log4cplus::Logger; + friend class log4cplus::DefaultLoggerFactory; + friend class log4cplus::Hierarchy; + }; + + typedef LoggerImpl::SharedLoggerImplPtr SharedLoggerImplPtr; + + } // end namespace spi +} // end namespace log4cplus + +#endif // LOG4CPLUS_SPI_LOGGER_HEADER_ + + diff --git a/sg_agent/thrid_party/logs/include/spi/loggingevent.h b/sg_agent/thrid_party/logs/include/spi/loggingevent.h new file mode 100644 index 0000000..e57bd6e --- /dev/null +++ b/sg_agent/thrid_party/logs/include/spi/loggingevent.h @@ -0,0 +1,228 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: loggingevent.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_INTERNAL_LOGGING_EVENT_HEADER_ +#define LOG4CPLUS_SPI_INTERNAL_LOGGING_EVENT_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + +namespace log4cplus { + namespace spi { + /** + * The internal representation of logging events. When an affirmative + * decision is made to log then a InternalLoggingEvent + * instance is created. This instance is passed around to the + * different log4cplus components. + * + * This class is of concern to those wishing to extend log4cplus. + */ + class LOG4CPLUS_EXPORT InternalLoggingEvent { + public: + // Ctors + /** + * Instantiate a LoggingEvent from the supplied parameters. + * + * @param logger The logger of this event. + * @param loglevel The LogLevel of this event. + * @param message The message of this event. + * @param filename Name of file where this event has occurred, + * can be NULL. + * @param line Line number in file specified by + * the filename parameter. + */ + InternalLoggingEvent(const log4cplus::tstring& logger, + LogLevel loglevel, const log4cplus::tstring& message, + const char* filename, int line); + + InternalLoggingEvent(const log4cplus::tstring& logger, + LogLevel loglevel, const log4cplus::tstring& ndc, + MappedDiagnosticContextMap const & mdc, + const log4cplus::tstring& message, + const log4cplus::tstring& thread, + log4cplus::helpers::Time time, const log4cplus::tstring& file, + int line); + + InternalLoggingEvent (); + + InternalLoggingEvent( + const log4cplus::spi::InternalLoggingEvent& rhs); + + virtual ~InternalLoggingEvent(); + + void setLoggingEvent (const log4cplus::tstring & logger, + LogLevel ll, const log4cplus::tstring & message, + const char * filename, int line); + + void setFunction (char const * func); + void setFunction (log4cplus::tstring const &); + + + // public virtual methods + /** The application supplied message of logging event. */ + virtual const log4cplus::tstring& getMessage() const; + + /** Returns the 'type' of InternalLoggingEvent. Derived classes + * should override this method. (NOTE: Values <= 1000 are + * reserved for log4cplus and should not be used.) + */ + virtual unsigned int getType() const; + + /** Returns a copy of this object. Derived classes + * should override this method. + */ + virtual std::auto_ptr clone() const; + + + + // public methods + /** The logger of the logging event. It is set by + * the LoggingEvent constructor. + */ + const log4cplus::tstring& getLoggerName() const + { + return loggerName; + } + + /** LogLevel of logging event. */ + LogLevel getLogLevel() const + { + return ll; + } + + /** The nested diagnostic context (NDC) of logging event. */ + const log4cplus::tstring& getNDC() const + { + if (!ndcCached) + { + ndc = log4cplus::getNDC().get(); + ndcCached = true; + } + return ndc; + } + + MappedDiagnosticContextMap const & getMDCCopy () const + { + if (!mdcCached) + { + mdc = log4cplus::getMDC().getContext (); + mdcCached = true; + } + return mdc; + } + + tstring const & getMDC (tstring const & key) const; + + /** The name of thread in which this logging event was generated. */ + const log4cplus::tstring& getThread() const + { + if (! threadCached) + { + thread = thread::getCurrentThreadName (); + threadCached = true; + } + return thread; + } + + //! The alternative name of thread in which this logging event + //! was generated. + const log4cplus::tstring& getThread2() const + { + if (! thread2Cached) + { + thread2 = thread::getCurrentThreadName2 (); + thread2Cached = true; + } + return thread2; + } + + + /** The number of milliseconds elapsed from 1/1/1970 until + * logging event was created. */ + const log4cplus::helpers::Time& getTimestamp() const + { + return timestamp; + } + + /** The is the file where this log statement was written */ + const log4cplus::tstring& getFile() const + { + return file; + } + + /** The is the line where this log statement was written */ + int getLine() const { return line; } + + log4cplus::tstring const & getFunction () const + { + return function; + } + + void gatherThreadSpecificData () const; + + void swap (InternalLoggingEvent &); + + // public operators + log4cplus::spi::InternalLoggingEvent& + operator=(const log4cplus::spi::InternalLoggingEvent& rhs); + + // static methods + static unsigned int getDefaultType(); + + protected: + // Data + log4cplus::tstring message; + log4cplus::tstring loggerName; + LogLevel ll; + mutable log4cplus::tstring ndc; + mutable MappedDiagnosticContextMap mdc; + mutable log4cplus::tstring thread; + mutable log4cplus::tstring thread2; + log4cplus::helpers::Time timestamp; + log4cplus::tstring file; + log4cplus::tstring function; + int line; + /** Indicates whether or not the Threadname has been retrieved. */ + mutable bool threadCached; + mutable bool thread2Cached; + /** Indicates whether or not the NDC has been retrieved. */ + mutable bool ndcCached; + /** Indicates whether or not the MDC has been retrieved. */ + mutable bool mdcCached; + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif // LOG4CPLUS_SPI_INTERNAL_LOGGING_EVENT_HEADER_ diff --git a/sg_agent/thrid_party/logs/include/spi/objectregistry.h b/sg_agent/thrid_party/logs/include/spi/objectregistry.h new file mode 100644 index 0000000..d059474 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/spi/objectregistry.h @@ -0,0 +1,106 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: objectregistry.h +// Created: 3/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_OBJECT_REGISTRY_HEADER_ +#define LOG4CPLUS_SPI_OBJECT_REGISTRY_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include + + +namespace log4cplus { + namespace spi { + + /** + * This is the base class used to implement the functionality required + * by the ObjectRegistry template class. + */ + class LOG4CPLUS_EXPORT ObjectRegistryBase { + public: + // public methods + /** + * Tests to see whether or not an object is bound in the + * registry as name. + */ + bool exists(const log4cplus::tstring& name) const; + + /** + * Returns the names of all registered objects. + */ + std::vector getAllNames() const; + + protected: + // Ctor and Dtor + ObjectRegistryBase(); + virtual ~ObjectRegistryBase(); + + // protected methods + /** + * Used to enter an object into the registry. (The registry now + * owns object.) + */ + bool putVal(const log4cplus::tstring& name, void* object); + + /** + * Used to retrieve an object from the registry. (The registry + * owns the returned pointer.) + */ + void* getVal(const log4cplus::tstring& name) const; + + /** + * Deletes object. + */ + virtual void deleteObject(void *object) const = 0; + + /** + * Deletes all objects from this registry. + */ + virtual void clear(); + + // Types + typedef std::map ObjectMap; + + // Data + thread::Mutex mutex; + ObjectMap data; + + private: + ObjectRegistryBase (ObjectRegistryBase const &); + ObjectRegistryBase & operator = (ObjectRegistryBase const &); + }; + + } +} + + +#endif // LOG4CPLUS_SPI_OBJECT_REGISTRY_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/spi/rootlogger.h b/sg_agent/thrid_party/logs/include/spi/rootlogger.h new file mode 100644 index 0000000..6c466c2 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/spi/rootlogger.h @@ -0,0 +1,75 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: rootlogger.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_ROOT_LOGGER_HEADER_ +#define LOG4CPLUS_SPI_ROOT_LOGGER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +namespace log4cplus { + namespace spi { + + /** + * RootLogger sits at the top of the logger hierachy. It is a + * regular logger except that it provides several guarantees. + * + * First, it cannot be assigned a NOT_SET_LOG_LEVEL + * LogLevel. Second, since root logger cannot have a parent, the + * getChainedLogLevel method always returns the value of the + * ll field without walking the hierarchy. + */ + class LOG4CPLUS_EXPORT RootLogger : public LoggerImpl { + public: + // Ctors + /** + * The root logger names itself as "root". However, the root + * logger cannot be retrieved by name. + */ + RootLogger(Hierarchy& h, LogLevel ll); + + // Methods + /** + * Return the assigned LogLevel value without walking the logger + * hierarchy. + */ + virtual LogLevel getChainedLogLevel() const; + + /** + * Setting a NOT_SET_LOG_LEVEL value to the LogLevel of the root logger + * may have catastrophic results. We prevent this here. + */ + void setLogLevel(LogLevel ll); + + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif // LOG4CPLUS_SPI_ROOT_LOGGER_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/stamp-h1 b/sg_agent/thrid_party/logs/include/stamp-h1 new file mode 100644 index 0000000..6218c71 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/stamp-h1 @@ -0,0 +1 @@ +timestamp for include/log4cplus/config.h diff --git a/sg_agent/thrid_party/logs/include/streams.h b/sg_agent/thrid_party/logs/include/streams.h new file mode 100644 index 0000000..df33c4d --- /dev/null +++ b/sg_agent/thrid_party/logs/include/streams.h @@ -0,0 +1,55 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: streams.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_STREAMS_HEADER_ +#define LOG4CPLUS_STREAMS_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#include + + +namespace log4cplus +{ + typedef std::basic_ostream tostream; + typedef std::basic_istream tistream; + typedef std::basic_ostringstream tostringstream; + typedef std::basic_istringstream tistringstream; + extern LOG4CPLUS_EXPORT tostream & tcout; + extern LOG4CPLUS_EXPORT tostream & tcerr; +} + +#if defined (UNICODE) && defined (LOG4CPLUS_ENABLE_GLOBAL_C_STRING_STREAM_INSERTER) + +LOG4CPLUS_EXPORT log4cplus::tostream& operator <<(log4cplus::tostream&, const char* psz ); + +#endif + +#endif // LOG4CPLUS_STREAMS_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/syslogappender.h b/sg_agent/thrid_party/logs/include/syslogappender.h new file mode 100644 index 0000000..60e06bd --- /dev/null +++ b/sg_agent/thrid_party/logs/include/syslogappender.h @@ -0,0 +1,118 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: syslogappender.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SYSLOG_APPENDER_HEADER_ +#define LOG4CPLUS_SYSLOG_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus +{ + + /** + * Appends log events to a file. + * + *

Properties

+ *
+ *
ident
+ *
First argument to openlog(), a string that + * will be prepended to every message.
+ * + *
facility
+ *
Facility is used in combination with syslog level in first + * argument to syslog(). It can be one of the supported facility + * names (case insensitive), e.g. auth, cron, kern, mail, news + * etc.
+ * + *
host
+ *
Destination syslog host. When this property is specified, + * messages are sent using UDP to destination host, otherwise + * messages are logged to local syslog.
+ * + *
port
+ *
Destination port of syslog service on host specified by the + * host property. The default value is port 514.
+ *
+ * + * \note Messages sent to remote syslog using UDP are conforming + * to RFC5424. + */ + class LOG4CPLUS_EXPORT SysLogAppender : public Appender { + public: + // Ctors +#if defined (LOG4CPLUS_HAVE_SYSLOG_H) + SysLogAppender(const tstring& ident); +#endif + SysLogAppender(const tstring& ident, const tstring & host, + int port = 514, const tstring & facility = tstring ()); + SysLogAppender(const log4cplus::helpers::Properties & properties); + + // Dtor + virtual ~SysLogAppender(); + + // Methods + virtual void close(); + + protected: + virtual int getSysLogLevel(const LogLevel& ll) const; + virtual void append(const spi::InternalLoggingEvent& event); +#if defined (LOG4CPLUS_HAVE_SYSLOG_H) + void appendLocal(const spi::InternalLoggingEvent& event); +#endif + void appendRemote(const spi::InternalLoggingEvent& event); + + // Data + tstring ident; + int facility; + + typedef void (SysLogAppender:: * AppendFuncType) ( + const spi::InternalLoggingEvent&); + AppendFuncType appendFunc; + + tstring host; + int port; + helpers::Socket syslogSocket; + + static tstring const remoteTimeFormat; + + private: + // Disallow copying of instances of this class + SysLogAppender(const SysLogAppender&); + SysLogAppender& operator=(const SysLogAppender&); + + std::string identStr; + tstring hostname; + }; + +} // end namespace log4cplus + + +#endif // LOG4CPLUS_SYSLOG_APPENDER_HEADER_ diff --git a/sg_agent/thrid_party/logs/include/tchar.h b/sg_agent/thrid_party/logs/include/tchar.h new file mode 100644 index 0000000..217fc76 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/tchar.h @@ -0,0 +1,63 @@ +// -*- C++ -*- +// Copyright (C) 2010-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/** @file */ + +#ifndef LOG4CPLUS_TCHAR_HEADER_ +#define LOG4CPLUS_TCHAR_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (_WIN32) +#include +#endif + + +#ifdef UNICODE +# define LOG4CPLUS_TEXT2(STRING) L##STRING +#else +# define LOG4CPLUS_TEXT2(STRING) STRING +#endif // UNICODE +#define LOG4CPLUS_TEXT(STRING) LOG4CPLUS_TEXT2(STRING) + + +namespace log4cplus +{ + +#if defined (UNICODE) +typedef wchar_t tchar; + +#else +typedef char tchar; + +#endif + +} // namespace log4cplus + + +#endif // LOG4CPLUS_TCHAR_HEADER_ diff --git a/sg_agent/thrid_party/logs/include/thread/impl/syncprims-impl.h b/sg_agent/thrid_party/logs/include/thread/impl/syncprims-impl.h new file mode 100644 index 0000000..6a2df91 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/thread/impl/syncprims-impl.h @@ -0,0 +1,240 @@ +// -*- C++ -*- +// Copyright (C) 2009-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_THREAD_SYNCPRIMS_IMPL_H +#define LOG4CPLUS_THREAD_SYNCPRIMS_IMPL_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + +#include +#include +#if defined (_WIN32) +# include + +#elif defined (LOG4CPLUS_USE_PTHREADS) +# include +# include +# include +# if defined (LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE) +# include +# include +# if defined (LOG4CPLUS_HAVE_SYS_TYPES_H) +# include +# endif +# if defined (LOG4CPLUS_HAVE_UNISTD_H) +# include +# endif +# endif +# if defined (LOG4CPLUS_HAVE_FCNTL_H) +# include +# endif +# include + +#endif + + +namespace log4cplus { namespace thread { namespace impl { + + +LOG4CPLUS_EXPORT void LOG4CPLUS_ATTRIBUTE_NORETURN + syncprims_throw_exception (char const * const msg, + char const * const file, int line); + + +#define LOG4CPLUS_THROW_RTE(msg) \ + do { syncprims_throw_exception (msg, __FILE__, __LINE__); } while (0) + + +class ManualResetEvent; + + +class Mutex + : public MutexImplBase +{ +public: + explicit Mutex (log4cplus::thread::Mutex::Type); + ~Mutex (); + + void lock () const; + void unlock () const; + +private: +#if defined (LOG4CPLUS_USE_PTHREADS) + mutable pthread_mutex_t mtx; + friend class ManualResetEvent; +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) + mutable CRITICAL_SECTION cs; +#endif + + Mutex (Mutex const &); + Mutex & operator = (Mutex &); +}; + + +typedef SyncGuard MutexGuard; + + +class Semaphore + : public SemaphoreImplBase +{ +public: + Semaphore (unsigned max, unsigned initial); + ~Semaphore (); + + void lock () const; + void unlock () const; + +private: +#if defined (LOG4CPLUS_USE_PTHREADS) +# if defined (LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE) + sem_t * sem; +# else + mutable sem_t sem; +# endif +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) + HANDLE sem; +#endif + + Semaphore (Semaphore const &); + Semaphore & operator = (Semaphore const &); +}; + + +typedef SyncGuard SemaphoreGuard; + + +class FairMutex + : public FairMutexImplBase +{ +public: + FairMutex (); + ~FairMutex (); + + void lock () const; + void unlock () const; + +private: +#if defined (LOG4CPLUS_USE_PTHREADS) + Semaphore sem; +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) + HANDLE mtx; +#endif + + FairMutex (FairMutex const &); + FairMutex & operator = (FairMutex &); +}; + + +typedef SyncGuard FairMutexGuard; + + +class ManualResetEvent + : public ManualResetEventImplBase +{ +public: + ManualResetEvent (bool = false); + ~ManualResetEvent (); + + void signal () const; + void wait () const; + bool timed_wait (unsigned long msec) const; + void reset () const; + +private: +#if defined (LOG4CPLUS_USE_PTHREADS) + mutable pthread_cond_t cv; + mutable Mutex mtx; + mutable volatile unsigned sigcount; + mutable volatile bool signaled; +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) + HANDLE ev; +#endif + + ManualResetEvent (ManualResetEvent const &); + ManualResetEvent & operator = (ManualResetEvent const &); +}; + + +class SharedMutex + : public SharedMutexImplBase +{ +public: + SharedMutex (); + ~SharedMutex (); + + void rdlock () const; + void wrlock () const; + void rdunlock () const; + void wrunlock () const; + +private: +#if defined (LOG4CPLUS_POOR_MANS_SHAREDMUTEX) + Mutex m1; + Mutex m2; + Mutex m3; + Semaphore w; + mutable unsigned writer_count; + Semaphore r; + mutable unsigned reader_count; + +#elif defined (LOG4CPLUS_USE_PTHREADS) + void unlock () const; + + mutable pthread_rwlock_t rwl; + +#elif defined (LOG4CPLUS_USE_SRW_LOCK) + mutable SRWLOCK srwl; + +#endif + + SharedMutex (SharedMutex const &); + SharedMutex & operator = (SharedMutex const &); +}; + + +} } } // namespace log4cplus { namespace thread { namespace impl { + + +// Include the appropriate implementations of the classes declared +// above. + +#if defined (LOG4CPLUS_USE_PTHREADS) +# include +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) +# include +#endif + + +#undef LOG4CPLUS_THROW_RTE + + +#endif // LOG4CPLUS_THREAD_SYNCPRIMS_IMPL_H diff --git a/sg_agent/thrid_party/logs/include/thread/impl/syncprims-pmsm.h b/sg_agent/thrid_party/logs/include/thread/impl/syncprims-pmsm.h new file mode 100644 index 0000000..34b315d --- /dev/null +++ b/sg_agent/thrid_party/logs/include/thread/impl/syncprims-pmsm.h @@ -0,0 +1,119 @@ +// -*- C++ -*- +// Copyright (C) 2010-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//! @file +//! This file contains implementations of reader-writer locking +//! primitive using other primitives, IOW poor man's rwlock. +//! It does not contain any include guards because it is only a fragment +//! to be included by syncprims-{pthreads,win32}.h. + + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + + +// This implements algorithm described in "Concurrent Control with "Readers" +// and "Writers"; P.J. Courtois, F. Heymans, and D.L. Parnas; +// MBLE Research Laboratory; Brussels, Belgium" + + +inline +SharedMutex::SharedMutex () + : m1 (log4cplus::thread::Mutex::DEFAULT) + , m2 (log4cplus::thread::Mutex::DEFAULT) + , m3 (log4cplus::thread::Mutex::DEFAULT) + , w (1, 1) + , writer_count (0) + , r (1, 1) + , reader_count (0) +{ } + + +inline +SharedMutex::~SharedMutex () +{ } + + +inline +void +SharedMutex::rdlock () const +{ + MutexGuard m3_guard (m3); + SemaphoreGuard r_guard (r); + MutexGuard m1_guard (m1); + if (reader_count + 1 == 1) + w.lock (); + + reader_count += 1; +} + + +inline +void +SharedMutex::rdunlock () const +{ + MutexGuard m1_guard (m1); + if (reader_count - 1 == 0) + w.unlock (); + + reader_count -= 1; +} + + +inline +void +SharedMutex::wrlock () const +{ + { + MutexGuard m2_guard (m2); + if (writer_count + 1 == 1) + r.lock (); + + writer_count += 1; + } + try + { + w.lock (); + } + catch (...) + { + MutexGuard m2_guard (m2); + writer_count -= 1; + throw; + } +} + + +inline +void +SharedMutex::wrunlock () const +{ + w.unlock (); + MutexGuard m2_guard (m2); + if (writer_count - 1 == 0) + r.unlock (); + + writer_count -= 1; +} diff --git a/sg_agent/thrid_party/logs/include/thread/impl/syncprims-pthreads.h b/sg_agent/thrid_party/logs/include/thread/impl/syncprims-pthreads.h new file mode 100644 index 0000000..0d3167c --- /dev/null +++ b/sg_agent/thrid_party/logs/include/thread/impl/syncprims-pthreads.h @@ -0,0 +1,507 @@ +// -*- C++ -*- +// Copyright (C) 2009-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//! @file +//! This file contains implementations of synchronization +//! primitives using the POSIX threads. It does not contain any +//! include guards because it is only a fragment to be included by +//! syncprims.h. + +#include "log4cplus/thread/threads.h" +#include +#include + + +namespace log4cplus { namespace thread { namespace impl { + + +struct PthreadMutexAttr +{ + PthreadMutexAttr () + { + int ret = pthread_mutexattr_init (&attr); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("PthreadMutexAttr::PthreadMutexAttr"); + } + + + ~PthreadMutexAttr () + { + try + { + int ret = pthread_mutexattr_destroy (&attr); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("PthreadMutexAttr::~PthreadMutexAttr"); + } + catch (...) + { } + } + + + void + set_type (log4cplus::thread::Mutex::Type t) + { + int mutex_type; + switch (t) + { + case log4cplus::thread::Mutex::RECURSIVE: + mutex_type = PTHREAD_MUTEX_RECURSIVE; + break; + + default: + mutex_type = PTHREAD_MUTEX_DEFAULT; + } + + int ret = pthread_mutexattr_settype (&attr, mutex_type); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("PthreadMutexAttr::set_type"); + } + + + pthread_mutexattr_t attr; +}; + + +// +// +// + +inline +Mutex::Mutex (log4cplus::thread::Mutex::Type t) +{ + PthreadMutexAttr attr; + attr.set_type (t); + + int ret = pthread_mutex_init (&mtx, &attr.attr); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Mutex::Mutex"); +} + + +inline +Mutex::~Mutex () +{ + try + { + int ret = pthread_mutex_destroy (&mtx); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Mutex::~Mutex"); + } + catch (...) + { } +} + + +inline +void +Mutex::lock () const +{ + int ret = pthread_mutex_lock (&mtx); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Mutex::lock"); +} + + +inline +void +Mutex::unlock () const +{ + int ret = pthread_mutex_unlock (&mtx); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Mutex::unlock"); +} + + +// +// +// + +inline +Semaphore::Semaphore (unsigned max, unsigned initial) +{ + unsigned const sem_value_max = +#if defined (SEM_VALUE_MAX) + SEM_VALUE_MAX +#else + (std::numeric_limits::max) () +#endif + ; + + unsigned const limited_max = (std::min) (max, sem_value_max); + unsigned const limited_initial = (std::min) (initial, limited_max); + int ret = 0; + +#if defined (LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE) + std::ostringstream oss; + char size_check[2 * (static_cast(sizeof (std::ptrdiff_t)) + - static_cast(sizeof (this))) + 1]; + (void)size_check; + oss << getpid () << "-" << reinterpret_cast(this); + std::string name (oss.str ()); + + sem = sem_open (name.c_str (), O_CREAT, S_IRWXU | S_IRWXG, limited_max); + ret = sem == SEM_FAILED; + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::Semaphore"); + + try + { + // Unlink the semaphore early to simulate anonymous semaphore. + ret = sem_unlink (name.c_str ()); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::Semaphore"); + } + catch (std::runtime_error const &) + { + ret = sem_close (sem); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::~Semaphore"); + + throw; + } + +#else + ret = sem_init (&sem, 0, limited_max); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::Semaphore"); + +#endif + + try + { + for (unsigned i = limited_initial; i < limited_max; ++i) + lock (); + } + catch (std::runtime_error const &) + { +#if defined (LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE) + ret = sem_close (sem); +#else + ret = sem_destroy (&sem); +#endif + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::~Semaphore"); + + throw; + } +} + + +inline +Semaphore::~Semaphore () +{ + try + { + int ret = 0; +#if defined (LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE) + ret = sem_close (sem); +#else + ret = sem_destroy (&sem); +#endif + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::~Semaphore"); + } + catch (...) + { } +} + + +inline +void +Semaphore::unlock () const +{ +#if defined (LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE) + int ret = sem_post (sem); +#else + int ret = sem_post (&sem); +#endif + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::unlock"); +} + + +inline +void +Semaphore::lock () const +{ +#if defined (LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE) + int ret = sem_wait (sem); +#else + int ret = sem_wait (&sem); +#endif + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::lock"); +} + + +// +// +// + + +inline +FairMutex::FairMutex () + : sem (1, 1) +{ } + + +inline +FairMutex::~FairMutex () +{ } + + +inline +void +FairMutex::lock () const +{ + sem.lock (); +} + + +inline +void +FairMutex::unlock () const +{ + sem.unlock (); +} + + +// +// +// + +inline +ManualResetEvent::ManualResetEvent (bool sig) + : mtx (log4cplus::thread::Mutex::DEFAULT) + , sigcount (0) + , signaled (sig) +{ + int ret = pthread_cond_init (&cv, 0); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("ManualResetEvent::ManualResetEvent"); +} + + +inline +ManualResetEvent::~ManualResetEvent () +{ + try + { + int ret = pthread_cond_destroy (&cv); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("ManualResetEvent::~ManualResetEvent"); + } + catch (...) + { } +} + + +inline +void +ManualResetEvent::signal () const +{ + MutexGuard mguard (mtx); + + signaled = true; + sigcount += 1; + int ret = pthread_cond_broadcast (&cv); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("ManualResetEVent::signal"); + +} + + +inline +void +ManualResetEvent::wait () const +{ + MutexGuard mguard (mtx); + + if (! signaled) + { + unsigned prev_count = sigcount; + do + { + int ret = pthread_cond_wait (&cv, &mtx.mtx); + if (ret != 0) + { + mguard.unlock (); + mguard.detach (); + LOG4CPLUS_THROW_RTE ("ManualResetEvent::wait"); + } + } + while (prev_count == sigcount); + } +} + + +inline +bool +ManualResetEvent::timed_wait (unsigned long msec) const +{ + MutexGuard mguard (mtx); + + if (! signaled) + { + helpers::Time const wakeup_time (helpers::Time::gettimeofday () + + helpers::Time (msec / 1000, (msec % 1000) * 1000)); + struct timespec const ts = {wakeup_time.sec (), + wakeup_time.usec () * 1000}; + unsigned prev_count = sigcount; + do + { + int ret = pthread_cond_timedwait (&cv, &mtx.mtx, &ts); + switch (ret) + { + case 0: + break; + + case ETIMEDOUT: + return false; + + default: + mguard.unlock (); + mguard.detach (); + LOG4CPLUS_THROW_RTE ("ManualResetEvent::timed_wait"); + } + } + while (prev_count == sigcount); + } + + return true; +} + + +inline +void +ManualResetEvent::reset () const +{ + MutexGuard mguard (mtx); + + signaled = false; +} + + +// +// +// + +#if defined (LOG4CPLUS_POOR_MANS_SHAREDMUTEX) +#include "log4cplus/thread/impl/syncprims-pmsm.h" + +#else +inline +SharedMutex::SharedMutex () +{ + int ret = pthread_rwlock_init (&rwl, 0); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("SharedMutex::SharedMutex"); +} + + +inline +SharedMutex::~SharedMutex () +{ + try + { + int ret = pthread_rwlock_destroy (&rwl); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("SharedMutex::~SharedMutex"); + } + catch (...) + { } +} + + +inline +void +SharedMutex::rdlock () const +{ + int ret; + + do + { + ret = pthread_rwlock_rdlock (&rwl); + switch (ret) + { + case EAGAIN: + // The read lock could not be acquired because the maximum + // number of read locks for rwlock has been exceeded. + + log4cplus::thread::yield (); + // Fall through. + + case 0: + break; + + default: + LOG4CPLUS_THROW_RTE ("SharedMutex::rdlock"); + + } + } + while (ret != 0); +} + + +inline +void +SharedMutex::rdunlock () const +{ + unlock (); +} + + +inline +void +SharedMutex::wrlock () const +{ + int ret = pthread_rwlock_wrlock (&rwl); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("SharedMutex::wrlock"); +} + + +inline +void +SharedMutex::wrunlock () const +{ + unlock (); +} + + +inline +void +SharedMutex::unlock () const +{ + int ret = pthread_rwlock_unlock (&rwl); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("SharedMutex::unlock"); + +} + + +#endif + + +} } } // namespace log4cplus { namespace thread { namespace impl { diff --git a/sg_agent/thrid_party/logs/include/thread/impl/syncprims-win32.h b/sg_agent/thrid_party/logs/include/thread/impl/syncprims-win32.h new file mode 100644 index 0000000..35cc423 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/thread/impl/syncprims-win32.h @@ -0,0 +1,328 @@ +// -*- C++ -*- +// Copyright (C) 2009-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//! @file +//! This file contains implementations of synchronization +//! primitives using the Win32 API. It does not contain any include +//! guards because it is only a fragment to be included by +//! syncprims.h. + +#include + + +namespace log4cplus { namespace thread { namespace impl { + + +// +// +// + +inline +bool +InitializeCriticalSection_wrapInternal (LPCRITICAL_SECTION cs) +{ +#if defined (_MSC_VER) + __try + { +#endif + + InitializeCriticalSection (cs); + +#if defined (_MSC_VER) + } + __except (GetExceptionCode() == STATUS_NO_MEMORY + ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) + { + return false; + } +#endif + + return true; +} + + +inline +void +InitializeCriticalSection_wrap (LPCRITICAL_SECTION cs) +{ + if (! InitializeCriticalSection_wrapInternal (cs)) + throw std::runtime_error ( + "InitializeCriticalSection: STATUS_NO_MEMORY"); +} + + +inline +Mutex::Mutex (log4cplus::thread::Mutex::Type) +{ + InitializeCriticalSection_wrap (&cs); +} + + +inline +Mutex::~Mutex () +{ + DeleteCriticalSection (&cs); +} + + +inline +void +Mutex::lock () const +{ + EnterCriticalSection (&cs); +} + + +inline +void +Mutex::unlock () const +{ + LeaveCriticalSection (&cs); +} + + +// +// +// + +inline +Semaphore::Semaphore (unsigned max, unsigned initial) +{ + sem = CreateSemaphore (0, initial, max, 0); + if (! sem) + LOG4CPLUS_THROW_RTE ("Semaphore::Semaphore"); +} + + +inline +Semaphore::~Semaphore () +{ + try + { + if (! CloseHandle (sem)) + LOG4CPLUS_THROW_RTE ("Semaphore::~Semaphore"); + } + catch (...) + { } +} + + +inline +void +Semaphore::unlock () const +{ + DWORD ret = ReleaseSemaphore (sem, 1, 0); + if (! ret) + LOG4CPLUS_THROW_RTE ("Semaphore::unlock"); +} + + +inline +void +Semaphore::lock () const +{ + DWORD ret = WaitForSingleObject (sem, INFINITE); + if (ret != WAIT_OBJECT_0) + LOG4CPLUS_THROW_RTE ("Semaphore::lock"); +} + + +// +// +// + + +inline +FairMutex::FairMutex () +{ + mtx = CreateMutex (0, false, 0); + if (! mtx) + LOG4CPLUS_THROW_RTE ("FairMutex::FairMutex"); +} + + +inline +FairMutex::~FairMutex () +{ + try + { + if (! CloseHandle (mtx)) + LOG4CPLUS_THROW_RTE ("FairMutex::~FairMutex"); + } + catch (...) + { } +} + + +inline +void +FairMutex::lock () const +{ + DWORD ret = WaitForSingleObject (mtx, INFINITE); + if (ret != WAIT_OBJECT_0) + LOG4CPLUS_THROW_RTE ("FairMutex::lock"); +} + + +inline +void +FairMutex::unlock () const +{ + if (! ReleaseMutex (mtx)) + LOG4CPLUS_THROW_RTE ("FairMutex::unlock"); +} + + +// +// +// + +inline +ManualResetEvent::ManualResetEvent (bool sig) +{ + ev = CreateEvent (0, true, sig, 0); + if (! ev) + LOG4CPLUS_THROW_RTE ("ManualResetEvent::ManualResetEvent"); +} + + +inline +ManualResetEvent::~ManualResetEvent () +{ + try + { + if (! CloseHandle (ev)) + LOG4CPLUS_THROW_RTE ("ManualResetEvent::~ManualResetEvent"); + } + catch (...) + { } +} + + +inline +void +ManualResetEvent::signal () const +{ + if (! SetEvent (ev)) + LOG4CPLUS_THROW_RTE ("ManualResetEVent::signal"); +} + + +inline +void +ManualResetEvent::wait () const +{ + DWORD ret = WaitForSingleObject (ev, INFINITE); + if (ret != WAIT_OBJECT_0) + LOG4CPLUS_THROW_RTE ("ManualResetEvent::wait"); +} + + +inline +bool +ManualResetEvent::timed_wait (unsigned long msec) const +{ + DWORD ret = WaitForSingleObject (ev, static_cast(msec)); + switch(ret) + { + case WAIT_OBJECT_0: + return true; + + case WAIT_TIMEOUT: + return false; + + default: + LOG4CPLUS_THROW_RTE ("ManualResetEvent::timed_wait"); + // Silence warnings about not returning any value from function + // returning bool. + return false; + } +} + + +inline +void +ManualResetEvent::reset () const +{ + if (! ResetEvent (ev)) + LOG4CPLUS_THROW_RTE ("ManualResetEvent::reset"); +} + + +// +// +// + +#if defined (LOG4CPLUS_POOR_MANS_SHAREDMUTEX) +#include "log4cplus/thread/impl/syncprims-pmsm.h" + +#else +inline +SharedMutex::SharedMutex () +{ + InitializeSRWLock (&srwl); +} + + +inline +SharedMutex::~SharedMutex () +{ } + + +inline +void +SharedMutex::rdlock () const +{ + AcquireSRWLockShared (&srwl); +} + + +inline +void +SharedMutex::rdunlock () const +{ + ReleaseSRWLockShared (&srwl); +} + + +inline +void +SharedMutex::wrlock () const +{ + AcquireSRWLockExclusive (&srwl); +} + + +inline +void +SharedMutex::wrunlock () const +{ + ReleaseSRWLockExclusive (&srwl); +} + + +#endif + + +} } } // namespace log4cplus { namespace thread { namespace impl { diff --git a/sg_agent/thrid_party/logs/include/thread/impl/threads-impl.h b/sg_agent/thrid_party/logs/include/thread/impl/threads-impl.h new file mode 100644 index 0000000..88b40b2 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/thread/impl/threads-impl.h @@ -0,0 +1,160 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: threads.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_IMPL_THREADS_IMPL_HEADER_ +#define LOG4CPLUS_IMPL_THREADS_IMPL_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (_WIN32) +#include +#endif +#include +#include +#include + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + + +namespace log4cplus { namespace thread { namespace impl { + + +#if defined (LOG4CPLUS_USE_PTHREADS) + +typedef pthread_t os_handle_type; +typedef pthread_t os_id_type; + + +inline +pthread_t +getCurrentThreadId () +{ + return pthread_self (); +} + + +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) + +typedef HANDLE os_handle_type; +typedef DWORD os_id_type; + + +inline +DWORD +getCurrentThreadId () +{ + return GetCurrentThreadId (); +} + + +#elif defined (LOG4CPLUS_SINGLE_THREADED) + +typedef void * os_handle_type; +typedef int os_id_type; + + +inline +int +getCurrentThreadId () +{ + return 1; +} + + +#endif + + +#ifndef LOG4CPLUS_SINGLE_THREADED + + +struct ThreadStart +{ +# ifdef LOG4CPLUS_USE_PTHREADS +static void* threadStartFuncWorker(void *); +# elif defined(LOG4CPLUS_USE_WIN32_THREADS) +static unsigned threadStartFuncWorker(void *); +# endif +}; + + +/** + * There are many cross-platform C++ Threading libraries. The goal of + * this class is not to replace (or match in functionality) those + * libraries. The goal of this class is to provide a simple Threading + * class with basic functionality. + */ +class Thread + : public ThreadImplBase +{ +public: + Thread(); + bool isRunning() const; + os_id_type getThreadId() const; + os_handle_type getThreadHandle () const; + void start(); + void join (); + +protected: + // Force objects to be constructed on the heap + virtual ~Thread(); + virtual void run() = 0; + +private: + // Friends. + friend struct ThreadStart; + + enum Flags + { + fRUNNING = 0x01, + fJOINED = 0x02 + }; + + unsigned flags; + + os_handle_type handle; + +# if defined(LOG4CPLUS_USE_WIN32_THREADS) + unsigned thread_id; +# endif + + // Disallow copying of instances of this class. + Thread(const Thread&); + Thread& operator=(const Thread&); +}; + +typedef helpers::SharedObjectPtr ThreadPtr; + + +#endif // LOG4CPLUS_SINGLE_THREADED + + +} } } // namespace log4cplus { namespace thread { namespace impl { + + +#endif // LOG4CPLUS_IMPL_THREADS_IMPL_HEADER_ diff --git a/sg_agent/thrid_party/logs/include/thread/impl/tls.h b/sg_agent/thrid_party/logs/include/thread/impl/tls.h new file mode 100644 index 0000000..5a390ae --- /dev/null +++ b/sg_agent/thrid_party/logs/include/thread/impl/tls.h @@ -0,0 +1,180 @@ +// -*- C++ -*- +// Copyright (C) 2010-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_THREAD_IMPL_TLS_H +#define LOG4CPLUS_THREAD_IMPL_TLS_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + +#ifdef LOG4CPLUS_USE_PTHREADS +# include + +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) +# include + +#elif defined (LOG4CPLUS_SINGLE_THREADED) +# include + +#endif + + +namespace log4cplus { namespace thread { namespace impl { + + +typedef void * tls_value_type; +typedef void (* tls_init_cleanup_func_type)(void *); + +#ifdef LOG4CPLUS_USE_PTHREADS +typedef pthread_key_t * tls_key_type; + +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) +typedef DWORD tls_key_type; + +#elif defined (LOG4CPLUS_SINGLE_THREADED) +typedef std::size_t tls_key_type; + +#endif + + +inline tls_key_type tls_init (tls_init_cleanup_func_type); +inline tls_value_type tls_get_value (tls_key_type); +inline void tls_set_value (tls_key_type, tls_value_type); +inline void tls_cleanup (tls_key_type); + + +#if defined (LOG4CPLUS_USE_PTHREADS) +tls_key_type +tls_init (tls_init_cleanup_func_type cleanupfunc) +{ + pthread_key_t * key = new pthread_key_t; + pthread_key_create (key, cleanupfunc); + return key; +} + + +tls_value_type +tls_get_value (tls_key_type key) +{ + return pthread_getspecific (*key); +} + + +void +tls_set_value (tls_key_type key, tls_value_type value) +{ + pthread_setspecific(*key, value); +} + + +void +tls_cleanup (tls_key_type key) +{ + pthread_key_delete (*key); + delete key; +} + + +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) +tls_key_type +tls_init (tls_init_cleanup_func_type) +{ + return TlsAlloc (); +} + + +tls_value_type tls_get_value (tls_key_type k) +{ + return TlsGetValue (k); +} + + +void +tls_set_value (tls_key_type k, tls_value_type value) +{ + TlsSetValue (k, value); +} + + +void +tls_cleanup (tls_key_type k) +{ + TlsFree (k); +} + + +#elif defined (LOG4CPLUS_SINGLE_THREADED) +extern std::vector * tls_single_threaded_values; + + +tls_key_type +tls_init (tls_init_cleanup_func_type) +{ + if (! tls_single_threaded_values) + tls_single_threaded_values = new std::vector; + tls_key_type key = tls_single_threaded_values->size (); + tls_single_threaded_values->resize (key + 1); + return key; +} + + +tls_value_type +tls_get_value (tls_key_type k) +{ + assert (k < tls_single_threaded_values->size ()); + return (*tls_single_threaded_values)[k]; +} + + +void +tls_set_value (tls_key_type k, tls_value_type val) +{ + assert (k < tls_single_threaded_values->size ()); + (*tls_single_threaded_values)[k] = val; +} + + +void +tls_cleanup (tls_key_type k) +{ + assert (k < tls_single_threaded_values->size ()); + (*tls_single_threaded_values)[k] = 0; +} + +#endif + + +} } } // namespace log4cplus { namespace thread { namespace impl { + +#endif // LOG4CPLUS_THREAD_IMPL_TLS_H diff --git a/sg_agent/thrid_party/logs/include/thread/syncprims-pub-impl.h b/sg_agent/thrid_party/logs/include/thread/syncprims-pub-impl.h new file mode 100644 index 0000000..15e045c --- /dev/null +++ b/sg_agent/thrid_party/logs/include/thread/syncprims-pub-impl.h @@ -0,0 +1,306 @@ +// -*- C++ -*- +// Copyright (C) 2010-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_THREAD_SYNCPRIMS_PUB_IMPL_H +#define LOG4CPLUS_THREAD_SYNCPRIMS_PUB_IMPL_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if (defined (LOG4CPLUS_INLINES_ARE_EXPORTED) \ + && defined (LOG4CPLUS_BUILD_DLL)) \ + || defined (LOG4CPLUS_ENABLE_SYNCPRIMS_PUB_IMPL) +#include + +#if defined (LOG4CPLUS_SINGLE_THREADED) +# define LOG4CPLUS_THREADED(x) +# define LOG4CPLUS_THREADED2(x, y) (y) +#else +# include +# define LOG4CPLUS_THREADED(x) (x) +# define LOG4CPLUS_THREADED2(x, y) (x) +#endif + + +namespace log4cplus { namespace thread { + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +MutexImplBase::~MutexImplBase () +{ } + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +Mutex::Mutex (Mutex::Type LOG4CPLUS_THREADED (t)) + : mtx (LOG4CPLUS_THREADED2 (new impl::Mutex (t), + static_cast(0))) +{ } + + +LOG4CPLUS_INLINE_EXPORT +Mutex::~Mutex () +{ + LOG4CPLUS_THREADED (delete static_cast(mtx)); +} + + +LOG4CPLUS_INLINE_EXPORT +void +Mutex::lock () const +{ + LOG4CPLUS_THREADED (static_cast(mtx)->lock ()); +} + + +LOG4CPLUS_INLINE_EXPORT +void +Mutex::unlock () const +{ + LOG4CPLUS_THREADED (static_cast(mtx)->unlock ()); +} + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +SemaphoreImplBase::~SemaphoreImplBase () +{ } + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +Semaphore::Semaphore (unsigned LOG4CPLUS_THREADED (max), + unsigned LOG4CPLUS_THREADED (initial)) + : sem (LOG4CPLUS_THREADED2 (new impl::Semaphore (max, initial), + static_cast(0))) +{ } + + +LOG4CPLUS_INLINE_EXPORT +Semaphore::~Semaphore () +{ + LOG4CPLUS_THREADED (delete static_cast(sem)); +} + + +LOG4CPLUS_INLINE_EXPORT +void +Semaphore::lock () const +{ + LOG4CPLUS_THREADED (static_cast(sem)->lock ()); +} + + +LOG4CPLUS_INLINE_EXPORT +void +Semaphore::unlock () const +{ + LOG4CPLUS_THREADED (static_cast(sem)->unlock ()); +} + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +FairMutexImplBase::~FairMutexImplBase () +{ } + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +FairMutex::FairMutex () + : mtx (LOG4CPLUS_THREADED2 (new impl::FairMutex, + static_cast(0))) +{ } + + +LOG4CPLUS_INLINE_EXPORT +FairMutex::~FairMutex () +{ + LOG4CPLUS_THREADED (delete static_cast(mtx)); +} + + +LOG4CPLUS_INLINE_EXPORT +void +FairMutex::lock () const +{ + LOG4CPLUS_THREADED (static_cast(mtx)->lock ()); +} + + +LOG4CPLUS_INLINE_EXPORT +void +FairMutex::unlock () const +{ + LOG4CPLUS_THREADED (static_cast(mtx)->unlock ()); +} + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +ManualResetEventImplBase::~ManualResetEventImplBase () +{ } + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +ManualResetEvent::ManualResetEvent (bool LOG4CPLUS_THREADED (sig)) + : ev (LOG4CPLUS_THREADED2 (new impl::ManualResetEvent (sig), + static_cast(0))) +{ } + + +LOG4CPLUS_INLINE_EXPORT +ManualResetEvent::~ManualResetEvent () +{ + LOG4CPLUS_THREADED (delete static_cast(ev)); +} + + +LOG4CPLUS_INLINE_EXPORT +void +ManualResetEvent::signal () const +{ + LOG4CPLUS_THREADED (static_cast(ev)->signal ()); +} + + +LOG4CPLUS_INLINE_EXPORT +void +ManualResetEvent::wait () const +{ + LOG4CPLUS_THREADED (static_cast(ev)->wait ()); +} + + +LOG4CPLUS_INLINE_EXPORT +bool +ManualResetEvent::timed_wait (unsigned long LOG4CPLUS_THREADED (msec)) const +{ +#if defined (LOG4CPLUS_SINGLE_THREADED) + return true; +#else + return static_cast(ev)->timed_wait (msec); +#endif +} + + +LOG4CPLUS_INLINE_EXPORT +void +ManualResetEvent::reset () const +{ + LOG4CPLUS_THREADED (static_cast(ev)->reset ()); +} + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +SharedMutexImplBase::~SharedMutexImplBase () +{ } + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +SharedMutex::SharedMutex () + : sm (LOG4CPLUS_THREADED2 (new impl::SharedMutex, + static_cast(0))) +{ } + + +LOG4CPLUS_INLINE_EXPORT +SharedMutex::~SharedMutex () +{ } + + +LOG4CPLUS_INLINE_EXPORT +void +SharedMutex::rdlock () const +{ + LOG4CPLUS_THREADED (static_cast(sm)->rdlock ()); +} + + +LOG4CPLUS_INLINE_EXPORT +void +SharedMutex::wrlock () const +{ + LOG4CPLUS_THREADED (static_cast(sm)->wrlock ()); +} + + +LOG4CPLUS_INLINE_EXPORT +void +SharedMutex::rdunlock () const +{ + LOG4CPLUS_THREADED (static_cast(sm)->rdunlock ()); +} + + +LOG4CPLUS_INLINE_EXPORT +void +SharedMutex::wrunlock () const +{ + LOG4CPLUS_THREADED (static_cast(sm)->wrunlock ()); +} + + +} } // namespace log4cplus { namespace thread { + +#endif // LOG4CPLUS_ENABLE_SYNCPRIMS_PUB_IMPL + +#endif // LOG4CPLUS_THREAD_SYNCPRIMS_PUB_IMPL_H diff --git a/sg_agent/thrid_party/logs/include/thread/syncprims.h b/sg_agent/thrid_party/logs/include/thread/syncprims.h new file mode 100644 index 0000000..d043845 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/thread/syncprims.h @@ -0,0 +1,382 @@ +// -*- C++ -*- +// Copyright (C) 2010-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_THREAD_SYNCPRIMS_H +#define LOG4CPLUS_THREAD_SYNCPRIMS_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + + +namespace log4cplus { namespace thread { + + +template +class SyncGuard +{ +public: + SyncGuard (); + SyncGuard (SP const &); + ~SyncGuard (); + + void lock (); + void unlock (); + void attach (SP const &); + void attach_and_lock (SP const &); + void detach (); + +private: + SP const * sp; + + SyncGuard (SyncGuard const &); + SyncGuard & operator = (SyncGuard const &); +}; + + +class ManualResetEvent; + + +class MutexImplBase +{ +protected: + ~MutexImplBase (); +}; + + +class LOG4CPLUS_EXPORT Mutex +{ +public: + enum Type + { + DEFAULT, + RECURSIVE + }; + + explicit Mutex (Type = RECURSIVE); + ~Mutex (); + + void lock () const; + void unlock () const; + +private: + MutexImplBase * mtx; + + Mutex (Mutex const &); + Mutex & operator = (Mutex &); +}; + + +typedef SyncGuard MutexGuard; + + +class SemaphoreImplBase +{ +protected: + ~SemaphoreImplBase (); +}; + + +class LOG4CPLUS_EXPORT Semaphore +{ +public: + Semaphore (unsigned max, unsigned initial); + ~Semaphore (); + + void lock () const; + void unlock () const; + +private: + SemaphoreImplBase * sem; + + Semaphore (Semaphore const &); + Semaphore & operator = (Semaphore const &); +}; + + +typedef SyncGuard SemaphoreGuard; + + +class FairMutexImplBase +{ +protected: + ~FairMutexImplBase (); +}; + + +class LOG4CPLUS_EXPORT FairMutex +{ +public: + FairMutex (); + ~FairMutex (); + + void lock () const; + void unlock () const; + +private: + FairMutexImplBase * mtx; + + FairMutex (FairMutex const &); + FairMutex & operator = (FairMutex &); +}; + + +typedef SyncGuard FairMutexGuard; + + +class ManualResetEventImplBase +{ +protected: + ~ManualResetEventImplBase (); +}; + + +class LOG4CPLUS_EXPORT ManualResetEvent +{ +public: + ManualResetEvent (bool = false); + ~ManualResetEvent (); + + void signal () const; + void wait () const; + bool timed_wait (unsigned long msec) const; + void reset () const; + +private: + ManualResetEventImplBase * ev; + + ManualResetEvent (ManualResetEvent const &); + ManualResetEvent & operator = (ManualResetEvent const &); +}; + + +class SharedMutexImplBase +{ +protected: + ~SharedMutexImplBase (); +}; + + +template +class SyncGuardFunc +{ +public: + SyncGuardFunc (SP const &); + ~SyncGuardFunc (); + + void lock (); + void unlock (); + void attach (SP const &); + void detach (); + +private: + SP const * sp; + + SyncGuardFunc (SyncGuardFunc const &); + SyncGuardFunc & operator = (SyncGuardFunc const &); +}; + + +class LOG4CPLUS_EXPORT SharedMutex +{ +public: + SharedMutex (); + ~SharedMutex (); + + void rdlock () const; + void rdunlock () const; + + void wrlock () const; + void wrunlock () const; + +private: + SharedMutexImplBase * sm; + + SharedMutex (SharedMutex const &); + SharedMutex & operator = (SharedMutex const &); +}; + + +typedef SyncGuardFunc SharedMutexReaderGuard; + + +typedef SyncGuardFunc SharedMutexWriterGuard; + + +// +// +// + +template +inline +SyncGuard::SyncGuard () + : sp (0) +{ } + + +template +inline +SyncGuard::SyncGuard (SP const & m) + : sp (&m) +{ + sp->lock (); +} + + +template +inline +SyncGuard::~SyncGuard () +{ + if (sp) + sp->unlock (); +} + + +template +inline +void +SyncGuard::lock () +{ + sp->lock (); +} + + +template +inline +void +SyncGuard::unlock () +{ + sp->unlock (); +} + + +template +inline +void +SyncGuard::attach (SP const & m) +{ + sp = &m; +} + + +template +inline +void +SyncGuard::attach_and_lock (SP const & m) +{ + attach (m); + try + { + lock(); + } + catch (...) + { + detach (); + throw; + } +} + + +template +inline +void +SyncGuard::detach () +{ + sp = 0; +} + + +// +// +// + +template +inline +SyncGuardFunc::SyncGuardFunc (SP const & m) + : sp (&m) +{ + (sp->*lock_func) (); +} + + +template +inline +SyncGuardFunc::~SyncGuardFunc () +{ + if (sp) + (sp->*unlock_func) (); +} + + +template +inline +void +SyncGuardFunc::lock () +{ + (sp->*lock_func) (); +} + + +template +inline +void +SyncGuardFunc::unlock () +{ + (sp->*unlock_func) (); +} + + +template +inline +void +SyncGuardFunc::attach (SP const & m) +{ + sp = &m; +} + + +template +inline +void +SyncGuardFunc::detach () +{ + sp = 0; +} + + +} } // namespace log4cplus { namespace thread { + + +#endif // LOG4CPLUS_THREAD_SYNCPRIMS_H diff --git a/sg_agent/thrid_party/logs/include/thread/threads.h b/sg_agent/thrid_party/logs/include/thread/threads.h new file mode 100644 index 0000000..82149c4 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/thread/threads.h @@ -0,0 +1,96 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: threads.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_THREADS_HEADER_ +#define LOG4CPLUS_THREADS_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus { namespace thread { + + +LOG4CPLUS_EXPORT log4cplus::tstring const & getCurrentThreadName(); +LOG4CPLUS_EXPORT log4cplus::tstring const & getCurrentThreadName2(); +LOG4CPLUS_EXPORT void setCurrentThreadName(const log4cplus::tstring & name); +LOG4CPLUS_EXPORT void setCurrentThreadName2(const log4cplus::tstring & name); +LOG4CPLUS_EXPORT void yield(); +LOG4CPLUS_EXPORT void blockAllSignals(); + + +#ifndef LOG4CPLUS_SINGLE_THREADED + +class ThreadImplBase + : public virtual log4cplus::helpers::SharedObject +{ +protected: + virtual ~ThreadImplBase (); +}; + + +/** + * There are many cross-platform C++ Threading libraries. The goal of + * this class is not to replace (or match in functionality) those + * libraries. The goal of this class is to provide a simple Threading + * class with basic functionality. + */ +class LOG4CPLUS_EXPORT AbstractThread + : public virtual log4cplus::helpers::SharedObject +{ +public: + AbstractThread(); + bool isRunning() const; + virtual void start(); + void join () const; + virtual void run() = 0; + +protected: + // Force objects to be constructed on the heap + virtual ~AbstractThread(); + +private: + helpers::SharedObjectPtr thread; + + // Disallow copying of instances of this class. + AbstractThread(const AbstractThread&); + AbstractThread& operator=(const AbstractThread&); +}; + +typedef helpers::SharedObjectPtr AbstractThreadPtr; + + +#endif // LOG4CPLUS_SINGLE_THREADED + + +} } // namespace log4cplus { namespace thread { + + +#endif // LOG4CPLUS_THREADS_HEADER_ + diff --git a/sg_agent/thrid_party/logs/include/tracelogger.h b/sg_agent/thrid_party/logs/include/tracelogger.h new file mode 100644 index 0000000..a056ccd --- /dev/null +++ b/sg_agent/thrid_party/logs/include/tracelogger.h @@ -0,0 +1,79 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: tracelogger.h +// Created: 1/2009 +// Author: Vaclav Haisman +// +// +// Copyright 2009-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_TRACELOGGER_H +#define LOG4CPLUS_TRACELOGGER_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + + +namespace log4cplus +{ + + +/** + * This class is used to produce "Trace" logging. When an instance of + * this class is created, it will log a "ENTER: " + msg + * log message if TRACE_LOG_LEVEL is enabled for logger. + * When an instance of this class is destroyed, it will log a + * "ENTER: " + msg log message if TRACE_LOG_LEVEL is enabled + * for logger. + *

+ * @see LOG4CPLUS_TRACE + */ +class TraceLogger +{ +public: + TraceLogger(const Logger& l, const log4cplus::tstring& _msg, + const char* _file=NULL, int _line=-1) + : logger(l), msg(_msg), file(_file), line(_line) + { if(logger.isEnabledFor(TRACE_LOG_LEVEL)) + logger.forcedLog(TRACE_LOG_LEVEL, LOG4CPLUS_TEXT("ENTER: ") + msg, file, line); + } + + ~TraceLogger() + { if(logger.isEnabledFor(TRACE_LOG_LEVEL)) + logger.forcedLog(TRACE_LOG_LEVEL, LOG4CPLUS_TEXT("EXIT: ") + msg, file, line); + } + +private: + TraceLogger (TraceLogger const &); + TraceLogger & operator = (TraceLogger const &); + + Logger logger; + log4cplus::tstring msg; + const char* file; + int line; +}; + + +} // log4cplus + + +#endif // LOG4CPLUS_TRACELOGGER_H diff --git a/sg_agent/thrid_party/logs/include/tstring.h b/sg_agent/thrid_party/logs/include/tstring.h new file mode 100644 index 0000000..587aaa1 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/tstring.h @@ -0,0 +1,134 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: tstring.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_TSTRING_HEADER_ +#define LOG4CPLUS_TSTRING_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + +namespace log4cplus +{ + +typedef std::basic_string tstring; + + +namespace helpers +{ + +inline +std::string +tostring (char const * str) +{ + return std::string (str); +} + +inline +std::string +tostring (std::string const & str) +{ + return str; +} + +inline +std::string const & +tostring (std::string & str) +{ + return str; +} + +#ifdef LOG4CPLUS_HAVE_RVALUE_REFS +inline +std::string +tostring (std::string && str) +{ + return std::move (str); +} + +#endif + + + +inline +std::wstring +towstring (wchar_t const * str) +{ + return std::wstring (str); +} + +inline +std::wstring +towstring (std::wstring const & str) +{ + return str; +} + +inline +std::wstring const & +towstring (std::wstring & str) +{ + return str; +} + +#ifdef LOG4CPLUS_HAVE_RVALUE_REFS +inline +std::wstring +towstring (std::wstring && str) +{ + return std::move (str); +} + +#endif + +LOG4CPLUS_EXPORT std::string tostring(const std::wstring&); +LOG4CPLUS_EXPORT std::string tostring(wchar_t const *); + +LOG4CPLUS_EXPORT std::wstring towstring(const std::string&); +LOG4CPLUS_EXPORT std::wstring towstring(char const *); + +} // namespace helpers + +#ifdef UNICODE + +#define LOG4CPLUS_C_STR_TO_TSTRING(STRING) log4cplus::helpers::towstring(STRING) +#define LOG4CPLUS_STRING_TO_TSTRING(STRING) log4cplus::helpers::towstring(STRING) +#define LOG4CPLUS_TSTRING_TO_STRING(STRING) log4cplus::helpers::tostring(STRING) + +#else // UNICODE + +#define LOG4CPLUS_C_STR_TO_TSTRING(STRING) std::string(STRING) +#define LOG4CPLUS_STRING_TO_TSTRING(STRING) STRING +#define LOG4CPLUS_TSTRING_TO_STRING(STRING) STRING + +#endif // UNICODE + +} // namespace log4cplus + + +#endif // LOG4CPLUS_TSTRING_HEADER_ diff --git a/sg_agent/thrid_party/logs/include/version.h b/sg_agent/thrid_party/logs/include/version.h new file mode 100644 index 0000000..0481df9 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/version.h @@ -0,0 +1,53 @@ +// -*- C++ -*- +// Copyright (C) 2010-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#if ! defined (LOG4CPLUS_VERSION_H) +#define LOG4CPLUS_VERSION_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#define LOG4CPLUS_MAKE_VERSION(major, minor, point) \ + (major * 1000 * 1000u + minor * 1000u + point) + +#define LOG4CPLUS_MAKE_VERSION_STR(major, minor, point) \ + #major "." #minor "." #point + +#define LOG4CPLUS_VERSION LOG4CPLUS_MAKE_VERSION(1, 1, 3) +#define LOG4CPLUS_VERSION_STR LOG4CPLUS_MAKE_VERSION_STR(1, 1, 3) + + +namespace log4cplus +{ + +extern LOG4CPLUS_EXPORT unsigned const version; +extern LOG4CPLUS_EXPORT char const versionStr[]; + +} + +#endif diff --git a/sg_agent/thrid_party/logs/include/win32consoleappender.h b/sg_agent/thrid_party/logs/include/win32consoleappender.h new file mode 100644 index 0000000..c98eb55 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/win32consoleappender.h @@ -0,0 +1,93 @@ +// -*- C++ -*- +// Copyright (C) 2009-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_WIN32CONSOLEAPPENDER_H +#define LOG4CPLUS_WIN32CONSOLEAPPENDER_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined(_WIN32) && defined (LOG4CPLUS_HAVE_WIN32_CONSOLE) + +#include + + +namespace log4cplus +{ + + /** + * Prints events to Win32 console. + * + *

Properties

+ *
+ *
AllocConsole
+ *
This boolean property specifies whether or not this appender + * will try to allocate new console using the + * AllocConsole() Win32 function.
+ * + *
logToStdErr
+ *
When it is set true, the output will be into + * STD_ERROR_HANDLE instead of STD_OUTPUT_HANDLE. + *
+ * + *
TextColor
+ *
See MSDN documentation for + * + * Character Attributes. + *
+ */ + class LOG4CPLUS_EXPORT Win32ConsoleAppender + : public Appender + { + public: + explicit Win32ConsoleAppender (bool allocConsole = true, + bool logToStdErr = false, unsigned int textColor = 0); + Win32ConsoleAppender (helpers::Properties const & properties); + virtual ~Win32ConsoleAppender (); + + virtual void close (); + + protected: + virtual void append (spi::InternalLoggingEvent const &); + + void write_handle (void *, tchar const *, std::size_t); + void write_console (void *, tchar const *, std::size_t); + + bool alloc_console; + bool log_to_std_err; + unsigned int text_color; + + private: + Win32ConsoleAppender (Win32ConsoleAppender const &); + Win32ConsoleAppender & operator = (Win32ConsoleAppender const &); + }; + +} // namespace log4cplus + +#endif + +#endif // LOG4CPLUS_WIN32CONSOLEAPPENDER_H diff --git a/sg_agent/thrid_party/logs/include/win32debugappender.h b/sg_agent/thrid_party/logs/include/win32debugappender.h new file mode 100644 index 0000000..50059d4 --- /dev/null +++ b/sg_agent/thrid_party/logs/include/win32debugappender.h @@ -0,0 +1,69 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: win32debugappender.h +// Created: 12/2003 +// Author: Eduardo Francos, Odalio SARL +// +// +// Copyright 2003-2013 Odalio SARL +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_WIN32DEBUG_APPENDER_HEADER_ +#define LOG4CPLUS_WIN32DEBUG_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (LOG4CPLUS_HAVE_OUTPUTDEBUGSTRING) + +#include + + +namespace log4cplus { + + /** + * Prints log events using OutputDebugString(). + */ + class LOG4CPLUS_EXPORT Win32DebugAppender + : public Appender + { + public: + // Ctors + Win32DebugAppender(); + Win32DebugAppender(const log4cplus::helpers::Properties& properties); + + // Dtor + virtual ~Win32DebugAppender(); + + // Methods + virtual void close(); + + protected: + virtual void append(const log4cplus::spi::InternalLoggingEvent& event); + + private: + // Disallow copying of instances of this class + Win32DebugAppender(const Win32DebugAppender&); + Win32DebugAppender& operator=(const Win32DebugAppender&); + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_HAVE_OUTPUTDEBUGSTRING +#endif // LOG4CPLUS_WIN32DEBUG_APPENDER_HEADER_ diff --git a/sg_agent/thrid_party/logs/lib/liblog4cplus.a b/sg_agent/thrid_party/logs/lib/liblog4cplus.a new file mode 100644 index 0000000..526efce Binary files /dev/null and b/sg_agent/thrid_party/logs/lib/liblog4cplus.a differ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/appender.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/appender.h new file mode 100644 index 0000000..5eca94c --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/appender.h @@ -0,0 +1,289 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: appender.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_APPENDER_HEADER_ +#define LOG4CPLUS_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include + +#include + + +namespace log4cplus { + + + namespace helpers + { + + class Properties; + + } + + + /** + * This class is used to "handle" errors encountered in an {@link + * log4cplus::Appender}. + */ + class LOG4CPLUS_EXPORT ErrorHandler + { + public: + ErrorHandler (); + virtual ~ErrorHandler() = 0; + virtual void error(const log4cplus::tstring& err) = 0; + virtual void reset() = 0; + }; + + + class LOG4CPLUS_EXPORT OnlyOnceErrorHandler + : public ErrorHandler + { + public: + // Ctor + OnlyOnceErrorHandler(); + virtual ~OnlyOnceErrorHandler (); + virtual void error(const log4cplus::tstring& err); + virtual void reset(); + + private: + bool firstTime; + }; + + + /** + * Extend this class for implementing your own strategies for printing log + * statements. + * + *

Properties

+ *
+ * + *
layout
+ *
This property specifies message layout used by + * Appender. + * \sa Layout + *
+ * + *
filters
+ *
This property specifies possibly multiple filters used by + * Appender. Each of multple filters and its properties is under a + * numbered subkey of filters key. E.g.: + * filters.1=log4cplus::spi::LogLevelMatchFilter. Filter + * subkey numbers must be consecutive.
+ * + *
Threshold
+ *
This property specifies log level threshold. Events with + * lower log level than the threshold will not be logged by + * appender.
+ * + *
UseLockFile
+ *
Set this property to true if you want your output + * through this appender to be synchronized between multiple + * processes. When this property is set to true then log4cplus + * uses OS specific facilities (e.g., lockf()) to + * provide inter-process locking. With the exception of + * FileAppender and its derived classes, it is also necessary to + * provide path to a lock file using the LockFile + * property. + * \sa FileAppender + *
+ * + *
LockFile
+ *
This property specifies lock file, file used for + * inter-process synchronization of log file access. The property + * is only used when UseLockFile is set to true. Then it + * is mandatory. + * \sa FileAppender + *
+ *
+ */ + class LOG4CPLUS_EXPORT Appender + : public virtual log4cplus::helpers::SharedObject + { + public: + // Ctor + Appender(); + Appender(const log4cplus::helpers::Properties & properties); + + // Dtor + virtual ~Appender(); + + /** + * This function is for derived appenders to call from their + * destructors. All classes derived from `Appender` class + * _must_ call this function from their destructors. It + * ensures that appenders will get properly closed during + * shutdown by call to `close()` function before they are + * destroyed. + */ + void destructorImpl(); + + // Methods + /** + * Release any resources allocated within the appender such as file + * handles, network connections, etc. + * + * It is a programming error to append to a closed appender. + */ + virtual void close() = 0; + + /** + * Check if this appender is in closed state. + */ + bool isClosed() const; + + /** + * This method performs threshold checks and invokes filters before + * delegating actual logging to the subclasses specific {@link + * #append} method. + */ + void doAppend(const log4cplus::spi::InternalLoggingEvent& event); + + /** + * Get the name of this appender. The name uniquely identifies the + * appender. + */ + virtual log4cplus::tstring getName(); + + /** + * Set the name of this appender. The name is used by other + * components to identify this appender. + */ + virtual void setName(const log4cplus::tstring& name); + + /** + * Set the {@link ErrorHandler} for this Appender. + */ + virtual void setErrorHandler(std::auto_ptr eh); + + /** + * Return the currently set {@link ErrorHandler} for this + * Appender. + */ + virtual ErrorHandler* getErrorHandler(); + + /** + * Set the layout for this appender. Note that some appenders have + * their own (fixed) layouts or do not use one. For example, the + * SocketAppender ignores the layout set here. + */ + virtual void setLayout(std::auto_ptr layout); + + /** + * Returns the layout of this appender. The value may be NULL. + * + * This class owns the returned pointer. + */ + virtual Layout* getLayout(); + + /** + * Set the filter chain on this Appender. + */ + void setFilter(log4cplus::spi::FilterPtr f) { filter = f; } + + /** + * Get the filter chain on this Appender. + */ + log4cplus::spi::FilterPtr getFilter() const { return filter; } + + /** + * Returns this appenders threshold LogLevel. See the {@link + * #setThreshold} method for the meaning of this option. + */ + LogLevel getThreshold() const { return threshold; } + + /** + * Set the threshold LogLevel. All log events with lower LogLevel + * than the threshold LogLevel are ignored by the appender. + * + * In configuration files this option is specified by setting the + * value of the Threshold option to a LogLevel + * string, such as "DEBUG", "INFO" and so on. + */ + void setThreshold(LogLevel th) { threshold = th; } + + /** + * Check whether the message LogLevel is below the appender's + * threshold. If there is no threshold set, then the return value is + * always true. + */ + bool isAsSevereAsThreshold(LogLevel ll) const { + return ((ll != NOT_SET_LOG_LEVEL) && (ll >= threshold)); + } + + protected: + // Methods + /** + * Subclasses of Appender should implement this + * method to perform actual logging. + * @see doAppend method. + */ + virtual void append(const log4cplus::spi::InternalLoggingEvent& event) = 0; + + tstring & formatEvent (const log4cplus::spi::InternalLoggingEvent& event) const; + + // Data + /** The layout variable does not need to be set if the appender + * implementation has its own layout. */ + std::auto_ptr layout; + + /** Appenders are named. */ + log4cplus::tstring name; + + /** There is no LogLevel threshold filtering by default. */ + LogLevel threshold; + + /** The first filter in the filter chain. Set to null + * initially. */ + log4cplus::spi::FilterPtr filter; + + /** It is assumed and enforced that errorHandler is never null. */ + std::auto_ptr errorHandler; + + //! Optional system wide synchronization lock. + std::auto_ptr lockFile; + + //! Use lock file for inter-process synchronization of access + //! to log file. + bool useLockFile; + + /** Is this appender closed? */ + bool closed; + }; + + /** This is a pointer to an Appender. */ + typedef helpers::SharedObjectPtr SharedAppenderPtr; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_APPENDER_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/asyncappender.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/asyncappender.h new file mode 100644 index 0000000..af9d5e5 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/asyncappender.h @@ -0,0 +1,90 @@ +// -*- C++ -*- +// Module: Log4cplus +// File: asyncappender.h +// Created: 1/2009 +// Author: Vaclav Haisman +// +// +// Copyright (C) 2009-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// + +/** @file */ + +#ifndef LOG4CPLUS_ASYNCAPPENDER_H +#define LOG4CPLUS_ASYNCAPPENDER_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#ifndef LOG4CPLUS_SINGLE_THREADED + +#include +#include +#include +#include + + +namespace log4cplus +{ + + +class LOG4CPLUS_EXPORT AsyncAppender + : public Appender + , public helpers::AppenderAttachableImpl +{ +public: + AsyncAppender (SharedAppenderPtr const & app, unsigned max_len); + AsyncAppender (helpers::Properties const &); + virtual ~AsyncAppender (); + + virtual void close (); + +protected: + virtual void append (spi::InternalLoggingEvent const &); + + void init_queue_thread (unsigned); + + thread::AbstractThreadPtr queue_thread; + thread::QueuePtr queue; + +private: + AsyncAppender (AsyncAppender const &); + AsyncAppender & operator = (AsyncAppender const &); +}; + + +typedef helpers::SharedObjectPtr AsyncAppenderPtr; + + +} // namespace log4cplus + + +#endif // LOG4CPLUS_SINGLE_THREADED + +#endif // LOG4CPLUS_ASYNCAPPENDER_H diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/boost/deviceappender.hxx b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/boost/deviceappender.hxx new file mode 100644 index 0000000..e31fc79 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/boost/deviceappender.hxx @@ -0,0 +1,201 @@ +// Copyright (C) 2009-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_BOOST_DEVICEAPPENDER_HXX +#define LOG4CPLUS_BOOST_DEVICEAPPENDER_HXX + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include + + +namespace log4cplus +{ + + +namespace device_appender_detail +{ + + +template +struct device_type_traits +{ + typedef T & device_type; + + static + device_type + unwrap (device_type x) + { + return x; + } +}; + + +template +struct device_type_traits > +{ + typedef boost::shared_ptr device_type; + + static + T & + unwrap (device_type const & ptr) + { + return *ptr; + } +}; + + +} // namespace device_appender_detail + + +template +class DeviceAppender + : public Appender +{ +public: + typedef device_appender_detail::device_type_traits device_traits; + typedef typename device_traits::device_type device_type; + + template + DeviceAppender (D & d, bool close_device = true) + : device (d) + , close_flag (close_device) + { } + + template + DeviceAppender (boost::shared_ptr const & d, bool close_device = true) + : device (d) + , close_flag (close_device) + { } + + template + DeviceAppender (D & d, const helpers::Properties & props) + : Appender (props) + , device (d) + { + if (props.exists (LOG4CPLUS_TEXT ("CloseDevice"))) + close_flag = true; + else + close_flag = false; + } + + template + DeviceAppender (boost::shared_ptr const & d, + const helpers::Properties & props) + : Appender (props) + , device (d) + { + if (props.exists (LOG4CPLUS_TEXT ("CloseDevice"))) + close_flag = true; + else + close_flag = false; + } + + virtual + ~DeviceAppender () + { } + + virtual + void + close () + { + if (close_flag) + boost::iostreams::close (device_traits::unwrap (device)); + } + +protected: + virtual + void + append (log4cplus::spi::InternalLoggingEvent const & event) + { + tstring & str = formatEvent (event); + boost::iostreams::write (device_traits::unwrap (device), + str.c_str (), str.size ()); + } + + device_type device; + bool close_flag; + +private: + DeviceAppender (DeviceAppender const &); + DeviceAppender & operator = (DeviceAppender const &); +}; + + +template +inline +SharedAppenderPtr +make_device_appender (T & d, bool close_device = true) +{ + SharedAppenderPtr app (new DeviceAppender (d, close_device)); + return app; +} + + +template +inline +SharedAppenderPtr +make_device_appender (T & d, const helpers::Properties & props) +{ + SharedAppenderPtr app (new DeviceAppender (d, props)); + return app; +} + + +template +inline +SharedAppenderPtr +make_device_appender_sp (boost::shared_ptr const & p, + bool close_device = true) +{ + SharedAppenderPtr app ( + new DeviceAppender > (p, close_device)); + return app; +} + + +template +inline +SharedAppenderPtr +make_device_appender_sp (boost::shared_ptr const & p, + const helpers::Properties & props) +{ + SharedAppenderPtr app ( + new DeviceAppender > (p, props)); + return app; +} + + +} // namespace log4cplus + + +#endif // LOG4CPLUS_BOOST_DEVICEAPPENDER_HXX diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/clfsappender.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/clfsappender.h new file mode 100644 index 0000000..ca46b69 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/clfsappender.h @@ -0,0 +1,98 @@ +// -*- C++ -*- +// Module: Log4cplus +// File: clfsappender.h +// Created: 5/2012 +// Author: Vaclav Zeman +// +// +// Copyright (C) 2012-2013, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// + +/** @file */ + +#ifndef LOG4CPLUS_CLFSAPPENDER_H +#define LOG4CPLUS_CLFSAPPENDER_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + + +#if defined (LOG4CPLUS_CLFSAPPENDER_BUILD_DLL) +# if defined (INSIDE_LOG4CPLUS_CLFSAPPENDER) +# define LOG4CPLUS_CLFSAPPENDER_EXPORT __declspec(dllexport) +# else +# define LOG4CPLUS_CLFSAPPENDER_EXPORT __declspec(dllimport) +# endif +#else +# define LOG4CPLUS_CLFSAPPENDER_EXPORT +#endif + + +namespace log4cplus +{ + + +class LOG4CPLUS_CLFSAPPENDER_EXPORT CLFSAppender + : public Appender +{ +public: + CLFSAppender (tstring const & logname, unsigned long logsize, + unsigned long buffersize); + explicit CLFSAppender (helpers::Properties const &); + virtual ~CLFSAppender (); + + virtual void close (); + + static void registerAppender (); + +protected: + virtual void append (spi::InternalLoggingEvent const &); + + void init (tstring const & logname, unsigned long logsize, + unsigned long buffersize); + + struct Data; + + Data * data; + +private: + CLFSAppender (CLFSAppender const &); + CLFSAppender & operator = (CLFSAppender const &); +}; + + +typedef helpers::SharedObjectPtr CLFSAppenderPtr; + + +} // namespace log4cplus + + +#endif // LOG4CPLUS_CLFSAPPENDER_H diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/clogger.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/clogger.h new file mode 100644 index 0000000..a340d1b --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/clogger.h @@ -0,0 +1,85 @@ +// -*- C -*- +/** + * Module: Log4CPLUS + * File: clogger.h + * Created: 01/2011 + * Author: Jens Rehsack + * + * + * Copyright 2011-2013 Jens Rehsack & Tad E. Smith + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file + * This header defines the C API for log4cplus and the logging macros. */ + +#ifndef LOG4CPLUS_CLOGGERHEADER_ +#define LOG4CPLUS_CLOGGERHEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + + +#ifdef __cplusplus +extern "C" +{ +#endif + +// TODO UNICDE capable + +typedef void *logger_t; +typedef int loglevel_t; + +#define L4CP_OFF_LOG_LEVEL 60000 +#define L4CP_FATAL_LOG_LEVEL 50000 +#define L4CP_ERROR_LOG_LEVEL 40000 +#define L4CP_WARN_LOG_LEVEL 30000 +#define L4CP_INFO_LOG_LEVEL 20000 +#define L4CP_DEBUG_LOG_LEVEL 10000 +#define L4CP_TRACE_LOG_LEVEL 0 +#define L4CP_ALL_LOG_LEVEL TRACE_LOG_LEVEL +#define L4CP_NOT_SET_LOG_LEVEL -1 + +#ifdef UNICODE +# define LOG4CPLUS_TEXT2(STRING) L##STRING +typedef wchar_t log4cplus_char_t; +#else +# define LOG4CPLUS_TEXT2(STRING) STRING +typedef char log4cplus_char_t; +#endif // UNICODE +#define LOG4CPLUS_TEXT(STRING) LOG4CPLUS_TEXT2(STRING) + +LOG4CPLUS_EXPORT int log4cplus_file_configure(const log4cplus_char_t *pathname); +LOG4CPLUS_EXPORT int log4cplus_str_configure(const log4cplus_char_t *config); +LOG4CPLUS_EXPORT int log4cplus_basic_configure(void); +LOG4CPLUS_EXPORT void log4cplus_shutdown(void); + +LOG4CPLUS_EXPORT int log4cplus_logger_exists(const log4cplus_char_t *name); +LOG4CPLUS_EXPORT int log4cplus_logger_is_enabled_for( + const log4cplus_char_t *name, loglevel_t ll); +LOG4CPLUS_EXPORT int log4cplus_logger_log(const log4cplus_char_t *name, + loglevel_t ll, const log4cplus_char_t *msgfmt, ...) + LOG4CPLUS_FORMAT_ATTRIBUTE (__printf__, 3, 4); +LOG4CPLUS_EXPORT int log4cplus_logger_force_log(const log4cplus_char_t *name, + loglevel_t ll, const log4cplus_char_t *msgfmt, ...) + LOG4CPLUS_FORMAT_ATTRIBUTE (__printf__, 3, 4); + +#ifdef __cplusplus +} +#endif + +#endif /*?LOG4CPLUS_CLOGGERHEADER_*/ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config.h new file mode 100644 index 0000000..a7f3eb7 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config.h @@ -0,0 +1,498 @@ +/* include/log4cplus/config.h. Generated from config.h.in by configure. */ +/* include/log4cplus/config.h.in. Generated from configure.ac by autoheader. */ + +#ifndef LOG4CPLUS_CONFIG_H + +#define LOG4CPLUS_CONFIG_H + +/* Defined if the compiler supports C99 style variadic macros with + __VA_ARGS__. */ +/* #undef HAS_C99_VARIADIC_MACROS */ + +/* Defined if the compiler supports GNU style variadic macros. */ +/* #undef HAS_GNU_VARIADIC_MACROS */ + +/* Define to 1 if you have the `clock_gettime' function. */ +#define HAVE_CLOCK_GETTIME 1 + +/* Define to 1 if you have the `clock_nanosleep' function. */ +#define HAVE_CLOCK_NANOSLEEP 1 + +/* Defined if the compiler provides C++11 header and increment, + decrement operations. */ +/* #undef HAVE_CXX11_ATOMICS */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `fcntl' function. */ +#define HAVE_FCNTL 1 + +/* Define to 1 if you have the `flock' function. */ +#define HAVE_FLOCK 1 + +/* Define to 1 if you have the `ftime' function. */ +#define HAVE_FTIME 1 + +/* Define to 1 if the system has the `constructor' function attribute */ +#define HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR 1 + +/* */ +#define HAVE_GETADDRINFO 1 + +/* */ +#define HAVE_GETHOSTBYNAME_R 1 + +/* Define to 1 if you have the `getpid' function. */ +#define HAVE_GETPID 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `gmtime_r' function. */ +#define HAVE_GMTIME_R 1 + +/* Define to 1 if you have the `htonl' function. */ +#define HAVE_HTONL 1 + +/* Define to 1 if you have the `htons' function. */ +#define HAVE_HTONS 1 + +/* Define to 1 if you have the `iconv' function. */ +/* #undef HAVE_ICONV */ + +/* Define to 1 if you have the `iconv_close' function. */ +/* #undef HAVE_ICONV_CLOSE */ + +/* Define to 1 if you have the `iconv_open' function. */ +/* #undef HAVE_ICONV_OPEN */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `advapi32' library (-ladvapi32). */ +/* #undef HAVE_LIBADVAPI32 */ + +/* Define to 1 if you have the `libiconv' function. */ +/* #undef HAVE_LIBICONV */ + +/* Define to 1 if you have the `libiconv_close' function. */ +/* #undef HAVE_LIBICONV_CLOSE */ + +/* Define to 1 if you have the `libiconv_open' function. */ +/* #undef HAVE_LIBICONV_OPEN */ + +/* Define to 1 if you have the `kernel32' library (-lkernel32). */ +/* #undef HAVE_LIBKERNEL32 */ + +/* Define to 1 if you have the `ws2_32' library (-lws2_32). */ +/* #undef HAVE_LIBWS2_32 */ + +/* Define to 1 if you have the `localtime_r' function. */ +#define HAVE_LOCALTIME_R 1 + +/* Define to 1 if you have the `lockf' function. */ +#define HAVE_LOCKF 1 + +/* Define to 1 if you have the `lstat' function. */ +#define HAVE_LSTAT 1 + +/* Define to 1 if you have the `mbstowcs' function. */ +#define HAVE_MBSTOWCS 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `nanosleep' function. */ +#define HAVE_NANOSLEEP 1 + +/* Define to 1 if you have the `ntohl' function. */ +#define HAVE_NTOHL 1 + +/* Define to 1 if you have the `ntohs' function. */ +#define HAVE_NTOHS 1 + +/* Define to 1 if you have the `pipe' function. */ +#define HAVE_PIPE 1 + +/* Define to 1 if you have the `pipe2' function. */ +#define HAVE_PIPE2 1 + +/* Define to 1 if you have the `poll' function. */ +#define HAVE_POLL 1 + +/* Define if you have POSIX threads libraries and header files. */ +#define HAVE_PTHREAD 1 + +/* Have PTHREAD_PRIO_INHERIT. */ +#define HAVE_PTHREAD_PRIO_INHERIT 1 + +/* Define to 1 if you have the `shutdown' function. */ +#define HAVE_SHUTDOWN 1 + +/* Define to 1 if you have the `stat' function. */ +#define HAVE_STAT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Defined if the compiler understands __thread or __declspec(thread) + construct. */ +#define HAVE_TLS_SUPPORT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if the system has the `init_priority' variable attribute */ +#define HAVE_VAR_ATTRIBUTE_INIT_PRIORITY 1 + +/* Define to 1 if you have the `vfprintf_s' function. */ +/* #undef HAVE_VFPRINTF_S */ + +/* Define to 1 if you have the `vfwprintf_s' function. */ +/* #undef HAVE_VFWPRINTF_S */ + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the `vsnwprintf' function. */ +/* #undef HAVE_VSNWPRINTF */ + +/* Define to 1 if you have the `vsprintf_s' function. */ +/* #undef HAVE_VSPRINTF_S */ + +/* Define to 1 if you have the `vswprintf_s' function. */ +/* #undef HAVE_VSWPRINTF_S */ + +/* Define to 1 if you have the `wcstombs' function. */ +#define HAVE_WCSTOMBS 1 + +/* Define to 1 if you have the `_vsnprintf_s' function. */ +/* #undef HAVE__VSNPRINTF_S */ + +/* Define to 1 if you have the `_vsnwprintf' function. */ +/* #undef HAVE__VSNWPRINTF */ + +/* Define to 1 if you have the `_vsnwprintf_s' function. */ +/* #undef HAVE__VSNWPRINTF_S */ + +/* Defined if the compiler supports __FUNCTION__ macro. */ +/* #undef HAVE___FUNCTION___MACRO */ + +/* Defined if the compiler supports __func__ symbol. */ +/* #undef HAVE___FUNC___SYMBOL */ + +/* Defined if the compiler supports __PRETTY_FUNCTION__ macro. */ +/* #undef HAVE___PRETTY_FUNCTION___MACRO */ + +/* Defined if the compiler provides __sync_add_and_fetch(). */ +#define HAVE___SYNC_ADD_AND_FETCH 1 + +/* Defined if the compiler provides __sync_sub_and_fetch(). */ +#define HAVE___SYNC_SUB_AND_FETCH 1 + +/* Defined for --enable-debugging builds. */ +/* #undef LOG4CPLUS_DEBUGGING */ + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) or __global construct. */ +#define LOG4CPLUS_DECLSPEC_EXPORT __attribute__ ((visibility("default"))) + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) or __global construct. */ +#define LOG4CPLUS_DECLSPEC_IMPORT __attribute__ ((visibility("default"))) + +/* Defined if the compiler understands __attribute__((visibility("hidden"))) + or __hidden construct. */ +#define LOG4CPLUS_DECLSPEC_PRIVATE __attribute__ ((visibility("hidden"))) + +/* */ +#define LOG4CPLUS_HAVE_ARPA_INET_H 1 + +/* */ +#define LOG4CPLUS_HAVE_C99_VARIADIC_MACROS 1 + +/* */ +#define LOG4CPLUS_HAVE_CLOCK_GETTIME 1 + +/* */ +#define LOG4CPLUS_HAVE_CLOCK_NANOSLEEP 1 + +/* */ +/* #undef LOG4CPLUS_HAVE_CXX11_ATOMICS */ + +/* */ +#define LOG4CPLUS_HAVE_ENAMETOOLONG 1 + +/* */ +#define LOG4CPLUS_HAVE_ERRNO_H 1 + +/* */ +#define LOG4CPLUS_HAVE_FCNTL 1 + +/* */ +#define LOG4CPLUS_HAVE_FCNTL_H 1 + +/* */ +#define LOG4CPLUS_HAVE_FLOCK 1 + +/* */ +#define LOG4CPLUS_HAVE_FTIME 1 + +/* */ +#define LOG4CPLUS_HAVE_FUNCTION_MACRO 1 + +/* */ +#define LOG4CPLUS_HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR 1 + +/* */ +#define LOG4CPLUS_HAVE_FUNC_SYMBOL 1 + +/* */ +#define LOG4CPLUS_HAVE_GETADDRINFO 1 + +/* */ +#define LOG4CPLUS_HAVE_GETHOSTBYNAME_R 1 + +/* */ +#define LOG4CPLUS_HAVE_GETPID 1 + +/* */ +#define LOG4CPLUS_HAVE_GETTID 1 + +/* */ +#define LOG4CPLUS_HAVE_GETTIMEOFDAY 1 + +/* */ +#define LOG4CPLUS_HAVE_GMTIME_R 1 + +/* */ +#define LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS 1 + +/* */ +#define LOG4CPLUS_HAVE_HTONL 1 + +/* */ +#define LOG4CPLUS_HAVE_HTONS 1 + +/* */ +/* #undef LOG4CPLUS_HAVE_ICONV */ + +/* */ +/* #undef LOG4CPLUS_HAVE_ICONV_CLOSE */ + +/* */ +/* #undef LOG4CPLUS_HAVE_ICONV_H */ + +/* */ +/* #undef LOG4CPLUS_HAVE_ICONV_OPEN */ + +/* */ +#define LOG4CPLUS_HAVE_LIMITS_H 1 + +/* */ +#define LOG4CPLUS_HAVE_LOCALTIME_R 1 + +/* */ +#define LOG4CPLUS_HAVE_LOCKF 1 + +/* */ +#define LOG4CPLUS_HAVE_LSTAT 1 + +/* */ +#define LOG4CPLUS_HAVE_MBSTOWCS 1 + +/* */ +#define LOG4CPLUS_HAVE_NANOSLEEP 1 + +/* */ +#define LOG4CPLUS_HAVE_NETDB_H 1 + +/* */ +#define LOG4CPLUS_HAVE_NETINET_IN_H 1 + +/* */ +#define LOG4CPLUS_HAVE_NETINET_TCP_H 1 + +/* */ +#define LOG4CPLUS_HAVE_NTOHL 1 + +/* */ +#define LOG4CPLUS_HAVE_NTOHS 1 + +/* */ +#define LOG4CPLUS_HAVE_PIPE 1 + +/* */ +#define LOG4CPLUS_HAVE_PIPE2 1 + +/* */ +#define LOG4CPLUS_HAVE_POLL 1 + +/* */ +#define LOG4CPLUS_HAVE_POLL_H 1 + +/* */ +#define LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO 1 + +/* */ +#define LOG4CPLUS_HAVE_SHUTDOWN 1 + +/* */ +#define LOG4CPLUS_HAVE_STAT 1 + +/* */ +#define LOG4CPLUS_HAVE_STDARG_H 1 + +/* */ +#define LOG4CPLUS_HAVE_STDIO_H 1 + +/* */ +#define LOG4CPLUS_HAVE_STDLIB_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYSLOG_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_FILE_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_SOCKET_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_STAT_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_SYSCALL_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_TIMEB_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_TIME_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_TYPES_H 1 + +/* */ +#define LOG4CPLUS_HAVE_TIME_H 1 + +/* */ +#define LOG4CPLUS_HAVE_TLS_SUPPORT 1 + +/* */ +#define LOG4CPLUS_HAVE_UNISTD_H 1 + +/* */ +#define LOG4CPLUS_HAVE_VAR_ATTRIBUTE_INIT_PRIORITY 1 + +/* */ +/* #undef LOG4CPLUS_HAVE_VFPRINTF_S */ + +/* */ +/* #undef LOG4CPLUS_HAVE_VFWPRINTF_S */ + +/* */ +#define LOG4CPLUS_HAVE_VSNPRINTF 1 + +/* */ +/* #undef LOG4CPLUS_HAVE_VSNWPRINTF */ + +/* */ +/* #undef LOG4CPLUS_HAVE_VSPRINTF_S */ + +/* */ +/* #undef LOG4CPLUS_HAVE_VSWPRINTF_S */ + +/* */ +#define LOG4CPLUS_HAVE_WCHAR_H 1 + +/* */ +#define LOG4CPLUS_HAVE_WCSTOMBS 1 + +/* */ +/* #undef LOG4CPLUS_HAVE__VSNPRINTF_S */ + +/* */ +/* #undef LOG4CPLUS_HAVE__VSNWPRINTF */ + +/* */ +/* #undef LOG4CPLUS_HAVE__VSNWPRINTF_S */ + +/* */ +#define LOG4CPLUS_HAVE___SYNC_ADD_AND_FETCH 1 + +/* */ +#define LOG4CPLUS_HAVE___SYNC_SUB_AND_FETCH 1 + +/* Define if this is a single-threaded library. */ +/* #undef LOG4CPLUS_SINGLE_THREADED */ + +/* */ +#define LOG4CPLUS_THREAD_LOCAL_VAR __thread + +/* */ +/* #undef LOG4CPLUS_USE_PTHREADS */ + +/* Define when iconv() is available. */ +/* #undef LOG4CPLUS_WITH_ICONV */ + +/* Define for C99 compilers/standard libraries that support more than just the + "C" locale. */ +/* #undef LOG4CPLUS_WORKING_C_LOCALE */ + +/* Define for compilers/standard libraries that support more than just the "C" + locale. */ +/* #undef LOG4CPLUS_WORKING_LOCALE */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "log4cplus" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "log4cplus 1.1.3" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "log4cplus" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.1.3" + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +/* #undef PTHREAD_CREATE_JOINABLE */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Defined to the actual TLS support construct. */ +#define TLS_SUPPORT_CONSTRUCT __thread + +/* Substitute for socklen_t */ +/* #undef socklen_t */ + +#endif // LOG4CPLUS_CONFIG_H diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config.h.cmake.in b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config.h.cmake.in new file mode 100644 index 0000000..3ba79af --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config.h.cmake.in @@ -0,0 +1,347 @@ +/* include/log4cplus/config.h.in. Generated from configure.in by autoheader. */ + +#ifndef LOG4CPLUS_CONFIG_H + +#define LOG4CPLUS_CONFIG_H + +/* Defined if the compiler supports C99 style variadic macros with + __VA_ARGS__. */ +/* #undef HAS_C99_VARIADIC_MACROS */ + +/* Defined if the compiler supports GNU style variadic macros. */ +/* #undef HAS_GNU_VARIADIC_MACROS */ + +/* Define to 1 if you have the `clock_gettime' function. */ +#undef HAVE_CLOCK_GETTIME + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_DLFCN_H 1 + +/* Define to 1 if you have the `ftime' function. */ +#cmakedefine HAVE_FTIME 1 + +/* */ +#cmakedefine HAVE_GETADDRINFO 1 + +/* */ +#cmakedefine HAVE_GETHOSTBYNAME_R 1 + +/* Define to 1 if you have the `getpid' function. */ +#cmakedefine HAVE_GETPID 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#cmakedefine HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `gmtime_r' function. */ +#cmakedefine HAVE_GMTIME_R 1 + +/* Define to 1 if you have the `htonl' function. */ +#cmakedefine HAVE_HTONL 1 + +/* Define to 1 if you have the `htons' function. */ +#cmakedefine HAVE_HTONS 1 + +/* Define to 1 if you have the `iconv' function. */ +#cmakedefine HAVE_ICONV 1 + +/* Define to 1 if you have the `iconv_close' function. */ +#cmakedefine HAVE_ICONV_CLOSE 1 + +/* Define to 1 if you have the `iconv_open' function. */ +#cmakedefine HAVE_ICONV_OPEN 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `advapi32' library (-ladvapi32). */ +#cmakedefine HAVE_LIBADVAPI32 1 + +/* Define to 1 if you have the `libiconv' function. */ +/* #undef HAVE_LIBICONV */ + +/* Define to 1 if you have the `libiconv_close' function. */ +/* #undef HAVE_LIBICONV_CLOSE */ + +/* Define to 1 if you have the `libiconv_open' function. */ +/* #undef HAVE_LIBICONV_OPEN */ + +/* Define to 1 if you have the `kernel32' library (-lkernel32). */ +#cmakedefine HAVE_LIBKERNEL32 1 + +/* Define to 1 if you have the `nsl' library (-lnsl). */ +#cmakedefine HAVE_LIBNSL 1 + +/* Define to 1 if you have the `rt' library (-lrt). */ +#cmakedefine HAVE_LIBRT 1 + +/* Define to 1 if you have the `socket' library (-lsocket). */ +#cmakedefine HAVE_LIBSOCKET 1 + +/* Define to 1 if you have the `ws2_32' library (-lws2_32). */ +#cmakedefine HAVE_LIBWS2_32 1 + +/* Define to 1 if you have the `localtime_r' function. */ +#cmakedefine HAVE_LOCALTIME_R 1 + +/* Define to 1 if you have the `lstat' function. */ +#cmakedefine HAVE_LSTAT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `ntohl' function. */ +#cmakedefine HAVE_NTOHL 1 + +/* Define to 1 if you have the `ntohs' function. */ +#cmakedefine HAVE_NTOHS 1 + +/* Define if you have POSIX threads libraries and header files. */ +#undef HAVE_PTHREAD + +/* Define to 1 if you have the `stat' function. */ +#cmakedefine HAVE_STAT 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `vfprintf_s' function. */ +#cmakedefine HAVE_VFPRINTF_S 1 + +/* Define to 1 if you have the `vfwprintf_s' function. */ +#cmakedefine HAVE_VFWPRINTF_S 1 + +/* Define to 1 if you have the `vsnprintf' function. */ +#cmakedefine HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the `vsprintf_s' function. */ +#cmakedefine HAVE_VSPRINTF_S 1 + +/* Define to 1 if you have the `vswprintf_s' function. */ +#cmakedefine HAVE_VSWPRINTF_S 1 + +/* Define to 1 if you have the `_vsnprintf' function. */ +#cmakedefine HAVE__VSNPRINTF 1 + +/* Define to 1 if you have the `_vsnprintf_s' function. */ +#cmakedefine HAVE__VSNPRINTF_S 1 + +/* Define to 1 if you have the `_vsnwprintf_s' function. */ +#cmakedefine HAVE__VSNWPRINTF_S 1 + +/* Defined if the compiler supports __FUNCTION__ macro. */ +#cmakedefine HAVE___FUNCTION___MACRO 1 + +/* Defined if the compiler supports __PRETTY_FUNCTION__ macro. */ +#cmakedefine HAVE___PRETTY_FUNCTION___MACRO 1 + +/* Defined if the compiler provides __sync_add_and_fetch(). */ +#cmakedefine HAVE___SYNC_ADD_AND_FETCH 1 + +/* Defined if the compiler provides __sync_sub_and_fetch(). */ +#cmakedefine HAVE___SYNC_SUB_AND_FETCH 1 + +/* Defined for --enable-debugging builds. */ +#undef LOG4CPLUS_DEBUGGING + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) construct. */ +#define LOG4CPLUS_DECLSPEC_EXPORT @LOG4CPLUS_DECLSPEC_EXPORT@ + +/* Defined if the compiler understands __declspec(dllexport) or construct. */ +#define LOG4CPLUS_DECLSPEC_IMPORT @LOG4CPLUS_DECLSPEC_IMPORT@ /**/ + +/* */ +#cmakedefine LOG4CPLUS_HAVE_C99_VARIADIC_MACROS 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_CLOCK_GETTIME 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_ENAMETOOLONG 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_ERRNO_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_FTIME 1 + +/* */ +#define LOG4CPLUS_HAVE_FUNCTION_MACRO 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GETADDRINFO 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GETHOSTBYNAME_R 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GETPID 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GETTID 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GETTIMEOFDAY 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GMTIME_R 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_HTONL 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_HTONS 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_ICONV 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_ICONV_CLOSE 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_ICONV_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_ICONV_OPEN 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_LIMITS_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_LOCALTIME_R 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_LSTAT 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_NETDB_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_NETINET_IN_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_NETINET_TCP_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_NTOHL 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_NTOHS 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_STAT 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_STDARG_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_STDIO_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_STDLIB_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYSLOG_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYS_SOCKET_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYS_STAT_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYS_SYSCALL_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYS_TIMEB_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYS_TIME_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_SYS_TYPES_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_TIME_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_UNISTD_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_VFPRINTF_S 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_VFWPRINTF_S 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_VSNPRINTF 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_VSPRINTF_S 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_VSWPRINTF_S 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE_WCHAR_H 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE__VSNPRINTF 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE__VSNPRINTF_S 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE__VSNWPRINTF_S 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE___SYNC_ADD_AND_FETCH 1 + +/* */ +#cmakedefine LOG4CPLUS_HAVE___SYNC_SUB_AND_FETCH 1 + +/* Define if this is a single-threaded library. */ +#undef LOG4CPLUS_SINGLE_THREADED + +/* */ +#undef LOG4CPLUS_USE_PTHREADS + +/* Define for compilers/standard libraries that support more than just the "C" + locale. */ +#undef LOG4CPLUS_WORKING_LOCALE + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +#undef PTHREAD_CREATE_JOINABLE + +/* Define to 1 if you have the ANSI C header files. Seems to be unused*/ +#cmakedefine STDC_HEADERS 1 + +/* Define to int if undefined. */ +#cmakedefine socklen_t int + +#endif // LOG4CPLUS_CONFIG_H diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config.h.in b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config.h.in new file mode 100644 index 0000000..1f2ef95 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config.h.in @@ -0,0 +1,497 @@ +/* include/log4cplus/config.h.in. Generated from configure.ac by autoheader. */ + +#ifndef LOG4CPLUS_CONFIG_H + +#define LOG4CPLUS_CONFIG_H + +/* Defined if the compiler supports C99 style variadic macros with + __VA_ARGS__. */ +#undef HAS_C99_VARIADIC_MACROS + +/* Defined if the compiler supports GNU style variadic macros. */ +#undef HAS_GNU_VARIADIC_MACROS + +/* Define to 1 if you have the `clock_gettime' function. */ +#undef HAVE_CLOCK_GETTIME + +/* Define to 1 if you have the `clock_nanosleep' function. */ +#undef HAVE_CLOCK_NANOSLEEP + +/* Defined if the compiler provides C++11 header and increment, + decrement operations. */ +#undef HAVE_CXX11_ATOMICS + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the `fcntl' function. */ +#undef HAVE_FCNTL + +/* Define to 1 if you have the `flock' function. */ +#undef HAVE_FLOCK + +/* Define to 1 if you have the `ftime' function. */ +#undef HAVE_FTIME + +/* Define to 1 if the system has the `constructor' function attribute */ +#undef HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR + +/* */ +#undef HAVE_GETADDRINFO + +/* */ +#undef HAVE_GETHOSTBYNAME_R + +/* Define to 1 if you have the `getpid' function. */ +#undef HAVE_GETPID + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the `gmtime_r' function. */ +#undef HAVE_GMTIME_R + +/* Define to 1 if you have the `htonl' function. */ +#undef HAVE_HTONL + +/* Define to 1 if you have the `htons' function. */ +#undef HAVE_HTONS + +/* Define to 1 if you have the `iconv' function. */ +#undef HAVE_ICONV + +/* Define to 1 if you have the `iconv_close' function. */ +#undef HAVE_ICONV_CLOSE + +/* Define to 1 if you have the `iconv_open' function. */ +#undef HAVE_ICONV_OPEN + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `advapi32' library (-ladvapi32). */ +#undef HAVE_LIBADVAPI32 + +/* Define to 1 if you have the `libiconv' function. */ +#undef HAVE_LIBICONV + +/* Define to 1 if you have the `libiconv_close' function. */ +#undef HAVE_LIBICONV_CLOSE + +/* Define to 1 if you have the `libiconv_open' function. */ +#undef HAVE_LIBICONV_OPEN + +/* Define to 1 if you have the `kernel32' library (-lkernel32). */ +#undef HAVE_LIBKERNEL32 + +/* Define to 1 if you have the `ws2_32' library (-lws2_32). */ +#undef HAVE_LIBWS2_32 + +/* Define to 1 if you have the `localtime_r' function. */ +#undef HAVE_LOCALTIME_R + +/* Define to 1 if you have the `lockf' function. */ +#undef HAVE_LOCKF + +/* Define to 1 if you have the `lstat' function. */ +#undef HAVE_LSTAT + +/* Define to 1 if you have the `mbstowcs' function. */ +#undef HAVE_MBSTOWCS + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `nanosleep' function. */ +#undef HAVE_NANOSLEEP + +/* Define to 1 if you have the `ntohl' function. */ +#undef HAVE_NTOHL + +/* Define to 1 if you have the `ntohs' function. */ +#undef HAVE_NTOHS + +/* Define to 1 if you have the `pipe' function. */ +#undef HAVE_PIPE + +/* Define to 1 if you have the `pipe2' function. */ +#undef HAVE_PIPE2 + +/* Define to 1 if you have the `poll' function. */ +#undef HAVE_POLL + +/* Define if you have POSIX threads libraries and header files. */ +#undef HAVE_PTHREAD + +/* Have PTHREAD_PRIO_INHERIT. */ +#undef HAVE_PTHREAD_PRIO_INHERIT + +/* Define to 1 if you have the `shutdown' function. */ +#undef HAVE_SHUTDOWN + +/* Define to 1 if you have the `stat' function. */ +#undef HAVE_STAT + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Defined if the compiler understands __thread or __declspec(thread) + construct. */ +#undef HAVE_TLS_SUPPORT + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if the system has the `init_priority' variable attribute */ +#undef HAVE_VAR_ATTRIBUTE_INIT_PRIORITY + +/* Define to 1 if you have the `vfprintf_s' function. */ +#undef HAVE_VFPRINTF_S + +/* Define to 1 if you have the `vfwprintf_s' function. */ +#undef HAVE_VFWPRINTF_S + +/* Define to 1 if you have the `vsnprintf' function. */ +#undef HAVE_VSNPRINTF + +/* Define to 1 if you have the `vsnwprintf' function. */ +#undef HAVE_VSNWPRINTF + +/* Define to 1 if you have the `vsprintf_s' function. */ +#undef HAVE_VSPRINTF_S + +/* Define to 1 if you have the `vswprintf_s' function. */ +#undef HAVE_VSWPRINTF_S + +/* Define to 1 if you have the `wcstombs' function. */ +#undef HAVE_WCSTOMBS + +/* Define to 1 if you have the `_vsnprintf_s' function. */ +#undef HAVE__VSNPRINTF_S + +/* Define to 1 if you have the `_vsnwprintf' function. */ +#undef HAVE__VSNWPRINTF + +/* Define to 1 if you have the `_vsnwprintf_s' function. */ +#undef HAVE__VSNWPRINTF_S + +/* Defined if the compiler supports __FUNCTION__ macro. */ +#undef HAVE___FUNCTION___MACRO + +/* Defined if the compiler supports __func__ symbol. */ +#undef HAVE___FUNC___SYMBOL + +/* Defined if the compiler supports __PRETTY_FUNCTION__ macro. */ +#undef HAVE___PRETTY_FUNCTION___MACRO + +/* Defined if the compiler provides __sync_add_and_fetch(). */ +#undef HAVE___SYNC_ADD_AND_FETCH + +/* Defined if the compiler provides __sync_sub_and_fetch(). */ +#undef HAVE___SYNC_SUB_AND_FETCH + +/* Defined for --enable-debugging builds. */ +#undef LOG4CPLUS_DEBUGGING + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) or __global construct. */ +#undef LOG4CPLUS_DECLSPEC_EXPORT + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) or __global construct. */ +#undef LOG4CPLUS_DECLSPEC_IMPORT + +/* Defined if the compiler understands __attribute__((visibility("hidden"))) + or __hidden construct. */ +#undef LOG4CPLUS_DECLSPEC_PRIVATE + +/* */ +#undef LOG4CPLUS_HAVE_ARPA_INET_H + +/* */ +#undef LOG4CPLUS_HAVE_C99_VARIADIC_MACROS + +/* */ +#undef LOG4CPLUS_HAVE_CLOCK_GETTIME + +/* */ +#undef LOG4CPLUS_HAVE_CLOCK_NANOSLEEP + +/* */ +#undef LOG4CPLUS_HAVE_CXX11_ATOMICS + +/* */ +#undef LOG4CPLUS_HAVE_ENAMETOOLONG + +/* */ +#undef LOG4CPLUS_HAVE_ERRNO_H + +/* */ +#undef LOG4CPLUS_HAVE_FCNTL + +/* */ +#undef LOG4CPLUS_HAVE_FCNTL_H + +/* */ +#undef LOG4CPLUS_HAVE_FLOCK + +/* */ +#undef LOG4CPLUS_HAVE_FTIME + +/* */ +#undef LOG4CPLUS_HAVE_FUNCTION_MACRO + +/* */ +#undef LOG4CPLUS_HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR + +/* */ +#undef LOG4CPLUS_HAVE_FUNC_SYMBOL + +/* */ +#undef LOG4CPLUS_HAVE_GETADDRINFO + +/* */ +#undef LOG4CPLUS_HAVE_GETHOSTBYNAME_R + +/* */ +#undef LOG4CPLUS_HAVE_GETPID + +/* */ +#undef LOG4CPLUS_HAVE_GETTID + +/* */ +#undef LOG4CPLUS_HAVE_GETTIMEOFDAY + +/* */ +#undef LOG4CPLUS_HAVE_GMTIME_R + +/* */ +#undef LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS + +/* */ +#undef LOG4CPLUS_HAVE_HTONL + +/* */ +#undef LOG4CPLUS_HAVE_HTONS + +/* */ +#undef LOG4CPLUS_HAVE_ICONV + +/* */ +#undef LOG4CPLUS_HAVE_ICONV_CLOSE + +/* */ +#undef LOG4CPLUS_HAVE_ICONV_H + +/* */ +#undef LOG4CPLUS_HAVE_ICONV_OPEN + +/* */ +#undef LOG4CPLUS_HAVE_LIMITS_H + +/* */ +#undef LOG4CPLUS_HAVE_LOCALTIME_R + +/* */ +#undef LOG4CPLUS_HAVE_LOCKF + +/* */ +#undef LOG4CPLUS_HAVE_LSTAT + +/* */ +#undef LOG4CPLUS_HAVE_MBSTOWCS + +/* */ +#undef LOG4CPLUS_HAVE_NANOSLEEP + +/* */ +#undef LOG4CPLUS_HAVE_NETDB_H + +/* */ +#undef LOG4CPLUS_HAVE_NETINET_IN_H + +/* */ +#undef LOG4CPLUS_HAVE_NETINET_TCP_H + +/* */ +#undef LOG4CPLUS_HAVE_NTOHL + +/* */ +#undef LOG4CPLUS_HAVE_NTOHS + +/* */ +#undef LOG4CPLUS_HAVE_PIPE + +/* */ +#undef LOG4CPLUS_HAVE_PIPE2 + +/* */ +#undef LOG4CPLUS_HAVE_POLL + +/* */ +#undef LOG4CPLUS_HAVE_POLL_H + +/* */ +#undef LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO + +/* */ +#undef LOG4CPLUS_HAVE_SHUTDOWN + +/* */ +#undef LOG4CPLUS_HAVE_STAT + +/* */ +#undef LOG4CPLUS_HAVE_STDARG_H + +/* */ +#undef LOG4CPLUS_HAVE_STDIO_H + +/* */ +#undef LOG4CPLUS_HAVE_STDLIB_H + +/* */ +#undef LOG4CPLUS_HAVE_SYSLOG_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_FILE_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_SOCKET_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_STAT_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_SYSCALL_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TIMEB_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TIME_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TYPES_H + +/* */ +#undef LOG4CPLUS_HAVE_TIME_H + +/* */ +#undef LOG4CPLUS_HAVE_TLS_SUPPORT + +/* */ +#undef LOG4CPLUS_HAVE_UNISTD_H + +/* */ +#undef LOG4CPLUS_HAVE_VAR_ATTRIBUTE_INIT_PRIORITY + +/* */ +#undef LOG4CPLUS_HAVE_VFPRINTF_S + +/* */ +#undef LOG4CPLUS_HAVE_VFWPRINTF_S + +/* */ +#undef LOG4CPLUS_HAVE_VSNPRINTF + +/* */ +#undef LOG4CPLUS_HAVE_VSNWPRINTF + +/* */ +#undef LOG4CPLUS_HAVE_VSPRINTF_S + +/* */ +#undef LOG4CPLUS_HAVE_VSWPRINTF_S + +/* */ +#undef LOG4CPLUS_HAVE_WCHAR_H + +/* */ +#undef LOG4CPLUS_HAVE_WCSTOMBS + +/* */ +#undef LOG4CPLUS_HAVE__VSNPRINTF_S + +/* */ +#undef LOG4CPLUS_HAVE__VSNWPRINTF + +/* */ +#undef LOG4CPLUS_HAVE__VSNWPRINTF_S + +/* */ +#undef LOG4CPLUS_HAVE___SYNC_ADD_AND_FETCH + +/* */ +#undef LOG4CPLUS_HAVE___SYNC_SUB_AND_FETCH + +/* Define if this is a single-threaded library. */ +#undef LOG4CPLUS_SINGLE_THREADED + +/* */ +#undef LOG4CPLUS_THREAD_LOCAL_VAR + +/* */ +#undef LOG4CPLUS_USE_PTHREADS + +/* Define when iconv() is available. */ +#undef LOG4CPLUS_WITH_ICONV + +/* Define for C99 compilers/standard libraries that support more than just the + "C" locale. */ +#undef LOG4CPLUS_WORKING_C_LOCALE + +/* Define for compilers/standard libraries that support more than just the "C" + locale. */ +#undef LOG4CPLUS_WORKING_LOCALE + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to necessary symbol if this constant uses a non-standard name on + your system. */ +#undef PTHREAD_CREATE_JOINABLE + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Defined to the actual TLS support construct. */ +#undef TLS_SUPPORT_CONSTRUCT + +/* Substitute for socklen_t */ +#undef socklen_t + +#endif // LOG4CPLUS_CONFIG_H diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config.hxx b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config.hxx new file mode 100644 index 0000000..608e762 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config.hxx @@ -0,0 +1,182 @@ +// Copyright (C) 2009-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_CONFIG_HXX +#define LOG4CPLUS_CONFIG_HXX + +#if defined (_WIN32) +# include +#elif (defined(__MWERKS__) && defined(__MACOS__)) +# include +#else +# include +#endif + +#if ! defined (UNICODE) && ! defined (LOG4CPLUS_HAVE_VSNPRINTF_S) \ + && ! defined (LOG4CPLUS_HAVE__VSNPRINTF_S) \ + && ! defined (LOG4CPLUS_HAVE_VSNPRINTF) \ + && ! defined (LOG4CPLUS_HAVE__VSNPRINTF) +# undef LOG4CPLUS_USE_POOR_MANS_SNPRINTF +# define LOG4CPLUS_USE_POOR_MANS_SNPRINTF +#endif + +# if ! defined (LOG4CPLUS_WORKING_LOCALE) \ + && ! defined (LOG4CPLUS_WORKING_C_LOCALE) \ + && ! defined (LOG4CPLUS_WITH_ICONV) +# define LOG4CPLUS_POOR_MANS_CHCONV +#endif + +#ifndef LOG4CPLUS_DECLSPEC_EXPORT +#define LOG4CPLUS_DECLSPEC_EXPORT /* empty */ +#endif + +#ifndef LOG4CPLUS_DECLSPEC_IMPORT +#define LOG4CPLUS_DECLSPEC_IMPORT /* empty */ +#endif + +#ifndef LOG4CPLUS_DECLSPEC_PRIVATE +#define LOG4CPLUS_DECLSPEC_PRIVATE /* empty */ +#endif + +#define LOG4CPLUS_PRIVATE LOG4CPLUS_DECLSPEC_PRIVATE + +#if !defined(_WIN32) +# define LOG4CPLUS_USE_BSD_SOCKETS +# if !defined(LOG4CPLUS_SINGLE_THREADED) +# define LOG4CPLUS_USE_PTHREADS +# endif +# if defined (INSIDE_LOG4CPLUS) +# define LOG4CPLUS_EXPORT LOG4CPLUS_DECLSPEC_EXPORT +# else +# define LOG4CPLUS_EXPORT LOG4CPLUS_DECLSPEC_IMPORT +# endif // defined (INSIDE_LOG4CPLUS) + +#endif // !_WIN32 + +#if defined (LOG4CPLUS_INLINES_ARE_EXPORTED) \ + && defined (LOG4CPLUS_BUILD_DLL) +# define LOG4CPLUS_INLINE_EXPORT inline +#else +# define LOG4CPLUS_INLINE_EXPORT +#endif + +#if defined (UNICODE) +# if defined (_MSC_VER) && _MSC_VER >= 1400 +# define LOG4CPLUS_FSTREAM_ACCEPTS_WCHAR_T +# endif +# if defined (_MSC_VER) && _MSC_VER >= 1600 +# define LOG4CPLUS_HAVE_CODECVT_UTF8_FACET +# define LOG4CPLUS_HAVE_CODECVT_UTF16_FACET +# endif +#endif + +// C++11 stuff + +#if ! defined (__has_feature) +//! __has_feature(X) is Clangs way for testing features. +//! Define it to 0 if it does not exist. +# define __has_feature(X) 0 +#endif + +#if (defined (_MSC_VER) && _MSC_VER >= 1600) \ + || defined (__GXX_EXPERIMENTAL_CXX0X__) \ + || __cplusplus >= 201103L +# define LOG4CPLUS_HAVE_CXX11_SUPPORT +#endif + +#if defined (LOG4CPLUS_HAVE_CXX11_SUPPORT) \ + || __has_feature (cxx_rvalue_references) +# define LOG4CPLUS_HAVE_RVALUE_REFS +#endif + +#if ! defined (UNICODE) && defined (__GNUC__) && __GNUC__ >= 3 +# define LOG4CPLUS_FORMAT_ATTRIBUTE(archetype, format_index, first_arg_index) \ + __attribute__ ((format (archetype, format_index, first_arg_index))) +#else +# define LOG4CPLUS_FORMAT_ATTRIBUTE(archetype, fmt_index, first_arg_index) \ + /* empty */ +#endif + +#if defined (__GNUC__) && __GNUC__ >= 3 +# define LOG4CPLUS_ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) +# define LOG4CPLUS_ATTRIBUTE_PURE __attribute__ ((__pure__)) +# define LOG4CPLUS_BUILTIN_EXPECT(exp, c) __builtin_expect ((exp), (c)) +#else +# if ! defined (LOG4CPLUS_ATTRIBUTE_NORETURN) +# define LOG4CPLUS_ATTRIBUTE_NORETURN /* empty */ +# endif +# define LOG4CPLUS_ATTRIBUTE_PURE /* empty */ +# define LOG4CPLUS_BUILTIN_EXPECT(exp, c) (exp) +#endif + +#define LOG4CPLUS_LIKELY(cond) LOG4CPLUS_BUILTIN_EXPECT(!! (cond), 1) +#define LOG4CPLUS_UNLIKELY(cond) LOG4CPLUS_BUILTIN_EXPECT(!! (cond), 0) + +#if defined (_MSC_VER) \ + || (defined (__BORLANDC__) && __BORLANDC__ >= 0x0650) \ + || (defined (__COMO__) && __COMO_VERSION__ >= 400) /* ??? */ \ + || (defined (__DMC__) && __DMC__ >= 0x700) /* ??? */ \ + || (defined (__clang__) && __clang_major__ >= 3) \ + || (defined (__GNUC__) && (__GNUC__ >= 4 \ + || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))) +# define LOG4CPLUS_HAVE_PRAGMA_ONCE +# pragma once +#endif + +#if defined (LOG4CPLUS_HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR) +# define LOG4CPLUS_CONSTRUCTOR_FUNC(prio) \ + __attribute__ ((__constructor__ ((prio)))) +#else +# define LOG4CPLUS_CONSTRUCTOR_FUNC(prio) /* empty */ +#endif + +#if defined (LOG4CPLUS_HAVE_VAR_ATTRIBUTE_INIT_PRIORITY) +# define LOG4CPLUS_INIT_PRIORITY(prio) \ + __attribute__ ((__init_priority__ ((prio)))) +#else +# define LOG4CPLUS_INIT_PRIORITY(prio) /* empty */ +#endif + +#define LOG4CPLUS_INIT_PRIORITY_BASE (65535 / 2) + +#include + +#if defined(__cplusplus) +namespace log4cplus +{ + +//! Per thread cleanup function. Users should call this function before +//! a thread ends its execution. It frees resources allocated in thread local +//! storage. It is important only for multi-threaded static library builds +//! of log4cplus and user threads. In all other cases the clean up is provided +//! automatically by other means. +LOG4CPLUS_EXPORT void threadCleanup (); + +//! Initializes log4cplus. +LOG4CPLUS_EXPORT void initialize (); + +} // namespace log4cplus + +#endif + +#endif // LOG4CPLUS_CONFIG_HXX diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config/defines.hxx b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config/defines.hxx new file mode 100644 index 0000000..b950678 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config/defines.hxx @@ -0,0 +1,266 @@ +/* include/log4cplus/config/defines.hxx. Generated from defines.hxx.in by configure. */ +#ifndef LOG4CPLUS_CONFIG_DEFINES_HXX +#define LOG4CPLUS_CONFIG_DEFINES_HXX + +/* */ +#define LOG4CPLUS_HAVE_SYSLOG_H 1 + +/* */ +#define LOG4CPLUS_HAVE_ARPA_INET_H 1 + +/* */ +#define LOG4CPLUS_HAVE_NETINET_IN_H 1 + +/* */ +#define LOG4CPLUS_HAVE_NETINET_TCP_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_TIMEB_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_TIME_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_TYPES_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_STAT_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_SYSCALL_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_FILE_H 1 + +/* */ +#define LOG4CPLUS_HAVE_TIME_H 1 + +/* */ +#define LOG4CPLUS_HAVE_SYS_SOCKET_H 1 + +/* */ +#define LOG4CPLUS_HAVE_NETDB_H 1 + +/* */ +#define LOG4CPLUS_HAVE_UNISTD_H 1 + +/* */ +#define LOG4CPLUS_HAVE_FCNTL_H 1 + +/* */ +#define LOG4CPLUS_HAVE_STDARG_H 1 + +/* */ +#define LOG4CPLUS_HAVE_STDIO_H 1 + +/* */ +#define LOG4CPLUS_HAVE_STDLIB_H 1 + +/* */ +#define LOG4CPLUS_HAVE_ERRNO_H 1 + +/* */ +#define LOG4CPLUS_HAVE_WCHAR_H 1 + +/* */ +/* #undef LOG4CPLUS_HAVE_ICONV_H */ + +/* */ +#define LOG4CPLUS_HAVE_LIMITS_H 1 + +/* */ +#define LOG4CPLUS_HAVE_FTIME 1 + +/* */ +#define LOG4CPLUS_HAVE_GETADDRINFO 1 + +/* */ +#define LOG4CPLUS_HAVE_GETHOSTBYNAME_R 1 + +/* */ +#define LOG4CPLUS_HAVE_GETPID 1 + +/* */ +#define LOG4CPLUS_HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `clock_gettime' function. */ +#define LOG4CPLUS_HAVE_CLOCK_GETTIME 1 + +/* Define to 1 if you have the `nanosleep' function. */ +#define LOG4CPLUS_HAVE_NANOSLEEP 1 + +/* Define to 1 if you have the `clock_nanosleep' function. */ +#define LOG4CPLUS_HAVE_CLOCK_NANOSLEEP 1 + +/* */ +#define LOG4CPLUS_HAVE_GMTIME_R 1 + +/* */ +#define LOG4CPLUS_HAVE_HTONL 1 + +/* */ +#define LOG4CPLUS_HAVE_HTONS 1 + +/* */ +#define LOG4CPLUS_HAVE_LOCALTIME_R 1 + +/* */ +#define LOG4CPLUS_HAVE_LSTAT 1 + +/* */ +#define LOG4CPLUS_HAVE_FCNTL 1 + +/* */ +#define LOG4CPLUS_HAVE_LOCKF 1 + +/* */ +#define LOG4CPLUS_HAVE_FLOCK 1 + +/* */ +#define LOG4CPLUS_HAVE_NTOHL 1 + +/* */ +#define LOG4CPLUS_HAVE_NTOHS 1 + +/* Define to 1 if you have the `shutdown' function. */ +#define LOG4CPLUS_HAVE_SHUTDOWN 1 + +/* */ +#define LOG4CPLUS_HAVE_PIPE 1 + +/* */ +#define LOG4CPLUS_HAVE_PIPE2 1 + +/* */ +#define LOG4CPLUS_HAVE_POLL 1 + +/* */ +#define LOG4CPLUS_HAVE_POLL_H 1 + +/* */ +#define LOG4CPLUS_HAVE_STAT 1 + +/* Define if this is a single-threaded library. */ +/* #undef LOG4CPLUS_SINGLE_THREADED */ + +/* */ +/* #undef LOG4CPLUS_USE_PTHREADS */ + +/* Define for compilers/standard libraries that support more than just the "C" + locale. */ +/* #undef LOG4CPLUS_WORKING_LOCALE */ + +/* Define for C99 compilers/standard libraries that support more than just the + "C" locale. */ +/* #undef LOG4CPLUS_WORKING_C_LOCALE */ + +/* Define to int if undefined. */ +/* #undef socklen_t */ + +/* Defined for --enable-debugging builds. */ +/* #undef LOG4CPLUS_DEBUGGING */ + +/* Defined if the compiler understands __declspec(dllexport) or + __attribute__((visibility("default"))) construct. */ +#define LOG4CPLUS_DECLSPEC_EXPORT __attribute__ ((visibility("default"))) + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) construct. */ +#define LOG4CPLUS_DECLSPEC_IMPORT __attribute__ ((visibility("default"))) + +/* Defined if the compiler understands + __attribute__((visibility("hidden"))) construct. */ +#define LOG4CPLUS_DECLSPEC_PRIVATE __attribute__ ((visibility("hidden"))) + +/* */ +#define LOG4CPLUS_HAVE_TLS_SUPPORT 1 + +/* */ +#define LOG4CPLUS_THREAD_LOCAL_VAR __thread + +/* Defined if the host OS provides ENAMETOOLONG errno value. */ +#define LOG4CPLUS_HAVE_ENAMETOOLONG 1 + +/* Defined if the compiler provides __sync_add_and_fetch(). */ +#define LOG4CPLUS_HAVE___SYNC_ADD_AND_FETCH 1 + +/* Defined if the compiler provides __sync_sub_and_fetch(). */ +#define LOG4CPLUS_HAVE___SYNC_SUB_AND_FETCH 1 + +/* Defined if the compiler provides C++11 header and increment, + decrement operations. */ +/* #undef LOG4CPLUS_HAVE_CXX11_ATOMICS */ + +/* */ +#define LOG4CPLUS_HAVE_C99_VARIADIC_MACROS 1 + +/* */ +#define LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS 1 + +/* */ +#define LOG4CPLUS_HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the `vsnwprintf' function. */ +/* #undef LOG4CPLUS_HAVE_VSNWPRINTF */ + +/* Define to 1 if you have the `_vsnwprintf' function. */ +/* #undef LOG4CPLUS_HAVE__VSNWPRINTF */ + +/* */ +/* #undef LOG4CPLUS_HAVE__VSNPRINTF */ + +/* Define to 1 if you have the `vfprintf_s' function. */ +/* #undef LOG4CPLUS_HAVE_VFPRINTF_S */ + +/* Define to 1 if you have the `vfwprintf_s' function. */ +/* #undef LOG4CPLUS_HAVE_VFWPRINTF_S */ + +/* Define to 1 if you have the `vsprintf_s' function. */ +/* #undef LOG4CPLUS_HAVE_VSPRINTF_S */ + +/* Define to 1 if you have the `vswprintf_s' function. */ +/* #undef LOG4CPLUS_HAVE_VSWPRINTF_S */ + +/* Define to 1 if you have the `_vsnprintf_s' function. */ +/* #undef LOG4CPLUS_HAVE__VSNPRINTF_S */ + +/* Define to 1 if you have the `_vsnwprintf_s' function. */ +/* #undef LOG4CPLUS_HAVE__VSNWPRINTF_S */ + +/* Defined if the compiler supports __FUNCTION__ macro. */ +#define LOG4CPLUS_HAVE_FUNCTION_MACRO 1 + +/* Defined if the compiler supports __PRETTY_FUNCTION__ macro. */ +#define LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO 1 + +/* Defined if the compiler supports __func__ symbol. */ +#define LOG4CPLUS_HAVE_FUNC_SYMBOL 1 + +/* Define to 1 if you have the `mbstowcs' function. */ +#define LOG4CPLUS_HAVE_MBSTOWCS 1 + +/* Define to 1 if you have the `wcstombs' function. */ +#define LOG4CPLUS_HAVE_WCSTOMBS 1 + +/* Define to 1 if you have Linux style syscall(SYS_gettid). */ +#define LOG4CPLUS_HAVE_GETTID 1 + +/* Define when iconv() is available. */ +/* #undef LOG4CPLUS_WITH_ICONV */ + +/* Define to 1 if you have the `iconv' function. */ +/* #undef LOG4CPLUS_HAVE_ICONV */ + +/* Define to 1 if you have the `iconv_close' function. */ +/* #undef LOG4CPLUS_HAVE_ICONV_CLOSE */ + +/* Define to 1 if you have the `iconv_open' function. */ +/* #undef LOG4CPLUS_HAVE_ICONV_OPEN */ + +/* Define to 1 if the system has the `constructor' function attribute */ +#define LOG4CPLUS_HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR 1 + +/* Define to 1 if the system has the `init_priority' variable attribute */ +#define LOG4CPLUS_HAVE_VAR_ATTRIBUTE_INIT_PRIORITY 1 + +#endif // LOG4CPLUS_CONFIG_DEFINES_HXX diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config/defines.hxx.in b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config/defines.hxx.in new file mode 100644 index 0000000..2f4158e --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config/defines.hxx.in @@ -0,0 +1,265 @@ +#ifndef LOG4CPLUS_CONFIG_DEFINES_HXX +#define LOG4CPLUS_CONFIG_DEFINES_HXX + +/* */ +#undef LOG4CPLUS_HAVE_SYSLOG_H + +/* */ +#undef LOG4CPLUS_HAVE_ARPA_INET_H + +/* */ +#undef LOG4CPLUS_HAVE_NETINET_IN_H + +/* */ +#undef LOG4CPLUS_HAVE_NETINET_TCP_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TIMEB_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TIME_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_TYPES_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_STAT_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_SYSCALL_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_FILE_H + +/* */ +#undef LOG4CPLUS_HAVE_TIME_H + +/* */ +#undef LOG4CPLUS_HAVE_SYS_SOCKET_H + +/* */ +#undef LOG4CPLUS_HAVE_NETDB_H + +/* */ +#undef LOG4CPLUS_HAVE_UNISTD_H + +/* */ +#undef LOG4CPLUS_HAVE_FCNTL_H + +/* */ +#undef LOG4CPLUS_HAVE_STDARG_H + +/* */ +#undef LOG4CPLUS_HAVE_STDIO_H + +/* */ +#undef LOG4CPLUS_HAVE_STDLIB_H + +/* */ +#undef LOG4CPLUS_HAVE_ERRNO_H + +/* */ +#undef LOG4CPLUS_HAVE_WCHAR_H + +/* */ +#undef LOG4CPLUS_HAVE_ICONV_H + +/* */ +#undef LOG4CPLUS_HAVE_LIMITS_H + +/* */ +#undef LOG4CPLUS_HAVE_FTIME + +/* */ +#undef LOG4CPLUS_HAVE_GETADDRINFO + +/* */ +#undef LOG4CPLUS_HAVE_GETHOSTBYNAME_R + +/* */ +#undef LOG4CPLUS_HAVE_GETPID + +/* */ +#undef LOG4CPLUS_HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the `clock_gettime' function. */ +#undef LOG4CPLUS_HAVE_CLOCK_GETTIME + +/* Define to 1 if you have the `nanosleep' function. */ +#undef LOG4CPLUS_HAVE_NANOSLEEP + +/* Define to 1 if you have the `clock_nanosleep' function. */ +#undef LOG4CPLUS_HAVE_CLOCK_NANOSLEEP + +/* */ +#undef LOG4CPLUS_HAVE_GMTIME_R + +/* */ +#undef LOG4CPLUS_HAVE_HTONL + +/* */ +#undef LOG4CPLUS_HAVE_HTONS + +/* */ +#undef LOG4CPLUS_HAVE_LOCALTIME_R + +/* */ +#undef LOG4CPLUS_HAVE_LSTAT + +/* */ +#undef LOG4CPLUS_HAVE_FCNTL + +/* */ +#undef LOG4CPLUS_HAVE_LOCKF + +/* */ +#undef LOG4CPLUS_HAVE_FLOCK + +/* */ +#undef LOG4CPLUS_HAVE_NTOHL + +/* */ +#undef LOG4CPLUS_HAVE_NTOHS + +/* Define to 1 if you have the `shutdown' function. */ +#undef LOG4CPLUS_HAVE_SHUTDOWN + +/* */ +#undef LOG4CPLUS_HAVE_PIPE + +/* */ +#undef LOG4CPLUS_HAVE_PIPE2 + +/* */ +#undef LOG4CPLUS_HAVE_POLL + +/* */ +#undef LOG4CPLUS_HAVE_POLL_H + +/* */ +#undef LOG4CPLUS_HAVE_STAT + +/* Define if this is a single-threaded library. */ +#undef LOG4CPLUS_SINGLE_THREADED + +/* */ +#undef LOG4CPLUS_USE_PTHREADS + +/* Define for compilers/standard libraries that support more than just the "C" + locale. */ +#undef LOG4CPLUS_WORKING_LOCALE + +/* Define for C99 compilers/standard libraries that support more than just the + "C" locale. */ +#undef LOG4CPLUS_WORKING_C_LOCALE + +/* Define to int if undefined. */ +#undef socklen_t + +/* Defined for --enable-debugging builds. */ +#undef LOG4CPLUS_DEBUGGING + +/* Defined if the compiler understands __declspec(dllexport) or + __attribute__((visibility("default"))) construct. */ +#undef LOG4CPLUS_DECLSPEC_EXPORT + +/* Defined if the compiler understands __declspec(dllimport) or + __attribute__((visibility("default"))) construct. */ +#undef LOG4CPLUS_DECLSPEC_IMPORT + +/* Defined if the compiler understands + __attribute__((visibility("hidden"))) construct. */ +#undef LOG4CPLUS_DECLSPEC_PRIVATE + +/* */ +#undef LOG4CPLUS_HAVE_TLS_SUPPORT + +/* */ +#undef LOG4CPLUS_THREAD_LOCAL_VAR + +/* Defined if the host OS provides ENAMETOOLONG errno value. */ +#undef LOG4CPLUS_HAVE_ENAMETOOLONG + +/* Defined if the compiler provides __sync_add_and_fetch(). */ +#undef LOG4CPLUS_HAVE___SYNC_ADD_AND_FETCH + +/* Defined if the compiler provides __sync_sub_and_fetch(). */ +#undef LOG4CPLUS_HAVE___SYNC_SUB_AND_FETCH + +/* Defined if the compiler provides C++11 header and increment, + decrement operations. */ +#undef LOG4CPLUS_HAVE_CXX11_ATOMICS + +/* */ +#undef LOG4CPLUS_HAVE_C99_VARIADIC_MACROS + +/* */ +#undef LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS + +/* */ +#undef LOG4CPLUS_HAVE_VSNPRINTF + +/* Define to 1 if you have the `vsnwprintf' function. */ +#undef LOG4CPLUS_HAVE_VSNWPRINTF + +/* Define to 1 if you have the `_vsnwprintf' function. */ +#undef LOG4CPLUS_HAVE__VSNWPRINTF + +/* */ +#undef LOG4CPLUS_HAVE__VSNPRINTF + +/* Define to 1 if you have the `vfprintf_s' function. */ +#undef LOG4CPLUS_HAVE_VFPRINTF_S + +/* Define to 1 if you have the `vfwprintf_s' function. */ +#undef LOG4CPLUS_HAVE_VFWPRINTF_S + +/* Define to 1 if you have the `vsprintf_s' function. */ +#undef LOG4CPLUS_HAVE_VSPRINTF_S + +/* Define to 1 if you have the `vswprintf_s' function. */ +#undef LOG4CPLUS_HAVE_VSWPRINTF_S + +/* Define to 1 if you have the `_vsnprintf_s' function. */ +#undef LOG4CPLUS_HAVE__VSNPRINTF_S + +/* Define to 1 if you have the `_vsnwprintf_s' function. */ +#undef LOG4CPLUS_HAVE__VSNWPRINTF_S + +/* Defined if the compiler supports __FUNCTION__ macro. */ +#undef LOG4CPLUS_HAVE_FUNCTION_MACRO + +/* Defined if the compiler supports __PRETTY_FUNCTION__ macro. */ +#undef LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO + +/* Defined if the compiler supports __func__ symbol. */ +#undef LOG4CPLUS_HAVE_FUNC_SYMBOL + +/* Define to 1 if you have the `mbstowcs' function. */ +#undef LOG4CPLUS_HAVE_MBSTOWCS + +/* Define to 1 if you have the `wcstombs' function. */ +#undef LOG4CPLUS_HAVE_WCSTOMBS + +/* Define to 1 if you have Linux style syscall(SYS_gettid). */ +#undef LOG4CPLUS_HAVE_GETTID + +/* Define when iconv() is available. */ +#undef LOG4CPLUS_WITH_ICONV + +/* Define to 1 if you have the `iconv' function. */ +#undef LOG4CPLUS_HAVE_ICONV + +/* Define to 1 if you have the `iconv_close' function. */ +#undef LOG4CPLUS_HAVE_ICONV_CLOSE + +/* Define to 1 if you have the `iconv_open' function. */ +#undef LOG4CPLUS_HAVE_ICONV_OPEN + +/* Define to 1 if the system has the `constructor' function attribute */ +#undef LOG4CPLUS_HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR + +/* Define to 1 if the system has the `init_priority' variable attribute */ +#undef LOG4CPLUS_HAVE_VAR_ATTRIBUTE_INIT_PRIORITY + +#endif // LOG4CPLUS_CONFIG_DEFINES_HXX diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config/macosx.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config/macosx.h new file mode 100644 index 0000000..448090c --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config/macosx.h @@ -0,0 +1,37 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: config-macosx.h +// Created: 7/2003 +// Author: Christopher R. Bailey +// +// +// Copyright 2003-2013 Christopher R. Bailey +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_CONFIG_MACOSX_HEADER_ +#define LOG4CPLUS_CONFIG_MACOSX_HEADER_ + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if (defined(__APPLE__) || (defined(__MWERKS__) && defined(__MACOS__))) + +#define LOG4CPLUS_HAVE_GETTIMEOFDAY 1 +#define socklen_t int + +#endif // MACOSX +#endif // LOG4CPLUS_CONFIG_MACOSX_HEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config/stamp-h2 b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config/stamp-h2 new file mode 100644 index 0000000..109f0fe --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config/stamp-h2 @@ -0,0 +1 @@ +timestamp for include/log4cplus/config/defines.hxx diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config/win32.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config/win32.h new file mode 100644 index 0000000..2ade3b9 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config/win32.h @@ -0,0 +1,210 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: config-win32.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_CONFIG_WIN32_HEADER_ +#define LOG4CPLUS_CONFIG_WIN32_HEADER_ + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (__MINGW32__) || defined (__MINGW64__) +# include <_mingw.h> +#endif + +#ifdef _WIN32 + +#if (defined (_MSC_VER) && _MSC_VER > 1400) \ + || (defined (__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR >= 3) +# define LOG4CPLUS_HAVE_INTRIN_H +#endif + +// Time related functions and headers. +#define LOG4CPLUS_HAVE_TIME_H +#define LOG4CPLUS_HAVE_SYS_TIMEB_H +#define LOG4CPLUS_HAVE_FTIME +#if defined (_MSC_VER) || defined (__BORLANDC__) +#define LOG4CPLUS_HAVE_GMTIME_S +#endif + +// Use Winsock on Windows. +#define LOG4CPLUS_USE_WINSOCK + +// Enable Win32DebugAppender +#define LOG4CPLUS_HAVE_OUTPUTDEBUGSTRING + +// Enable Win32ConsoleAppender. +#define LOG4CPLUS_HAVE_WIN32_CONSOLE + +#define LOG4CPLUS_HAVE_SYS_TYPES_H +#define LOG4CPLUS_HAVE_SYS_LOCKING_H +#define LOG4CPLUS_HAVE_FCNTL_H +#define LOG4CPLUS_HAVE_IO_H +#define LOG4CPLUS_HAVE_STDIO_H +#define LOG4CPLUS_HAVE_WCHAR_H +#define LOG4CPLUS_HAVE_STDARG_H +#define LOG4CPLUS_HAVE_STDLIB_H +#define LOG4CPLUS_HAVE_ERRNO_H +#define LOG4CPLUS_HAVE_SYS_STAT_H +#define LOG4CPLUS_HAVE_TIME_H +#define LOG4CPLUS_HAVE_STDLIB_H + +// MSVC has both and so does MinGW. +#define LOG4CPLUS_HAVE_VSNPRINTF +#define LOG4CPLUS_HAVE__VSNPRINTF +#define LOG4CPLUS_HAVE__VSNWPRINTF + +// Limit the use of foo_s() functions to builds using Visual Studio +// 2005 and its run time library. In MinGW land, limit the foo_s() +// functions to MinGw-w64 toolchain and __MSVCRT_VERSION__ >= 0x0900. +#if (defined (_MSC_VER) && _MSC_VER >= 1400) \ + || (defined (__MSVCRT_VERSION__) && __MSVCRT_VERSION__ >= 0x0900 \ + && defined (__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR >= 2) +// MS secure versions of vprintf(). +# define LOG4CPLUS_HAVE_VSPRINTF_S +# define LOG4CPLUS_HAVE_VSWPRINTF_S + +// MS secure versions of vfprintf(). +# define LOG4CPLUS_HAVE_VFPRINTF_S +# define LOG4CPLUS_HAVE_VFWPRINTF_S + +// MS secure versions of vsnprintf(). +# define LOG4CPLUS_HAVE_VSNPRINTF_S +# define LOG4CPLUS_HAVE__VSNPRINTF_S +# define LOG4CPLUS_HAVE__VSNWPRINTF_S + +// MS printf-like functions supporting positional parameters. +# define LOG4CPLUS_HAVE__VSPRINTF_P +# define LOG4CPLUS_HAVE__VSWPRINTF_P + +// MS secure version of _tsopen(). +# define LOG4CPLUS_HAVE__TSOPEN_S +#endif + +#define LOG4CPLUS_HAVE__TSOPEN + +#define LOG4CPLUS_DLLMAIN_HINSTANCE HINSTANCE +#define LOG4CPLUS_HAVE_NT_EVENT_LOG + +// log4cplus_EXPORTS is used by the CMake build system. DLL_EXPORT is +// used by the autotools build system. +#if (defined (log4cplus_EXPORTS) || defined (log4cplusU_EXPORTS) \ + || defined (DLL_EXPORT)) \ + && ! defined (LOG4CPLUS_STATIC) +# undef LOG4CPLUS_BUILD_DLL +# define LOG4CPLUS_BUILD_DLL +#endif + +#if ! defined (LOG4CPLUS_BUILD_DLL) +# undef LOG4CPLUS_STATIC +# define LOG4CPLUS_STATIC +#endif + +#if defined (LOG4CPLUS_STATIC) && defined (LOG4CPLUS_BUILD_DLL) +# error LOG4CPLUS_STATIC and LOG4CPLUS_BUILD_DLL cannot be defined both. +#endif + +#if defined (LOG4CPLUS_BUILD_DLL) +# if defined (INSIDE_LOG4CPLUS) +# define LOG4CPLUS_EXPORT __declspec(dllexport) +# else +# define LOG4CPLUS_EXPORT __declspec(dllimport) +# endif +#else +# define LOG4CPLUS_EXPORT +#endif + +#ifndef LOG4CPLUS_SINGLE_THREADED +# define LOG4CPLUS_USE_WIN32_THREADS +#endif + +#if defined (_WIN32_WINNT) && _WIN32_WINNT < 0x0600 +# define LOG4CPLUS_POOR_MANS_SHAREDMUTEX +#endif + +#if defined(_MSC_VER) + // Warning about: identifier was truncated to '255' characters in the debug information +# pragma warning( disable : 4786 ) + // Warning about: needs to have dll-interface to be used by clients of class +# pragma warning( disable : 4251 ) + +# define LOG4CPLUS_INLINES_ARE_EXPORTED + +# if _MSC_VER >= 1400 +# define LOG4CPLUS_WORKING_LOCALE +# define LOG4CPLUS_HAVE_FUNCTION_MACRO +# define LOG4CPLUS_HAVE_FUNCSIG_MACRO +# define LOG4CPLUS_HAVE_C99_VARIADIC_MACROS +# define LOG4CPLUS_ATTRIBUTE_NORETURN __declspec(noreturn) +# endif +# if _MSC_VER >= 1700 +# define LOG4CPLUS_HAVE_CXX11_ATOMICS +# endif +#endif + +#if defined (__GNUC__) +# undef LOG4CPLUS_INLINES_ARE_EXPORTED +# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) +# define LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO +# define LOG4CPLUS_HAVE_FUNC_SYMBOL +# endif +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) +# if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) +# define LOG4CPLUS_HAVE___SYNC_SUB_AND_FETCH +# define LOG4CPLUS_HAVE___SYNC_ADD_AND_FETCH +# endif +# endif +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) +# if defined (__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) +# define LOG4CPLUS_HAVE___ATOMIC_ADD_FETCH +# define LOG4CPLUS_HAVE___ATOMIC_SUB_FETCH +# endif +// This has worked for some versions of MinGW with GCC 4.7+ but it +// appears to be broken again in 4.8.x. Thus, we disable this for GCC +// completely forever. +// +//# define LOG4CPLUS_INLINES_ARE_EXPORTED +# endif +# define LOG4CPLUS_HAVE_FUNCTION_MACRO +# define LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS +# define LOG4CPLUS_HAVE_C99_VARIADIC_MACROS +# if defined (__MINGW32__) +# define LOG4CPLUS_WORKING_C_LOCALE +# endif +#endif + +#if defined (__BORLANDC__) && __BORLANDC__ >= 0x0650 +# define LOG4CPLUS_HAVE_FUNCTION_MACRO +# define LOG4CPLUS_HAVE_C99_VARIADIC_MACROS +#endif // __BORLANDC__ + +#if ! defined (LOG4CPLUS_DISABLE_DLL_RUNTIME_WARNING) +# if defined (LOG4CPLUS_STATIC) && defined (_MSC_VER) && ! defined (_DLL) +# pragma message("You are not using DLL C run time library. " \ + "You must call log4cplus::initialize() once before " \ + "you use any other log4cplus API.") +# endif +#endif + +#endif // _WIN32 +#endif // LOG4CPLUS_CONFIG_WIN32_HEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config/windowsh-inc.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config/windowsh-inc.h new file mode 100644 index 0000000..b71a8e1 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/config/windowsh-inc.h @@ -0,0 +1,159 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: windowsh-inc.h +// Created: 4/2010 +// Author: Vaclav Zeman +// +// +// Copyright (C) 2010-2013, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// NOTE: This file is a fragment intentionally left without include guards. + +#if defined (_WIN32) +#undef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN + +#undef NOGDICAPMASKS +#define NOGDICAPMASKS + +#undef NOVIRTUALKEYCODES +#define NOVIRTUALKEYCODES + +#undef NOWINMESSAGES +#define NOWINMESSAGES + +#undef NOWINSTYLES +#define NOWINSTYLES + +#undef NOSYSMETRICS +#define NOSYSMETRICS + +#undef NOMENUS +#define NOMENUS + +#undef NOICONS +#define NOICONS + +#undef NOKEYSTATES +#define NOKEYSTATES + +#undef NOSYSCOMMANDS +#define NOSYSCOMMANDS + +#undef NORASTEROPS +#define NORASTEROPS + +#undef NOSHOWWINDOW +#define NOSHOWWINDOW + +#undef NOATOM +#define NOATOM + +#undef NOCLIPBOARD +#define NOCLIPBOARD + +#undef NOCOLOR +#define NOCOLOR + +#undef NOCTLMGR +#define NOCTLMGR + +#undef NODRAWTEXT +#define NODRAWTEXT + +#undef NOGDI +#define NOGDI + +#undef NOKERNEL +#define NOKERNEL + +#undef NOUSER +#define NOUSER + +#undef NONLS +#define NONLS + +#undef NOMB +#define NOMB + +#undef NOMEMMGR +#define NOMEMMGR + +#undef NOMETAFILE +#define NOMETAFILE + +#undef NOMINMAX +#define NOMINMAX + +#undef NOMSG +#define NOMSG + +#undef NOOPENFILE +#define NOOPENFILE + +#undef NOSCROLL +#define NOSCROLL + +#undef NOSERVICE +#define NOSERVICE + +#undef NOSOUND +#define NOSOUND + +#undef NOTEXTMETRIC +#define NOTEXTMETRIC + +#undef NOWH +#define NOWH + +#undef NOWINOFFSETS +#define NOWINOFFSETS + +#undef NOCOMM +#define NOCOMM + +#undef NOKANJI +#define NOKANJI + +#undef NOHELP +#define NOHELP + +#undef NOPROFILER +#define NOPROFILER + +#undef NODEFERWINDOWPOS +#define NODEFERWINDOWPOS + +#undef NOMCX +#define NOMCX + +#include +#include +#include +#if defined (LOG4CPLUS_HAVE_INTRIN_H) +#include +#endif +#endif + +// NOTE: This file is a fragment intentionally left without include guards. diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/configurator.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/configurator.h new file mode 100644 index 0000000..5cbb96f --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/configurator.h @@ -0,0 +1,374 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: configurator.h +// Created: 3/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_CONFIGURATOR_HEADER_ +#define LOG4CPLUS_CONFIGURATOR_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + +#include + + +namespace log4cplus +{ + class Hierarchy; + + + /** + * Provides configuration from an external file. See configure() for + * the expected format. + * + * All option values admit variable substitution. For + * example, if userhome environment property is set to + * /home/xyz and the File option is set to the string + * ${userhome}/test.log, then File option will be + * interpreted as the string /home/xyz/test.log. + * + * The syntax of variable substitution is similar to that of UNIX + * shells. The string between an opening "${" and + * closing "}" is interpreted as a key. Its value is + * searched in the environment properties. The corresponding value replaces + * the ${variableName} sequence. + * + * Configuration files also recognize include + * file.properties directive that allow composing + * configuration from multiple files. There is no cyclic includes + * detection mechanism to stop unbound recursion. + */ + class LOG4CPLUS_EXPORT PropertyConfigurator + { + public: + enum PCFlags + { + fRecursiveExpansion = (1 << 0) + , fShadowEnvironment = (1 << 1) + , fAllowEmptyVars = (1 << 2) + + // These encoding related options occupy 2 bits of the flags + // and are mutually exclusive. These flags are synchronized with + // PFlags in Properties. + + , fEncodingShift = 3 + , fEncodingMask = 0x3 + , fUnspecEncoding = (0 << fEncodingShift) +#if defined (LOG4CPLUS_HAVE_CODECVT_UTF8_FACET) && defined (UNICODE) + , fUTF8 = (1 << fEncodingShift) +#endif +#if (defined (LOG4CPLUS_HAVE_CODECVT_UTF16_FACET) || defined (_WIN32)) \ + && defined (UNICODE) + , fUTF16 = (2 << fEncodingShift) +#endif +#if defined (LOG4CPLUS_HAVE_CODECVT_UTF32_FACET) && defined (UNICODE) + , fUTF32 = (3 << fEncodingShift) +#endif + }; + + // ctor and dtor + PropertyConfigurator(const log4cplus::tstring& propertyFile, + Hierarchy& h = Logger::getDefaultHierarchy(), unsigned flags = 0); + PropertyConfigurator(const log4cplus::helpers::Properties& props, + Hierarchy& h = Logger::getDefaultHierarchy(), unsigned flags = 0); + PropertyConfigurator(log4cplus::tistream& propertyStream, + Hierarchy& h = Logger::getDefaultHierarchy(), unsigned flags = 0); + virtual ~PropertyConfigurator(); + + /** + * This method eliminates the need to create a temporary + * PropertyConfigurator to configure log4cplus. + * It is equivalent to the following:
+ * + * PropertyConfigurator config("filename"); + * config.configure(); + * + */ + static void doConfigure(const log4cplus::tstring& configFilename, + Hierarchy& h = Logger::getDefaultHierarchy(), unsigned flags = 0); + + /** + * Read configuration from a file. The existing configuration is + * not cleared nor reset. If you require a different behavior, + * then call {@link Hierarchy::resetConfiguration + * resetConfiguration} method before calling + * doConfigure. + * + * The configuration file consists of statements in the format + * key=value. The syntax of different configuration + * elements are discussed below. + * + *

Appender configuration

+ * + * Appender configuration syntax is: + *
+         * # For appender named appenderName, set its class.
+         * # Note: The appender name can contain dots.
+         * log4cplus.appender.appenderName=fully.qualified.name.of.appender.class
+         *
+         * # Set appender specific options.
+         * log4cplus.appender.appenderName.option1=value1
+         * ...
+         * log4cplus.appender.appenderName.optionN=valueN
+         * 
+ * + * For each named appender you can configure its {@link Layout}. The + * syntax for configuring an appender's layout is: + *
+         * log4cplus.appender.appenderName.layout=fully.qualified.name.of.layout.class
+         * log4cplus.appender.appenderName.layout.option1=value1
+         * ....
+         * log4cplus.appender.appenderName.layout.optionN=valueN
+         * 
+ * + *

Configuring loggers

+ * + * The syntax for configuring the root logger is: + *
+         * log4cplus.rootLogger=[LogLevel], appenderName, appenderName, ...
+         * 
+ * + * This syntax means that an optional LogLevel value can + * be supplied followed by appender names separated by commas. + * + * The LogLevel value can consist of the string values FATAL, + * ERROR, WARN, INFO, DEBUG or a custom LogLevel value. + * + * If a LogLevel value is specified, then the root LogLevel is set + * to the corresponding LogLevel. If no LogLevel value is specified, + * then the root LogLevel remains untouched. + * + * The root logger can be assigned multiple appenders. + * + * Each appenderName (separated by commas) will be added to + * the root logger. The named appender is defined using the + * appender syntax defined above. + * + * For non-root loggers the syntax is almost the same: + *
+         * log4cplus.logger.logger_name=[LogLevel|INHERITED], appenderName, appenderName, ...
+         * 
+ * + * The meaning of the optional LogLevel value is discussed above + * in relation to the root logger. In addition however, the value + * INHERITED can be specified meaning that the named logger should + * inherit its LogLevel from the logger hierarchy. + * + * By default loggers inherit their LogLevel from the + * hierarchy. However, if you set the LogLevel of a logger and + * later decide that that logger should inherit its LogLevel, then + * you should specify INHERITED as the value for the LogLevel value. + * + * Similar to the root logger syntax, each appenderName + * (separated by commas) will be attached to the named logger. + * + * See the appender + * additivity rule in the user manual for the meaning of the + * additivity flag. + * + * The user can override any of the {@link + * Hierarchy#disable} family of methods by setting the a key + * "log4cplus.disableOverride" to true or any value other + * than false. As in
log4cplus.disableOverride=true 
+ * + *

Example

+ * + * An example configuration is given below. + * + *
+         *
+         * # Set options for appender named "A1".
+         * # Appender "A1" will be a SyslogAppender
+         * log4cplus.appender.A1=log4cplus::SyslogAppender
+         *
+         * # The syslog daemon resides on www.abc.net
+         * log4cplus.appender.A1.SyslogHost=www.abc.net
+         *
+         * # A1's layout is a PatternLayout, using the conversion pattern
+         * # %r %-5p %c{2} %M.%L %x - %m\n. Thus, the log output will
+         * # include # the relative time since the start of the application in
+         * # milliseconds, followed by the LogLevel of the log request,
+         * # followed by the two rightmost components of the logger name,
+         * # followed by the callers method name, followed by the line number,
+         * # the nested disgnostic context and finally the message itself.
+         * # Refer to the documentation of {@link PatternLayout} for further information
+         * # on the syntax of the ConversionPattern key.
+         * log4cplus.appender.A1.layout=log4cplus::PatternLayout
+         * log4cplus.appender.A1.layout.ConversionPattern=%-4r %-5p %c{2} %M.%L %x - %m\n
+         *
+         * # Set options for appender named "A2"
+         * # A2 should be a RollingFileAppender, with maximum file size of 10 MB
+         * # using at most one backup file. A2's layout is TTCC, using the
+         * # ISO8061 date format with context printing enabled.
+         * log4cplus.appender.A2=log4cplus::RollingFileAppender
+         * log4cplus.appender.A2.MaxFileSize=10MB
+         * log4cplus.appender.A2.MaxBackupIndex=1
+         * log4cplus.appender.A2.layout=log4cplus::TTCCLayout
+         * log4cplus.appender.A2.layout.ContextPrinting=enabled
+         * log4cplus.appender.A2.layout.DateFormat=ISO8601
+         *
+         * # Root logger set to DEBUG using the A2 appender defined above.
+         * log4cplus.rootLogger=DEBUG, A2
+         *
+         * # Logger definitions:
+         * # The SECURITY logger inherits is LogLevel from root. However, it's output
+         * # will go to A1 appender defined above. It's additivity is non-cumulative.
+         * log4cplus.logger.SECURITY=INHERIT, A1
+         * log4cplus.additivity.SECURITY=false
+         *
+         * # Only warnings or above will be logged for the logger "SECURITY.access".
+         * # Output will go to A1.
+         * log4cplus.logger.SECURITY.access=WARN
+         *
+         *
+         * # The logger "class.of.the.day" inherits its LogLevel from the
+         * # logger hierarchy.  Output will go to the appender's of the root
+         * # logger, A2 in this case.
+         * log4cplus.logger.class.of.the.day=INHERIT
+         * 
+ * + * Refer to the setOption method in each Appender and + * Layout for class specific options. + * + * Use the # character at the beginning of a line + * for comments. + */ + virtual void configure(); + + /** + * \return The return value is reference to Properties + * container of properties with the "log4cplus." + * prefix removed and references to other properties and/or + * environment variables expanded. + */ + log4cplus::helpers::Properties const & getProperties () const; + + /** + * \return The return value is a reference to log4cplus::tstring + * containing filename of properties source file. It will be + * string "UNAVAILABLE" if the PropertyConfigurator instance has been + * constructed using one of the other constructors that do not take + * filename as parameter. + */ + log4cplus::tstring const & getPropertyFilename () const; + + protected: + // Methods + void init(); // called by the ctor + void reconfigure(); + void replaceEnvironVariables(); + void configureLoggers(); + void configureLogger(log4cplus::Logger logger, const log4cplus::tstring& config); + void configureAppenders(); + void configureAdditivity(); + + virtual Logger getLogger(const log4cplus::tstring& name); + virtual void addAppender(Logger &logger, log4cplus::SharedAppenderPtr& appender); + + // Types + typedef std::map AppenderMap; + + // Data + Hierarchy& h; + log4cplus::tstring propertyFilename; + log4cplus::helpers::Properties properties; + AppenderMap appenders; + unsigned flags; + + private: + // Disable copy + PropertyConfigurator(const PropertyConfigurator&); + PropertyConfigurator& operator=(PropertyConfigurator&); + }; + + + + /** + * Use this class to quickly configure the package. For file based + * configuration see PropertyConfigurator. BasicConfigurator + * automatically attaches ConsoleAppender to + * rootLogger, with output going to standard output, + * using DEBUG LogLevel value. The additional parameter + * logToStdErr may redirect the output to standard error. + */ + class LOG4CPLUS_EXPORT BasicConfigurator : public PropertyConfigurator { + public: + // ctor and dtor + BasicConfigurator(Hierarchy& h = Logger::getDefaultHierarchy(), + bool logToStdErr = false); + virtual ~BasicConfigurator(); + + /** + * This method eliminates the need to create a temporary + * BasicConfigurator object to configure log4cplus. + * It is equivalent to the following:
+ *
+         * BasicConfigurator config;
+         * config.configure();
+         * 
+ */ + static void doConfigure(Hierarchy& h = Logger::getDefaultHierarchy(), + bool logToStdErr = false); + + //! Property name for disable override. + static log4cplus::tstring const DISABLE_OVERRIDE_KEY; + + private: + // Disable copy + BasicConfigurator(const BasicConfigurator&); + BasicConfigurator& operator=(BasicConfigurator&); + }; + + +#if !defined(LOG4CPLUS_SINGLE_THREADED) + // Forward Declarations + class ConfigurationWatchDogThread; + + + class LOG4CPLUS_EXPORT ConfigureAndWatchThread { + public: + // ctor and dtor + ConfigureAndWatchThread(const log4cplus::tstring& propertyFile, + unsigned int millis = 60 * 1000); + virtual ~ConfigureAndWatchThread(); + + private: + // Disallow copying of instances of this class + ConfigureAndWatchThread(const ConfigureAndWatchThread&); + ConfigureAndWatchThread& operator=(const ConfigureAndWatchThread&); + + // Data + ConfigurationWatchDogThread * watchDogThread; + }; +#endif + +} // end namespace log4cplus + +#endif // LOG4CPLUS_CONFIGURATOR_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/consoleappender.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/consoleappender.h new file mode 100644 index 0000000..e31bdad --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/consoleappender.h @@ -0,0 +1,85 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: consoleappender.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_CONSOLE_APPENDER_HEADER_ +#define LOG4CPLUS_CONSOLE_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +namespace log4cplus { + /** + * ConsoleAppender appends log events to std::cout or + * std::cerr using a layout specified by the + * user. The default target is std::cout. + * + *

Properties

+ *
+ *
logToStdErr
+ *
When it is set true, the output stream will be + * std::cerr instead of std::cout.
+ * + *
ImmediateFlush
+ *
When it is set true, output stream will be flushed after + * each appended event.
+ * + *
+ * \sa Appender + */ + class LOG4CPLUS_EXPORT ConsoleAppender : public Appender { + public: + // Ctors + ConsoleAppender(bool logToStdErr = false, bool immediateFlush = false); + ConsoleAppender(const log4cplus::helpers::Properties & properties); + + // Dtor + ~ConsoleAppender(); + + // Methods + virtual void close(); + + //! This mutex is used by ConsoleAppender and helpers::LogLog + //! classes to synchronize output to console. + static log4cplus::thread::Mutex const & getOutputMutex(); + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + + // Data + bool logToStdErr; + /** + * Immediate flush means that the underlying output stream + * will be flushed at the end of each append operation. + */ + bool immediateFlush; + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_CONSOLE_APPENDER_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/fileappender.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/fileappender.h new file mode 100644 index 0000000..787b92e --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/fileappender.h @@ -0,0 +1,282 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: fileappender.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_FILE_APPENDER_HEADER_ +#define LOG4CPLUS_FILE_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + + +namespace log4cplus +{ + + /** + * Appends log events to a file. + * + *

Properties

+ *
+ *
File
+ *
This property specifies output file name.
+ * + *
ImmediateFlush
+ *
When it is set true, output stream will be flushed after + * each appended event.
+ * + *
Append
+ *
When it is set true, output file will be appended to + * instead of being truncated at opening.
+ * + *
ReopenDelay
+ *
This property sets a delay after which the appender will try + * to reopen log file again, after last logging failure. + *
+ * + *
BufferSize
+ *
Non-zero value of this property sets up buffering of output + * stream using a buffer of given size. + *
+ * + *
UseLockFile
+ *
Set this property to true if you want your output + * to go into a log file shared by multiple processes. When this + * property is set to true then log4cplus uses OS specific + * facilities (e.g., lockf()) to provide + * inter-process file locking. + * \sa Appender + *
+ * + *
LockFile
+ *
This property specifies lock file, file used for + * inter-process synchronization of log file access. When this + * property is not specified, the value is derived from + * File property by addition of ".lock" suffix. The + * property is only used when UseLockFile is set to true. + * \sa Appender + *
+ * + *
Locale
+ *
This property specifies a locale name that will be imbued + * into output stream. Locale can be specified either by system + * specific locale name, e.g., en_US.UTF-8, or by one of + * four recognized keywords: GLOBAL, DEFAULT + * (which is an alias for GLOBAL), USER and + * CLASSIC. When specified locale is not available, + * GLOBAL is used instead. It is possible to register + * additional locale keywords by registering an instance of + * spi::LocaleFactory in + * spi::LocaleFactoryRegistry. + * \sa spi::getLocaleFactoryRegistry() + *
+ * + *
+ */ + class LOG4CPLUS_EXPORT FileAppender : public Appender { + public: + // Ctors + FileAppender(const log4cplus::tstring& filename, + std::ios_base::openmode mode = std::ios_base::trunc, + bool immediateFlush = true); + FileAppender(const log4cplus::helpers::Properties& properties, + std::ios_base::openmode mode = std::ios_base::trunc); + + // Dtor + virtual ~FileAppender(); + + // Methods + virtual void close(); + + //! Redefine default locale for output stream. It may be a good idea to + //! provide UTF-8 locale in case UNICODE macro is defined. + virtual std::locale imbue(std::locale const& loc); + + //! \returns Locale imbued in fstream. + virtual std::locale getloc () const; + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + + void open(std::ios_base::openmode mode); + bool reopen(); + + // Data + /** + * Immediate flush means that the underlying writer or output stream + * will be flushed at the end of each append operation. Immediate + * flush is slower but ensures that each append request is actually + * written. If immediateFlush is set to + * false, then there is a good chance that the last few + * logs events are not actually written to persistent media if and + * when the application crashes. + * + * The immediateFlush variable is set to + * true by default. + */ + bool immediateFlush; + + /** + * When any append operation fails, reopenDelay says + * for how many seconds the next attempt to re-open the log file and + * resume logging will be delayed. If reopenDelay is zero, + * each failed append operation will cause log file to be re-opened. + * By default, reopenDelay is 1 second. + */ + int reopenDelay; + + unsigned long bufferSize; + log4cplus::tchar * buffer; + + log4cplus::tofstream out; + log4cplus::tstring filename; + log4cplus::tstring localeName; + + log4cplus::helpers::Time reopen_time; + + private: + LOG4CPLUS_PRIVATE void init(const log4cplus::tstring& filename, + std::ios_base::openmode mode, + const log4cplus::tstring& lockFileName); + + // Disallow copying of instances of this class + FileAppender(const FileAppender&); + FileAppender& operator=(const FileAppender&); + }; + + + + /** + * RollingFileAppender extends FileAppender to backup the log + * files when they reach a certain size. + * + *

Properties

+ *

Properties additional to {@link FileAppender}'s properties: + * + *

+ *
MaxFileSize
+ *
This property specifies maximal size of output file. The + * value is in bytes. It is possible to use MB and + * KB suffixes to specify the value in megabytes or + * kilobytes instead.
+ * + *
MaxBackupIndex
+ *
This property limits the number of backup output + * files; e.g. how many log.1, log.2 etc. files + * will be kept.
+ *
+ */ + class LOG4CPLUS_EXPORT RollingFileAppender : public FileAppender { + public: + // Ctors + RollingFileAppender(const log4cplus::tstring& filename, + long maxFileSize = 10*1024*1024, // 10 MB + int maxBackupIndex = 1, + bool immediateFlush = true); + RollingFileAppender(const log4cplus::helpers::Properties& properties); + + // Dtor + virtual ~RollingFileAppender(); + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + void rollover(bool alreadyLocked = false); + + // Data + long maxFileSize; + int maxBackupIndex; + + private: + LOG4CPLUS_PRIVATE void init(long maxFileSize, int maxBackupIndex); + }; + + + + enum DailyRollingFileSchedule { MONTHLY, WEEKLY, DAILY, + TWICE_DAILY, HOURLY, MINUTELY}; + + /** + * DailyRollingFileAppender extends {@link FileAppender} so that the + * underlying file is rolled over at a user chosen frequency. + * + *

Properties

+ *

Properties additional to {@link FileAppender}'s properties: + * + *

+ *
Schedule
+ *
This property specifies rollover schedule. The possible + * values are MONTHLY, WEEKLY, DAILY, + * TWICE_DAILY, HOURLY and + * MINUTELY.
+ * + *
MaxBackupIndex
+ *
This property limits how many backup files are kept per + * single logging period; e.g. how many log.2009-11-07.1, + * log.2009-11-07.2 etc. files are kept.
+ * + *
+ */ + class LOG4CPLUS_EXPORT DailyRollingFileAppender : public FileAppender { + public: + // Ctors + DailyRollingFileAppender(const log4cplus::tstring& filename, + DailyRollingFileSchedule schedule = DAILY, + bool immediateFlush = true, + int maxBackupIndex = 10); + DailyRollingFileAppender(const log4cplus::helpers::Properties& properties); + + // Dtor + virtual ~DailyRollingFileAppender(); + + // Methods + virtual void close(); + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + void rollover(bool alreadyLocked = false); + log4cplus::helpers::Time calculateNextRolloverTime(const log4cplus::helpers::Time& t) const; + log4cplus::tstring getFilename(const log4cplus::helpers::Time& t) const; + + // Data + DailyRollingFileSchedule schedule; + log4cplus::tstring scheduledFilename; + log4cplus::helpers::Time nextRolloverTime; + int maxBackupIndex; + + private: + LOG4CPLUS_PRIVATE void init(DailyRollingFileSchedule schedule); + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_FILE_APPENDER_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/fstreams.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/fstreams.h new file mode 100644 index 0000000..d0c0831 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/fstreams.h @@ -0,0 +1,56 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: fstreams.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_FSTREAMS_HEADER_ +#define LOG4CPLUS_FSTREAMS_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus +{ + + +typedef std::basic_ofstream tofstream; +typedef std::basic_ifstream tifstream; + +//! \def LOG4CPLUS_FSTREAM_PREFERED_FILE_NAME(X) +//! \brief Expands into expression that picks the right type for +//! std::fstream file name parameter. +#if defined (LOG4CPLUS_FSTREAM_ACCEPTS_WCHAR_T) && defined (UNICODE) +# define LOG4CPLUS_FSTREAM_PREFERED_FILE_NAME(X) (X) +#else +# define LOG4CPLUS_FSTREAM_PREFERED_FILE_NAME(X) (LOG4CPLUS_TSTRING_TO_STRING(X)) +#endif + + +} + +#endif // LOG4CPLUS_FSTREAMS_HEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/appenderattachableimpl.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/appenderattachableimpl.h new file mode 100644 index 0000000..4cfaf3f --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/appenderattachableimpl.h @@ -0,0 +1,119 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: appenderattachableimpl.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_APPENDER_ATTACHABLE_IMPL_HEADER_ +#define LOG4CPLUS_HELPERS_APPENDER_ATTACHABLE_IMPL_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + +#include +#include + + +namespace log4cplus { + namespace helpers { + + /** + * This Interface is for attaching Appenders to objects. + */ + class LOG4CPLUS_EXPORT AppenderAttachableImpl + : public log4cplus::spi::AppenderAttachable + { + public: + // Data + thread::Mutex appender_list_mutex; + + // Ctors + AppenderAttachableImpl(); + + // Dtor + virtual ~AppenderAttachableImpl(); + + // Methods + /** + * Add an appender. If the appender is already in the list in + * won't be added again. + */ + virtual void addAppender(SharedAppenderPtr newAppender); + + /** + * Get all previously added appenders as an vectory. + */ + virtual SharedAppenderPtrList getAllAppenders(); + + /** + * Look for an attached appender named as name. + * + * Return the appender with that name if in the list. Return null + * otherwise. + */ + virtual SharedAppenderPtr getAppender(const log4cplus::tstring& name); + + /** + * Remove all previously added appenders. + */ + virtual void removeAllAppenders(); + + /** + * Remove the appender passed as parameter from the list of appenders. + */ + virtual void removeAppender(SharedAppenderPtr appender); + + /** + * Remove the appender with the name passed as parameter from the + * list of appenders. + */ + virtual void removeAppender(const log4cplus::tstring& name); + + /** + * Call the doAppend method on all attached appenders. + */ + int appendLoopOnAppenders(const spi::InternalLoggingEvent& event) const; + + protected: + // Types + typedef std::vector ListType; + + // Data + /** Array of appenders. */ + ListType appenderList; + + private: + AppenderAttachableImpl(AppenderAttachableImpl const &); + AppenderAttachableImpl & operator = (AppenderAttachableImpl const &); + }; // end class AppenderAttachableImpl + + } // end namespace helpers +} // end namespace log4cplus + +#endif // LOG4CPLUS_HELPERS_APPENDER_ATTACHABLE_IMPL_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/fileinfo.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/fileinfo.h new file mode 100644 index 0000000..725c940 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/fileinfo.h @@ -0,0 +1,59 @@ +// -*- C++ -*- +// +// Copyright (C) 2012-2013, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if ! defined (LOG4CPLUS_HELPERS_FILEINFO_H) +#define LOG4CPLUS_HELPERS_FILEINFO_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#ifdef LOG4CPLUS_HAVE_SYS_TYPES_H +#include +#endif + + +namespace log4cplus { namespace helpers { + +//! FileInfo structure is OS independent abstraction of the +//! stat() function. +struct LOG4CPLUS_EXPORT FileInfo +{ + helpers::Time mtime; + bool is_link; + off_t size; +}; + + +//! OS independent abstraction of stat() function. +LOG4CPLUS_EXPORT int getFileInfo (FileInfo * fi, tstring const & name); + + +} } // namespace log4cplus { namespace helpers { + +#endif // LOG4CPLUS_HELPERS_FILEINFO_H diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/lockfile.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/lockfile.h new file mode 100644 index 0000000..f451ff8 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/lockfile.h @@ -0,0 +1,68 @@ +// -*- C++ -*- +// +// Copyright (C) 2012-2013, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if ! defined (LOG4CPLUS_HELPERS_LOCKFILE_H) +#define LOG4CPLUS_HELPERS_LOCKFILE_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus { namespace helpers { + + +class LOG4CPLUS_EXPORT LockFile +{ +public: + LockFile (tstring const & lock_file); + ~LockFile (); + + void lock () const; + void unlock () const; + +private: + void open (int) const; + void close () const; + + struct Impl; + + tstring lock_file_name; + Impl * data; +}; + + +typedef log4cplus::thread::SyncGuard LockFileGuard; + + +} } // namespace log4cplus { namespace helpers { + + +#endif // LOG4CPLUS_HELPERS_LOCKFILE_H diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/loglog.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/loglog.h new file mode 100644 index 0000000..336f18f --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/loglog.h @@ -0,0 +1,145 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: loglog.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_LOGLOG +#define LOG4CPLUS_HELPERS_LOGLOG + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include + + +namespace log4cplus { + namespace helpers { + + /** + * This class used to output log statements from within the log4cplus package. + * + * Log4cplus components cannot make log4cplus logging calls. However, it is + * sometimes useful for the user to learn about what log4cplus is + * doing. You can enable log4cplus internal logging by defining the + * log4cplus.configDebug variable. + * + * All log4cplus internal debug calls go to cout + * where as internal error messages are sent to + * cerr. All internal messages are prepended with + * the string "log4clus: ". + */ + class LOG4CPLUS_EXPORT LogLog + { + public: + //! Return type of getLogLog(). + typedef LogLog * Ptr; + + /** + * Returns a reference to the LogLog singleton. + */ + static Ptr getLogLog(); + + + /** + * Allows to enable/disable log4cplus internal logging. + */ + void setInternalDebugging(bool enabled); + + /** + * In quite mode no LogLog generates strictly no output, not even + * for errors. + * + * @param quietMode A true for not + */ + void setQuietMode(bool quietMode); + + /** + * This method is used to output log4cplus internal debug + * statements. Output goes to std::cout. + */ + void debug(const log4cplus::tstring& msg) const; + void debug(tchar const * msg) const; + + /** + * This method is used to output log4cplus internal error + * statements. There is no way to disable error + * statements. Output goes to + * std::cerr. Optionally, this method can + * throw std::runtime_error exception too. + */ + void error(const log4cplus::tstring& msg, bool throw_flag = false) const; + void error(tchar const * msg, bool throw_flag = false) const; + + /** + * This method is used to output log4cplus internal warning + * statements. There is no way to disable warning statements. + * Output goes to std::cerr. + */ + void warn(const log4cplus::tstring& msg) const; + void warn(tchar const * msg) const; + + // Public ctor and dtor to be used only by internal::DefaultContext. + LogLog(); + virtual ~LogLog(); + + private: + enum TriState + { + TriUndef = -1, + TriFalse, + TriTrue + }; + + template + LOG4CPLUS_PRIVATE + void logging_worker (tostream & os, + bool (LogLog:: * cond) () const, tchar const *, + StringType const &, bool throw_flag = false) const; + + LOG4CPLUS_PRIVATE static void set_tristate_from_env (TriState *, + tchar const * envvar); + + LOG4CPLUS_PRIVATE bool get_quiet_mode () const; + LOG4CPLUS_PRIVATE bool get_not_quiet_mode () const; + LOG4CPLUS_PRIVATE bool get_debug_mode () const; + + // Data + mutable TriState debugEnabled; + mutable TriState quietMode; + thread::Mutex mutex; + + LOG4CPLUS_PRIVATE LogLog(const LogLog&); + LOG4CPLUS_PRIVATE LogLog & operator = (LogLog const &); + }; + + LOG4CPLUS_EXPORT LogLog & getLogLog (); + + } // end namespace helpers +} // end namespace log4cplus + + +#endif // LOG4CPLUS_HELPERS_LOGLOG + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/logloguser.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/logloguser.h new file mode 100644 index 0000000..11b3f5e --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/logloguser.h @@ -0,0 +1,64 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: logloguser.h +// Created: 6/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_LOGLOG_USER +#define LOG4CPLUS_HELPERS_LOGLOG_USER + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + + +namespace log4cplus { + namespace helpers { + // forward declarations + class LogLog; + + /** + * This class used to simplify the use of the LogLog class. Any class + * that uses the LogLog class should extend this class and retrieve + * their reference to LogLog using the method provided. + */ + class LOG4CPLUS_EXPORT LogLogUser + { + public: + // ctor and dtor + LogLogUser(); + LogLogUser(const LogLogUser&); + virtual ~LogLogUser(); + + // public methods + LogLog& getLogLog() const; + + // operators + LogLogUser& operator=(const LogLogUser& rhs); + }; + + } // end namespace helpers +} // end namespace log4cplus + + +#endif // LOG4CPLUS_HELPERS_LOGLOG_USER + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/pointer.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/pointer.h new file mode 100644 index 0000000..0b1b6fe --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/pointer.h @@ -0,0 +1,191 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: pointer.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +// Note: Some of this code uses ideas from "More Effective C++" by Scott +// Myers, Addison Wesley Longmain, Inc., (c) 1996, Chapter 29, pp. 183-213 +// + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_POINTERS_HEADER_ +#define LOG4CPLUS_HELPERS_POINTERS_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#if ! defined (LOG4CPLUS_SINGLE_THREADED) \ + && defined (LOG4CPLUS_HAVE_CXX11_ATOMICS) +#include +#endif + + +namespace log4cplus { + namespace helpers { + + /****************************************************************************** + * Class SharedObject (from pp. 204-205) * + ******************************************************************************/ + + class LOG4CPLUS_EXPORT SharedObject + { + public: + void addReference() const; + void removeReference() const; + + protected: + // Ctor + SharedObject() + : access_mutex() + , count(0) + { } + + SharedObject(const SharedObject&) + : access_mutex() + , count(0) + { } + + // Dtor + virtual ~SharedObject(); + + // Operators + SharedObject& operator=(const SharedObject&) { return *this; } + + public: + thread::Mutex access_mutex; + + private: +#if defined (LOG4CPLUS_SINGLE_THREADED) + typedef unsigned count_type; +#elif defined (LOG4CPLUS_HAVE_CXX11_ATOMICS) + typedef std::atomic count_type; +#elif defined (_WIN32) || defined (__CYGWIN__) + typedef long count_type; +#else + typedef unsigned count_type; +#endif + mutable count_type count; + }; + + + /****************************************************************************** + * Template Class SharedObjectPtr (from pp. 203, 206) * + ******************************************************************************/ + template + class SharedObjectPtr + { + public: + // Ctor + explicit + SharedObjectPtr(T* realPtr = 0) + : pointee(realPtr) + { + addref (); + } + + SharedObjectPtr(const SharedObjectPtr& rhs) + : pointee(rhs.pointee) + { + addref (); + } + +#if defined (LOG4CPLUS_HAVE_RVALUE_REFS) + SharedObjectPtr(SharedObjectPtr && rhs) + : pointee (std::move (rhs.pointee)) + { + rhs.pointee = 0; + } + + SharedObjectPtr & operator = (SharedObjectPtr && rhs) + { + rhs.swap (*this); + return *this; + } +#endif + + // Dtor + ~SharedObjectPtr() + { + if (pointee) + pointee->removeReference(); + } + + // Operators + bool operator==(const SharedObjectPtr& rhs) const { return (pointee == rhs.pointee); } + bool operator!=(const SharedObjectPtr& rhs) const { return (pointee != rhs.pointee); } + bool operator==(const T* rhs) const { return (pointee == rhs); } + bool operator!=(const T* rhs) const { return (pointee != rhs); } + T* operator->() const {assert (pointee); return pointee; } + T& operator*() const {assert (pointee); return *pointee; } + + SharedObjectPtr& operator=(const SharedObjectPtr& rhs) + { + return this->operator = (rhs.pointee); + } + + SharedObjectPtr& operator=(T* rhs) + { + SharedObjectPtr (rhs).swap (*this); + return *this; + } + + // Methods + T* get() const { return pointee; } + + void swap (SharedObjectPtr & other) throw () + { + std::swap (pointee, other.pointee); + } + + typedef T * (SharedObjectPtr:: * unspec_bool_type) () const; + operator unspec_bool_type () const + { + return pointee ? &SharedObjectPtr::get : 0; + } + + bool operator ! () const + { + return ! pointee; + } + + private: + // Methods + void addref() const + { + if (pointee) + pointee->addReference(); + } + + // Data + T* pointee; + }; + + } // end namespace helpers +} // end namespace log4cplus + + +#endif // LOG4CPLUS_HELPERS_POINTERS_HEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/property.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/property.h new file mode 100644 index 0000000..e97c6d4 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/property.h @@ -0,0 +1,162 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: property.h +// Created: 2/2002 +// Author: Tad E. Smith +// +// +// Copyright 2002-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_PROPERTY_HEADER_ +#define LOG4CPLUS_HELPERS_PROPERTY_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + + +namespace log4cplus { + namespace helpers { + + //! \sa log4cplus::PropertyConfigurator + class LOG4CPLUS_EXPORT Properties { + public: + enum PFlags + { + // These encoding related options occupy 2 bits of the flags + // and are mutually exclusive. These flags are synchronized + // with PCFlags in PropertyConfigurator. + + fEncodingShift = 3 + , fEncodingMask = 0x3 + , fUnspecEncoding = (0 << fEncodingShift) +#if defined (LOG4CPLUS_HAVE_CODECVT_UTF8_FACET) && defined (UNICODE) + , fUTF8 = (1 << fEncodingShift) +#endif +#if (defined (LOG4CPLUS_HAVE_CODECVT_UTF16_FACET) || defined (_WIN32)) \ + && defined (UNICODE) + , fUTF16 = (2 << fEncodingShift) +#endif +#if defined (LOG4CPLUS_HAVE_CODECVT_UTF32_FACET) && defined (UNICODE) + , fUTF32 = (3 << fEncodingShift) +#endif + }; + + Properties(); + explicit Properties(log4cplus::tistream& input); + explicit Properties(const log4cplus::tstring& inputFile, unsigned flags = 0); + virtual ~Properties(); + + // constants + static const tchar PROPERTIES_COMMENT_CHAR; + + // methods + /** + * Tests to see if key can be found in this map. + */ + bool exists(const log4cplus::tstring& key) const; + bool exists(tchar const * key) const; + + /** + * Returns the number of entries in this map. + */ + std::size_t size() const + { + return data.size(); + } + + /** + * Searches for the property with the specified key in this property + * list. If the key is not found in this property list, the default + * property list, and its defaults, recursively, are then checked. + * The method returns null if the property is not found. + */ + log4cplus::tstring const & getProperty(const log4cplus::tstring& key) const; + log4cplus::tstring const & getProperty(tchar const * key) const; + + /** + * Searches for the property with the specified key in this property + * list. If the key is not found in this property list, the default + * property list, and its defaults, recursively, are then checked. + * The method returns the default value argument if the property is + * not found. + */ + log4cplus::tstring getProperty(const log4cplus::tstring& key, + const log4cplus::tstring& defaultVal) const; + + /** + * Returns all the keys in this property list. + */ + std::vector propertyNames() const; + + /** + * Inserts value into this map indexed by key. + */ + void setProperty(const log4cplus::tstring& key, const log4cplus::tstring& value); + + /** + * Removed the property index by key from this map. + */ + bool removeProperty(const log4cplus::tstring& key); + + /** + * Returns a subset of the "properties" whose keys start with + * "prefix". The returned "properties" have "prefix" trimmed from + * their keys. + */ + Properties getPropertySubset(const log4cplus::tstring& prefix) const; + + bool getInt (int & val, log4cplus::tstring const & key) const; + bool getUInt (unsigned & val, log4cplus::tstring const & key) const; + bool getLong (long & val, log4cplus::tstring const & key) const; + bool getULong (unsigned long & val, log4cplus::tstring const & key) const; + bool getBool (bool & val, log4cplus::tstring const & key) const; + + protected: + // Types + typedef std::map StringMap; + + // Methods + void init(log4cplus::tistream& input); + + // Data + StringMap data; + unsigned flags; + + private: + template + log4cplus::tstring const & get_property_worker ( + StringType const & key) const; + + template + bool get_type_val_worker (ValType & val, + log4cplus::tstring const & key) const; + }; + } // end namespace helpers + +} + + +#endif // LOG4CPLUS_HELPERS_PROPERTY_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/queue.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/queue.h new file mode 100644 index 0000000..eefaf2f --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/queue.h @@ -0,0 +1,158 @@ +// -*- C++ -*- +// Copyright (C) 2009-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_HELPERS_QUEUE_H +#define LOG4CPLUS_HELPERS_QUEUE_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + +#include +#include +#include +#include + + +namespace log4cplus { namespace thread { + + +//! Single consumer, multiple producers queue. +class LOG4CPLUS_EXPORT Queue + : public virtual helpers::SharedObject +{ +public: + //! Type of the state flags field. + typedef unsigned flags_type; + + //! Queue storage type. + typedef std::deque queue_storage_type; + + Queue (unsigned len = 100); + virtual ~Queue (); + + // Producers' methods. + + //! Puts event ev into queue, sets QUEUE flag and + //! sets internal event object into signaled state. If the EXIT + //! flags is already set upon entering the function, nothing is + //! inserted into the queue. The function can block on internal + //! semaphore if the queue has reached maximal allowed + //! length. Calling thread is unblocked either by consumer thread + //! removing item from queue or by any other thread calling + //! signal_exit(). + //! + //! \param ev spi::InternalLoggingEvent to be put into the queue. + //! \return Flags. + flags_type put_event (spi::InternalLoggingEvent const & ev); + + //! Sets EXIT flag and DRAIN flag and sets internal event object + //! into signaled state. + //! \param drain If true, DRAIN flag will be set, otherwise unset. + //! \return Flags, ERROR_BIT can be set upon error. + flags_type signal_exit (bool drain = true); + + // Consumer's methods. + + //! The get_events() function is used by queue's consumer. It + //! fills buf argument and sets EVENT flag in return + //! value. If EXIT flag is already set in flags member upon + //! entering the function then depending on DRAIN flag it either + //! fills buf argument or does not fill the argument, + //! if the queue is non-empty. The function blocks by waiting for + //! internal event object to be signaled if the queue is empty, + //! unless EXIT flag is set. The calling thread is unblocked when + //! items are added into the queue or when exit is signaled using + //! the signal_exit() function. + //! + //! + //! Upon error, return value has one of the error flags set. + //! + //! \param buf Pointer to storage of spi::InternalLoggingEvent + //! instances to be filled from queue. + //! \return Flags. + flags_type get_events (queue_storage_type * buf); + + //! Possible state flags. + enum Flags + { + //! EVENT flag is set in return value of get_event() call if + //! the ev argument is filled with event from the queue. + EVENT = 0x0001, + + //! QUEUE flag is set by producers when they put item into the + //! queue. + QUEUE = 0x0002, + + //! EXIT flag is set by signal_exit() call, signaling that the + //! queue worker thread should end itself. + EXIT = 0x0004, + + //! When DRAIN flag is set together with EXIT flag, the queue + //! worker thread will first drain the queue before exiting. + DRAIN = 0x0008, + + //! ERROR_BIT signals error. + ERROR_BIT = 0x0010, + + //! ERROR_AFTER signals error that has occured after queue has + //! already been touched. + ERROR_AFTER = 0x0020 + }; + +protected: + //! Queue storage. + queue_storage_type queue; + + //! Mutex protecting queue and flags. + Mutex mutex; + + //! Event on which consumer can wait if it finds queue empty. + ManualResetEvent ev_consumer; + + //! Semaphore that limits the queue length. + Semaphore sem; + + //! State flags. + flags_type flags; + +private: + Queue (Queue const &); + Queue & operator = (Queue const &); +}; + + +typedef helpers::SharedObjectPtr QueuePtr; + + +} } // namespace log4cplus { namespace thread { + + +#endif // LOG4CPLUS_SINGLE_THREADED + +#endif // LOG4CPLUS_HELPERS_QUEUE_H diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/sleep.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/sleep.h new file mode 100644 index 0000000..f3c5636 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/sleep.h @@ -0,0 +1,43 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: sleep.h +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_SLEEP_HEADER_ +#define LOG4CPLUS_HELPERS_SLEEP_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + + +namespace log4cplus { + namespace helpers { + LOG4CPLUS_EXPORT void sleep(unsigned long secs, + unsigned long nanosecs = 0); + LOG4CPLUS_EXPORT void sleepmillis(unsigned long millis); + } // end namespace helpers +} // end namespace log4cplus + +#endif // LOG4CPLUS_HELPERS_SLEEP_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/snprintf.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/snprintf.h new file mode 100644 index 0000000..f0dc949 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/snprintf.h @@ -0,0 +1,62 @@ +// -*- C++ -*- +// Copyright (C) 2010-2013, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_HELPERS_SNPRINTF_H +#define LOG4CPLUS_HELPERS_SNPRINTF_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include + + +namespace log4cplus { namespace helpers { + + +class LOG4CPLUS_EXPORT snprintf_buf +{ +public: + snprintf_buf (); + + tchar const * print (tchar const * fmt, ...) + LOG4CPLUS_FORMAT_ATTRIBUTE (__printf__, 2, 3); + + int print_va_list (tchar const * & str, tchar const * fmt, std::va_list) + LOG4CPLUS_FORMAT_ATTRIBUTE (__printf__, 3, 0); + +private: + std::vector buf; +}; + + +} } // namespace log4cplus { namespace helpers + + + +#endif // LOG4CPLUS_HELPERS_SNPRINTF_H diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/socket.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/socket.h new file mode 100644 index 0000000..eb52d84 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/socket.h @@ -0,0 +1,141 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: socket.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_SOCKET_HEADER_ +#define LOG4CPLUS_HELPERS_SOCKET_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus { + namespace helpers { + + enum SocketState { ok, + not_opened, + bad_address, + connection_failed, + broken_pipe, + invalid_access_mode, + message_truncated, + accept_interrupted + }; + + typedef std::ptrdiff_t SOCKET_TYPE; + + extern LOG4CPLUS_EXPORT SOCKET_TYPE const INVALID_SOCKET_VALUE; + + class LOG4CPLUS_EXPORT AbstractSocket { + public: + // ctor and dtor + AbstractSocket(); + AbstractSocket(SOCKET_TYPE sock, SocketState state, int err); + AbstractSocket(const AbstractSocket&); + virtual ~AbstractSocket() = 0; + + // methods + /// Close socket + virtual void close(); + virtual bool isOpen() const; + virtual void shutdown(); + AbstractSocket& operator=(const AbstractSocket& rhs); + + protected: + // Methods + virtual void copy(const AbstractSocket& rhs); + + // Data + SOCKET_TYPE sock; + SocketState state; + int err; + }; + + + + /** + * This class implements client sockets (also called just "sockets"). + * A socket is an endpoint for communication between two machines. + */ + class LOG4CPLUS_EXPORT Socket : public AbstractSocket { + public: + // ctor and dtor + Socket(); + Socket(SOCKET_TYPE sock, SocketState state, int err); + Socket(const tstring& address, unsigned short port, bool udp = false); + virtual ~Socket(); + + // methods + virtual bool read(SocketBuffer& buffer); + virtual bool write(const SocketBuffer& buffer); + virtual bool write(const std::string & buffer); + }; + + + + /** + * This class implements server sockets. A server socket waits for + * requests to come in over the network. It performs some operation + * based on that request, and then possibly returns a result to the + * requester. + */ + class LOG4CPLUS_EXPORT ServerSocket : public AbstractSocket { + public: + // ctor and dtor + ServerSocket(unsigned short port); + virtual ~ServerSocket(); + + Socket accept(); + void interruptAccept (); + + protected: + std::ptrdiff_t interruptHandles[2]; + }; + + + LOG4CPLUS_EXPORT SOCKET_TYPE openSocket(unsigned short port, SocketState& state); + LOG4CPLUS_EXPORT SOCKET_TYPE connectSocket(const log4cplus::tstring& hostn, + unsigned short port, bool udp, + SocketState& state); + LOG4CPLUS_EXPORT SOCKET_TYPE acceptSocket(SOCKET_TYPE sock, SocketState& state); + LOG4CPLUS_EXPORT int closeSocket(SOCKET_TYPE sock); + LOG4CPLUS_EXPORT int shutdownSocket(SOCKET_TYPE sock); + + LOG4CPLUS_EXPORT long read(SOCKET_TYPE sock, SocketBuffer& buffer); + LOG4CPLUS_EXPORT long write(SOCKET_TYPE sock, + const SocketBuffer& buffer); + LOG4CPLUS_EXPORT long write(SOCKET_TYPE sock, + const std::string & buffer); + + LOG4CPLUS_EXPORT tstring getHostname (bool fqdn); + LOG4CPLUS_EXPORT int setTCPNoDelay (SOCKET_TYPE, bool); + + } // end namespace helpers +} // end namespace log4cplus + +#endif // LOG4CPLUS_HELPERS_SOCKET_HEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/socketbuffer.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/socketbuffer.h new file mode 100644 index 0000000..f8b9613 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/socketbuffer.h @@ -0,0 +1,79 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: socketbuffer.h +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_SOCKET_BUFFER_HEADER_ +#define LOG4CPLUS_HELPERS_SOCKET_BUFFER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + + +namespace log4cplus { +namespace helpers { + +/** + * + */ +class LOG4CPLUS_EXPORT SocketBuffer +{ +public: + explicit SocketBuffer(std::size_t max); + virtual ~SocketBuffer(); + + char *getBuffer() const { return buffer; } + std::size_t getMaxSize() const { return maxsize; } + std::size_t getSize() const { return size; } + void setSize(std::size_t s) { size = s; } + std::size_t getPos() const { return pos; } + + unsigned char readByte(); + unsigned short readShort(); + unsigned int readInt(); + tstring readString(unsigned char sizeOfChar); + + void appendByte(unsigned char val); + void appendShort(unsigned short val); + void appendInt(unsigned int val); + void appendString(const tstring& str); + void appendBuffer(const SocketBuffer& buffer); + +private: + // Data + std::size_t maxsize; + std::size_t size; + std::size_t pos; + char *buffer; + + SocketBuffer(SocketBuffer const & rhs); + SocketBuffer& operator= (SocketBuffer const& rhs); +}; + +} // end namespace helpers +} // end namespace log4cplus + +#endif // LOG4CPLUS_HELPERS_SOCKET_HEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/stringhelper.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/stringhelper.h new file mode 100644 index 0000000..56d150c --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/stringhelper.h @@ -0,0 +1,212 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: stringhelper.h +// Created: 3/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_ +#define LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#include +#include + + +namespace log4cplus { + namespace helpers { + + /** + * Returns s in upper case. + */ + LOG4CPLUS_EXPORT log4cplus::tstring toUpper(const log4cplus::tstring& s); + + + /** + * Returns s in lower case. + */ + LOG4CPLUS_EXPORT log4cplus::tstring toLower(const log4cplus::tstring& s); + + + /** + * Tokenize s using c as the delimiter and + * put the resulting tokens in _result. If + * collapseTokens is false, multiple adjacent delimiters + * will result in zero length tokens. + * + * Example: + *
+         *   string s = // Set string with '.' as delimiters
+         *   list tokens;
+         *   tokenize(s, '.', back_insert_iterator >(tokens));
+         * 
+ */ + template + inline + void + tokenize(const StringType& s, typename StringType::value_type c, + OutputIter result, bool collapseTokens = true) + { + typedef typename StringType::size_type size_type; + size_type const slen = s.length(); + size_type first = 0; + size_type i = 0; + for (i=0; i < slen; ++i) + { + if (s[i] == c) + { + *result = StringType (s, first, i - first); + ++result; + if (collapseTokens) + while (i+1 < slen && s[i+1] == c) + ++i; + first = i + 1; + } + } + if (first != i) + *result = StringType (s, first, i - first); + } + + + template + struct ConvertIntegerToStringHelper; + + + template + struct ConvertIntegerToStringHelper + { + static inline + void + step1 (tchar * & it, intType & value) + { + // The sign of the result of the modulo operator is + // implementation defined. That's why we work with + // positive counterpart instead. Also, in twos + // complement arithmetic the smallest negative number + // does not have positive counterpart; the range is + // asymetric. That's why we handle the case of value + // == min() specially here. + if (value == (std::numeric_limits::min) ()) + { + intType const r = value / 10; + intType const a = (-r) * 10; + intType const mod = -(a + value); + value = -r; + + *(it - 1) = static_cast(LOG4CPLUS_TEXT('0') + mod); + --it; + } + else + value = -value; + } + + static inline + bool + is_negative (intType val) + { + return val < 0; + } + }; + + + template + struct ConvertIntegerToStringHelper + { + static inline + void + step1 (tchar * &, intType &) + { + // This will never be called for unsigned types. + } + + static inline + bool + is_negative (intType) + { + return false; + } + }; + + + template + inline + void + convertIntegerToString (tstring & str, intType value) + { + typedef std::numeric_limits intTypeLimits; + typedef ConvertIntegerToStringHelper + HelperType; + + tchar buffer[intTypeLimits::digits10 + 2]; + // We define buffer_size from buffer using sizeof operator + // to appease HP aCC compiler. + const std::size_t buffer_size = sizeof (buffer) / sizeof (tchar); + + tchar * it = &buffer[buffer_size]; + tchar const * const buf_end = it; + + if (value == 0) + { + --it; + *it = LOG4CPLUS_TEXT('0'); + } + + bool const negative = HelperType::is_negative (value); + if (negative) + HelperType::step1 (it, value); + + for (; value != 0; --it) + { + intType mod = value % 10; + value = value / 10; + *(it - 1) = static_cast(LOG4CPLUS_TEXT('0') + mod); + } + + if (negative) + { + --it; + *it = LOG4CPLUS_TEXT('-'); + } + + str.assign (static_cast(it), buf_end); + } + + + template + inline + tstring + convertIntegerToString (intType value) + { + tstring result; + convertIntegerToString (result, value); + return result; + } + + } // namespace helpers + +} // namespace log4cplus + +#endif // LOG4CPLUS_HELPERS_STRINGHELPER_HEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/thread-config.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/thread-config.h new file mode 100644 index 0000000..4f9e063 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/thread-config.h @@ -0,0 +1,61 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: thread-config.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_THREAD_CONFIG_HEADER_ +#define LOG4CPLUS_HELPERS_THREAD_CONFIG_HEADER_ + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (LOG4CPLUS_USE_PTHREADS) +# if defined (__APPLE__) +# define LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE +# endif + +#elif defined(LOG4CPLUS_USE_WIN32_THREADS) +# if defined (_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 +# define LOG4CPLUS_USE_SRW_LOCK +# else +# define LOG4CPLUS_POOR_MANS_SHAREDMUTEX +# endif +# undef LOG4CPLUS_HAVE_TLS_SUPPORT +# undef LOG4CPLUS_THREAD_LOCAL_VAR +# if defined (_MSC_VER) && _WIN32_WINNT >= 0x0600 +// The __declspec(thread) functionality is not compatible with LoadLibrary(). +// For more information why see and "Windows and TLS" note in README. +// . +# define LOG4CPLUS_HAVE_TLS_SUPPORT 1 +# define LOG4CPLUS_THREAD_LOCAL_VAR __declspec(thread) +# endif + +#elif defined(LOG4CPLUS_SINGLE_THREADED) +# undef LOG4CPLUS_HAVE_TLS_SUPPORT +# undef LOG4CPLUS_THREAD_LOCAL_VAR + +#else +# error "You Must define a Threading model" + +#endif + + +#endif // LOG4CPLUS_HELPERS_THREAD_CONFIG_HEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/timehelper.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/timehelper.h new file mode 100644 index 0000000..06b3281 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/helpers/timehelper.h @@ -0,0 +1,179 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: timehelper.h +// Created: 6/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HELPERS_TIME_HELPER_HEADER_ +#define LOG4CPLUS_HELPERS_TIME_HELPER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#if defined (LOG4CPLUS_HAVE_TIME_H) +#include +#endif + +#include + + +namespace log4cplus { + +namespace helpers { + + +using std::time_t; +using std::tm; + + +/** + * This class represents a Epoch time with microsecond accuracy. + */ +class LOG4CPLUS_EXPORT Time { +public: + Time(); + Time(time_t tv_sec, long tv_usec); + explicit Time(time_t time); + + /** + * Returns the current time using the gettimeofday() + * method if it is available on the current platform. (Not on + * WIN32.) + */ + static Time gettimeofday(); + + // Methods + /** + * Returns seconds value. + */ + time_t sec() const { return tv_sec; } + + /** + * Returns microseconds value. + */ + long usec() const { return tv_usec; } + + /** + * Sets the seconds value. + */ + void sec(time_t s) { tv_sec = s; } + + /** + * Sets the microseconds value. + */ + void usec(long us) { tv_usec = us; } + + /** + * Sets this Time using the mktime function. + */ + time_t setTime(tm* t); + + /** + * Returns this Time as a time_t value. + */ + time_t getTime() const LOG4CPLUS_ATTRIBUTE_PURE; + + /** + * Populates tm using the gmtime() + * function. + */ + void gmtime(tm* t) const; + + /** + * Populates tm using the localtime() + * function. + */ + void localtime(tm* t) const; + + /** + * Returns a string with a "formatted time" specified by + * fmt. It used the strftime() + * function to do this. + * + * Look at your platform's strftime() documentation + * for the formatting options available. + * + * The following additional options are provided:
+ * %q - 3 character field that provides milliseconds + * %Q - 7 character field that provides fractional + * milliseconds. + */ + log4cplus::tstring getFormattedTime(const log4cplus::tstring& fmt, + bool use_gmtime = false) const; + + // Operators + Time& operator+=(const Time& rhs); + Time& operator-=(const Time& rhs); + Time& operator/=(long rhs); + Time& operator*=(long rhs); + +private: + // Data + time_t tv_sec; /* seconds */ + long tv_usec; /* microseconds */ +}; + + +LOG4CPLUS_EXPORT const log4cplus::helpers::Time operator+ + (const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs); +LOG4CPLUS_EXPORT const log4cplus::helpers::Time operator- + (const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs); +LOG4CPLUS_EXPORT const log4cplus::helpers::Time operator/ + (const log4cplus::helpers::Time& lhs, + long rhs); +LOG4CPLUS_EXPORT const log4cplus::helpers::Time operator* + (const log4cplus::helpers::Time& lhs, + long rhs); + +LOG4CPLUS_EXPORT bool operator<(const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs) + LOG4CPLUS_ATTRIBUTE_PURE; +LOG4CPLUS_EXPORT bool operator<=(const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs) + LOG4CPLUS_ATTRIBUTE_PURE; + +LOG4CPLUS_EXPORT bool operator>(const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs) + LOG4CPLUS_ATTRIBUTE_PURE; +LOG4CPLUS_EXPORT bool operator>=(const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs) + LOG4CPLUS_ATTRIBUTE_PURE; + +LOG4CPLUS_EXPORT bool operator==(const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs) + LOG4CPLUS_ATTRIBUTE_PURE; +LOG4CPLUS_EXPORT bool operator!=(const log4cplus::helpers::Time& lhs, + const log4cplus::helpers::Time& rhs) + LOG4CPLUS_ATTRIBUTE_PURE; + +} // namespace helpers + +} // namespace log4cplus + + +#endif // LOG4CPLUS_HELPERS_TIME_HELPER_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/hierarchy.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/hierarchy.h new file mode 100644 index 0000000..2c023a9 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/hierarchy.h @@ -0,0 +1,325 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: hierarchy.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HIERARCHY_HEADER_ +#define LOG4CPLUS_HIERARCHY_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include + + +namespace log4cplus { + // Forward Declarations + class HierarchyLocker; + + /** + * This class is specialized in retrieving loggers by name and + * also maintaining the logger hierarchy. + * + * The casual user should not have to deal with this class + * directly. However, if you are in an environment where + * multiple applications run in the same process, then read on. + * + * The structure of the logger hierarchy is maintained by the + * {@link #getInstance} method. The hierarchy is such that children + * link to their parent but parents do not have any pointers to their + * children. Moreover, loggers can be instantiated in any order, in + * particular descendant before ancestor. + * + * In case a descendant is created before a particular ancestor, + * then it creates a provision node for the ancestor and adds itself + * to the provision node. Other descendants of the same ancestor add + * themselves to the previously created provision node. + */ + class LOG4CPLUS_EXPORT Hierarchy + { + public: + // DISABLE_OFF should be set to a value lower than all possible + // priorities. + static const LogLevel DISABLE_OFF; + static const LogLevel DISABLE_OVERRIDE; + + // Ctors + /** + * Create a new Logger hierarchy. + */ + Hierarchy(); + + // Dtor + virtual ~Hierarchy(); + + // Methods + /** + * This call will clear all logger definitions from the internal + * hashtable. Invoking this method will irrevocably mess up the + * logger hierarchy. + * + * You should really know what you are doing before + * invoking this method. + */ + virtual void clear(); + + /** + * Returns true if the named logger exists + * (in the default hierarchy). + * + * @param name The name of the logger to search for. + */ + virtual bool exists(const log4cplus::tstring& name); + + /** + * Similar to {@link #disable(LogLevel)} except that the LogLevel + * argument is given as a log4cplus::tstring. + */ + virtual void disable(const log4cplus::tstring& loglevelStr); + + /** + * Disable all logging requests of LogLevel equal to or + * below the ll parameter p, for + * all loggers in this hierarchy. Logging requests of + * higher LogLevel then p remain unaffected. + * + * Nevertheless, if the + * BasicConfigurator::DISABLE_OVERRIDE_KEY property is set to + * true, then logging requests are evaluated as usual. + * + * The "disable" family of methods are there for speed. They + * allow printing methods such as debug, info, etc. to return + * immediately after an integer comparison without walking the + * logger hierarchy. In most modern computers an integer + * comparison is measured in nanoseconds where as a logger walk is + * measured in units of microseconds. + */ + virtual void disable(LogLevel ll); + + /** + * Disable all logging requests regardless of logger and LogLevel. + * This method is equivalent to calling {@link #disable} with the + * argument FATAL_LOG_LEVEL, the highest possible LogLevel. + */ + virtual void disableAll(); + + /** + * Disable all Debug logging requests regardless of logger. + * This method is equivalent to calling {@link #disable} with the + * argument DEBUG_LOG_LEVEL. + */ + virtual void disableDebug(); + + /** + * Disable all Info logging requests regardless of logger. + * This method is equivalent to calling {@link #disable} with the + * argument INFO_LOG_LEVEL. + */ + virtual void disableInfo(); + + /** + * Undoes the effect of calling any of {@link #disable}, {@link + * #disableAll}, {@link #disableDebug} and {@link #disableInfo} + * methods. More precisely, invoking this method sets the Logger + * class internal variable called disable to its + * default "off" value. + */ + virtual void enableAll(); + + /** + * Return a new logger instance named as the first parameter using + * the default factory. + * + * If a logger of that name already exists, then it will be + * returned. Otherwise, a new logger will be instantiated and + * then linked with its existing ancestors as well as children. + * + * @param name The name of the logger to retrieve. + */ + virtual Logger getInstance(const log4cplus::tstring& name); + + /** + * Return a new logger instance named as the first parameter using + * factory. + * + * If a logger of that name already exists, then it will be + * returned. Otherwise, a new logger will be instantiated by the + * factory parameter and linked with its existing + * ancestors as well as children. + * + * @param name The name of the logger to retrieve. + * @param factory The factory that will make the new logger instance. + */ + virtual Logger getInstance(const log4cplus::tstring& name, spi::LoggerFactory& factory); + + /** + * Returns all the currently defined loggers in this hierarchy. + * + * The root logger is not included in the returned list. + */ + virtual LoggerList getCurrentLoggers(); + + /** + * Is the LogLevel specified by level enabled? + */ + virtual bool isDisabled(LogLevel level); + + /** + * Get the root of this hierarchy. + */ + virtual Logger getRoot() const; + + /** + * Reset all values contained in this hierarchy instance to their + * default. This removes all appenders from all loggers, sets + * the LogLevel of all non-root loggers to NOT_SET_LOG_LEVEL, + * sets their additivity flag to true and sets the LogLevel + * of the root logger to DEBUG_LOG_LEVEL. Moreover, message disabling + * is set its default "off" value. + * + * Existing loggers are not removed. They are just reset. + * + * This method should be used sparingly and with care as it will + * block all logging until it is completed.

+ */ + virtual void resetConfiguration(); + + /** + * Set the default LoggerFactory instance. + */ + virtual void setLoggerFactory(std::auto_ptr factory); + + /** + * Returns the default LoggerFactory instance. + */ + virtual spi::LoggerFactory* getLoggerFactory(); + + /** + * Shutting down a hierarchy will safely close and remove + * all appenders in all loggers including the root logger. + * + * Some appenders such as SocketAppender need to be closed before the + * application exits. Otherwise, pending logging events might be + * lost. + * + * The shutdown method is careful to close nested + * appenders before closing regular appenders. This is allows + * configurations where a regular appender is attached to a logger + * and again to a nested appender. + */ + virtual void shutdown(); + + private: + // Types + typedef std::vector ProvisionNode; + typedef std::map ProvisionNodeMap; + typedef std::map LoggerMap; + + // Methods + /** + * This is the implementation of the getInstance() method. + * NOTE: This method does not lock the hashtable_mutex. + */ + LOG4CPLUS_PRIVATE + virtual Logger getInstanceImpl(const log4cplus::tstring& name, + spi::LoggerFactory& factory); + + /** + * This is the implementation of the getCurrentLoggers(). + * NOTE: This method does not lock the hashtable_mutex. + */ + LOG4CPLUS_PRIVATE + virtual void initializeLoggerList(LoggerList& list) const; + + /** + * This method loops through all the *potential* parents of + * logger'. There 3 possible cases: + * + * 1) No entry for the potential parent of 'logger' exists + * + * We create a ProvisionNode for this potential parent and insert + * 'logger' in that provision node. + * + * 2) There is an entry of type Logger for the potential parent. + * + * The entry is 'logger's nearest existing parent. We update logger's + * parent field with this entry. We also break from the loop + * because updating our parent's parent is our parent's + * responsibility. + * + * 3) There entry is of type ProvisionNode for this potential parent. + * + * We add 'logger' to the list of children for this potential parent. + */ + LOG4CPLUS_PRIVATE void updateParents(Logger const & logger); + + /** + * We update the links for all the children that placed themselves + * in the provision node 'pn'. The second argument 'logger' is a + * reference for the newly created Logger, parent of all the + * children in 'pn' + * + * We loop on all the children 'c' in 'pn': + * + * If the child 'c' has been already linked to a child of + * 'logger' then there is no need to update 'c'. + * + * Otherwise, we set logger's parent field to c's parent and set + * c's parent field to logger. + */ + LOG4CPLUS_PRIVATE void updateChildren(ProvisionNode& pn, + Logger const & logger); + + // Data + thread::Mutex hashtable_mutex; + std::auto_ptr defaultFactory; + ProvisionNodeMap provisionNodes; + LoggerMap loggerPtrs; + Logger root; + + int disableValue; + + bool emittedNoAppenderWarning; + + // Disallow copying of instances of this class + Hierarchy(const Hierarchy&); + Hierarchy& operator=(const Hierarchy&); + + // Friends + friend class log4cplus::spi::LoggerImpl; + friend class log4cplus::HierarchyLocker; + }; + + + LOG4CPLUS_EXPORT Hierarchy & getDefaultHierarchy (); + + +} // end namespace log4cplus + +#endif // LOG4CPLUS_HIERARCHY_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/hierarchylocker.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/hierarchylocker.h new file mode 100644 index 0000000..ed27664 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/hierarchylocker.h @@ -0,0 +1,80 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: hierarchylocker.h +// Created: 8/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_HIERARCHY_LOCKER_HEADER_ +#define LOG4CPLUS_HIERARCHY_LOCKER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include + + +namespace log4cplus +{ + + class Hierarchy; + + + /** + * This is used to lock a Hierarchy. The dtor unlocks the Hierarchy. + */ + class LOG4CPLUS_EXPORT HierarchyLocker { + public: + // ctor & dtor + HierarchyLocker(Hierarchy& h); + ~HierarchyLocker(); + + /** + * Calls the resetConfiguration() method on the locked Hierarchy. + */ + void resetConfiguration(); + + /** + * Calls the getInstance() method on the locked Hierarchy. + */ + Logger getInstance(const log4cplus::tstring& name); + + /** + * Calls the getInstance() method on the locked Hierarchy. + */ + Logger getInstance(const log4cplus::tstring& name, spi::LoggerFactory& factory); + + void addAppender(Logger &logger, log4cplus::SharedAppenderPtr& appender); + + private: + // Data + Hierarchy& h; + log4cplus::thread::MutexGuard hierarchyLocker; + LoggerList loggerList; + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_HIERARCHY_LOCKER_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/internal/cygwin-win32.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/internal/cygwin-win32.h new file mode 100644 index 0000000..ab5a744 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/internal/cygwin-win32.h @@ -0,0 +1,54 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: cygwin-win32.h +// Created: 7/2011 +// Author: Vaclav Zeman +// +// Copyright (C) 2011-2013, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#if ! defined (LOG4CPLUS_CONFIG_CYGWIN_WIN32_H) +#define LOG4CPLUS_CONFIG_CYGWIN_WIN32_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (__CYGWIN__) + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + + +namespace log4cplus { namespace cygwin { + +unsigned long get_current_win32_thread_id (); + +} } // namespace log4cplus { namespace cygwin { + + +#endif // defined (__CYGWIN__) +#endif // LOG4CPLUS_CONFIG_CYGWIN_WIN32_H diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/internal/env.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/internal/env.h new file mode 100644 index 0000000..8c9a364 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/internal/env.h @@ -0,0 +1,87 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: env.h +// Created: 7/2010 +// Author: Vaclav Haisman +// +// +// Copyright (C) 2010-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_INTERNAL_ENV_H +#define LOG4CPLUS_INTERNAL_ENV_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#if defined (_WIN32) +#include +#endif +#ifdef LOG4CPLUS_HAVE_SYS_TYPES_H +#include +#endif +#ifdef LOG4CPLUS_HAVE_UNISTD_H +#include +#endif + + +namespace log4cplus { namespace internal { + + +bool get_env_var (tstring & value, tstring const & name); +bool parse_bool (bool & val, tstring const & str); + +inline +#if defined (_WIN32) +DWORD +get_process_id () +{ + return GetCurrentProcessId (); +} + +#elif defined (LOG4CPLUS_HAVE_GETPID) +pid_t +get_process_id () +{ + return getpid (); +} + +#else +int +get_process_id () +{ + return 0; +} + +#endif + + +} } // namespace log4cplus { namespace internal { + + +#endif // LOG4CPLUS_INTERNAL_ENV_H diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/internal/internal.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/internal/internal.h new file mode 100644 index 0000000..3b467ef --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/internal/internal.h @@ -0,0 +1,243 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: internal.h +// Created: 1/2009 +// Author: Vaclav Haisman +// +// +// Copyright (C) 2009-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/** @file + * This header contains declaration internal to log4cplus. They must never be + * visible from user accesible headers or exported in DLL/shared libray. + */ + + +#ifndef LOG4CPLUS_INTERNAL_INTERNAL_HEADER_ +#define LOG4CPLUS_INTERNAL_INTERNAL_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace log4cplus { + +namespace internal { + + +//! Canonical empty string. It is used when the need to return empty string +//! by reference arises. +extern log4cplus::tstring const empty_str; + + +struct gft_scratch_pad +{ + gft_scratch_pad (); + ~gft_scratch_pad (); + + void + reset () + { + uc_q_str_valid = false; + q_str_valid = false; + s_str_valid = false; + ret.clear (); + } + + log4cplus::tstring q_str; + log4cplus::tstring uc_q_str; + log4cplus::tstring s_str; + log4cplus::tstring ret; + log4cplus::tstring fmt; + log4cplus::tstring tmp; + std::vector buffer; + bool uc_q_str_valid; + bool q_str_valid; + bool s_str_valid; +}; + + +struct appender_sratch_pad +{ + appender_sratch_pad (); + ~appender_sratch_pad (); + + tostringstream oss; + tstring str; + std::string chstr; +}; + + +//! Per thread data. +struct per_thread_data +{ + per_thread_data (); + ~per_thread_data (); + + tostringstream macros_oss; + tostringstream layout_oss; + DiagnosticContextStack ndc_dcs; + MappedDiagnosticContextMap mdc_map; + log4cplus::tstring thread_name; + log4cplus::tstring thread_name2; + gft_scratch_pad gft_sp; + appender_sratch_pad appender_sp; + log4cplus::tstring faa_str; + log4cplus::tstring ll_str; + spi::InternalLoggingEvent forced_log_ev; + std::FILE * fnull; + log4cplus::helpers::snprintf_buf snprintf_buf; +}; + + +per_thread_data * alloc_ptd (); + +// TLS key whose value is pointer struct per_thread_data. +extern log4cplus::thread::impl::tls_key_type tls_storage_key; + + +#if ! defined (LOG4CPLUS_SINGLE_THREADED) \ + && defined (LOG4CPLUS_THREAD_LOCAL_VAR) + +extern LOG4CPLUS_THREAD_LOCAL_VAR per_thread_data * ptd; + + +inline +void +set_ptd (per_thread_data * p) +{ + ptd = p; +} + + +inline +per_thread_data * +get_ptd (bool alloc = true) +{ + if (LOG4CPLUS_UNLIKELY (! ptd && alloc)) + return alloc_ptd (); + + // The assert() does not belong here. get_ptd() might be called by + // cleanup code that can handle the returned NULL pointer. + //assert (ptd); + + return ptd; +} + + +#else // defined (LOG4CPLUS_THREAD_LOCAL_VAR) + + +inline +void +set_ptd (per_thread_data * p) +{ + thread::impl::tls_set_value (tls_storage_key, p); +} + + +inline +per_thread_data * +get_ptd (bool alloc = true) +{ + per_thread_data * ptd + = reinterpret_cast( + thread::impl::tls_get_value (tls_storage_key)); + + if (LOG4CPLUS_UNLIKELY (! ptd && alloc)) + return alloc_ptd (); + + return ptd; +} + + +#endif // defined (LOG4CPLUS_THREAD_LOCAL_VAR) + + +inline +tstring & +get_thread_name_str () +{ + return get_ptd ()->thread_name; +} + + +inline +tstring & +get_thread_name2_str () +{ + return get_ptd ()->thread_name2; +} + + +inline +gft_scratch_pad & +get_gft_scratch_pad () +{ + return get_ptd ()->gft_sp; +} + + +inline +appender_sratch_pad & +get_appender_sp () +{ + return get_ptd ()->appender_sp; +} + + +} // namespace internal { + + +namespace detail +{ + +LOG4CPLUS_EXPORT void clear_tostringstream (tostringstream &); + +} // namespace detail + + +} // namespace log4cplus { + + +#endif // LOG4CPLUS_INTERNAL_INTERNAL_HEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/internal/socket.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/internal/socket.h new file mode 100644 index 0000000..e1402e3 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/internal/socket.h @@ -0,0 +1,118 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: socket.h +// Created: 1/2010 +// Author: Vaclav Haisman +// +// +// Copyright (C) 2010-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/** @file + * This header contains declaration internal to log4cplus. They must never be + * visible from user accesible headers or exported in DLL/shared libray. + */ + + +#ifndef LOG4CPLUS_INTERNAL_SOCKET_H_ +#define LOG4CPLUS_INTERNAL_SOCKET_H_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + +#if defined(_WIN32) +#include +#endif +#include + +#include +#ifdef LOG4CPLUS_HAVE_ERRNO_H +#include +#endif + + +namespace log4cplus { + +namespace helpers { + + +#if defined(_WIN32) +typedef SOCKET os_socket_type; +#else +typedef int os_socket_type; +#endif + + +os_socket_type const INVALID_OS_SOCKET_VALUE +#if defined(_WIN32) + = INVALID_SOCKET; +#else + = -1; +#endif + + +static inline +os_socket_type +to_os_socket (SOCKET_TYPE const & x) +{ + return static_cast(x); +} + + +static inline +SOCKET_TYPE +to_log4cplus_socket (os_socket_type const & x) +{ + return static_cast(x); +} + + +static inline +void +set_last_socket_error (int err) +{ + errno = err; +} + + +static inline +int +get_last_socket_error () +{ + return errno; +} + + +} // namespace helpers { + +} // namespace log4cplus { + + +#endif // LOG4CPLUS_INTERNAL_SOCKET_H_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/layout.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/layout.h new file mode 100644 index 0000000..16a6d31 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/layout.h @@ -0,0 +1,622 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: Layout.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_LAYOUT_HEADER_ +#define LOG4CPLUS_LAYOUT_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include + +#include + + +namespace log4cplus { + + // Forward Declarations + namespace pattern + { + + class PatternConverter; + + } + + + namespace helpers + { + + class Properties; + class Time; + + } + + + namespace spi + { + + class InternalLoggingEvent; + + } + + + /** + * This class is used to layout strings sent to an {@link + * log4cplus::Appender}. + */ + class LOG4CPLUS_EXPORT Layout + { + public: + Layout(); + Layout(const helpers::Properties& properties); + virtual ~Layout() = 0; + + virtual void formatAndAppend(log4cplus::tostream& output, + const log4cplus::spi::InternalLoggingEvent& event) = 0; + + protected: + LogLevelManager& llmCache; + + private: + // Disable copy + Layout(const Layout&); + Layout& operator=(Layout const &); + }; + + + + /** + * SimpleLayout consists of the LogLevel of the log statement, + * followed by " - " and then the log message itself. For example, + * + *
+     *         DEBUG - Hello world
+     * 
+ * + * {@link PatternLayout} offers a much more powerful alternative. + */ + class LOG4CPLUS_EXPORT SimpleLayout + : public Layout + { + public: + SimpleLayout(); + SimpleLayout(const log4cplus::helpers::Properties& properties); + virtual ~SimpleLayout(); + + virtual void formatAndAppend(log4cplus::tostream& output, + const log4cplus::spi::InternalLoggingEvent& event); + + private: + // Disallow copying of instances of this class + SimpleLayout(const SimpleLayout&); + SimpleLayout& operator=(const SimpleLayout&); + }; + + + + /** + * TTCC layout format consists of time, thread, Logger and nested + * diagnostic context information, hence the name. + * + * The time format depends on the DateFormat used. Use the + * Use_gmtime to specify whether messages should be logged using + * localtime or gmtime. + * + * Here is an example TTCCLayout output: + * + *
+     * 176 [main] INFO  org.apache.log4j.examples.Sort - Populating an array of 2 elements in reverse order.
+     * 225 [main] INFO  org.apache.log4j.examples.SortAlgo - Entered the sort method.
+     * 262 [main] DEBUG org.apache.log4j.examples.SortAlgo.OUTER i=1 - Outer loop.
+     * 276 [main] DEBUG org.apache.log4j.examples.SortAlgo.SWAP i=1 j=0 - Swapping intArray[0] = 1 and intArray[1] = 0
+     * 290 [main] DEBUG org.apache.log4j.examples.SortAlgo.OUTER i=0 - Outer loop.
+     * 304 [main] INFO  org.apache.log4j.examples.SortAlgo.DUMP - Dump of interger array:
+     * 317 [main] INFO  org.apache.log4j.examples.SortAlgo.DUMP - Element [0] = 0
+     * 331 [main] INFO  org.apache.log4j.examples.SortAlgo.DUMP - Element [1] = 1
+     * 343 [main] INFO  org.apache.log4j.examples.Sort - The next log statement should be an error message.
+     * 346 [main] ERROR org.apache.log4j.examples.SortAlgo.DUMP - Tried to dump an uninitialized array.
+     * 467 [main] INFO  org.apache.log4j.examples.Sort - Exiting main method.
+     * 
+ * + * The first field is the number of milliseconds elapsed since the + * start of the program. The second field is the thread outputting the + * log statement. The third field is the LogLevel, the fourth field is + * the logger to which the statement belongs. + * + * The fifth field (just before the '-') is the nested diagnostic + * context. Note the nested diagnostic context may be empty as in the + * first two statements. The text after the '-' is the message of the + * statement. + * + * PatternLayout offers a much more flexible alternative. + */ + class LOG4CPLUS_EXPORT TTCCLayout + : public Layout + { + public: + // Ctor and dtor + TTCCLayout(bool use_gmtime = false); + TTCCLayout(const log4cplus::helpers::Properties& properties); + virtual ~TTCCLayout(); + + virtual void formatAndAppend(log4cplus::tostream& output, + const log4cplus::spi::InternalLoggingEvent& event); + + protected: + log4cplus::tstring dateFormat; + bool use_gmtime; + + private: + // Disallow copying of instances of this class + TTCCLayout(const TTCCLayout&); + TTCCLayout& operator=(const TTCCLayout&); + }; + + + LOG4CPLUS_EXPORT helpers::Time const & getTTCCLayoutTimeBase (); + + + /** + * A flexible layout configurable with pattern string. + * + * The goal of this class is to format a InternalLoggingEvent and return + * the results as a string. The results depend on the conversion + * pattern. + * + * The conversion pattern is closely related to the conversion + * pattern of the printf function in C. A conversion pattern is + * composed of literal text and format control expressions called + * conversion specifiers. + * + * You are free to insert any literal text within the conversion + * pattern. + * + * Each conversion specifier starts with a percent sign (%%) and is + * followed by optional format modifiers and a conversion + * character. The conversion character specifies the type of + * data, e.g. Logger, LogLevel, date, thread name. The format + * modifiers control such things as field width, padding, left and + * right justification. The following is a simple example. + * + * Let the conversion pattern be "%-5p [%t]: %m%n" and assume + * that the log4cplus environment was set to use a PatternLayout. Then the + * statements + *
+     * Logger root = Logger.getRoot();
+     * LOG4CPLUS_DEBUG(root, "Message 1");
+     * LOG4CPLUS_WARN(root, "Message 2");
+     * 
+ * would yield the output + *
+     * DEBUG [main]: Message 1
+     * WARN  [main]: Message 2  
+     * 
+ * + * Note that there is no explicit separator between text and + * conversion specifiers. The pattern parser knows when it has reached + * the end of a conversion specifier when it reads a conversion + * character. In the example above the conversion specifier + * "%-5p" means the LogLevel of the logging event should be left + * justified to a width of five characters. + * + * The recognized conversion characters are + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Conversion CharacterEffect
bUsed to output file name component of path name. + * E.g. main.cxx from path ../../main.cxx.
cUsed to output the logger of the logging event. The + * logger conversion specifier can be optionally followed by + * precision specifier, that is a decimal constant in + * brackets. + * + * If a precision specifier is given, then only the corresponding + * number of right most components of the logger name will be + * printed. By default the logger name is printed in full. + * + * For example, for the logger name "a.b.c" the pattern + * %c{2} will output "b.c". + * + *
dUsed to output the date of the logging event in UTC. + * + * The date conversion specifier may be followed by a date format + * specifier enclosed between braces. For example, %%d{%%H:%%M:%%s} + * or %%d{%%d %%b %%Y %%H:%%M:%%s}. If no date format + * specifier is given then %%d{%%d %%m %%Y %%H:%%M:%%s} + * is assumed. + * + * The Following format options are possible: + *
    + *
  • %%a -- Abbreviated weekday name
  • + *
  • %%A -- Full weekday name
  • + *
  • %%b -- Abbreviated month name
  • + *
  • %%B -- Full month name
  • + *
  • %%c -- Standard date and time string
  • + *
  • %%d -- Day of month as a decimal(1-31)
  • + *
  • %%H -- Hour(0-23)
  • + *
  • %%I -- Hour(1-12)
  • + *
  • %%j -- Day of year as a decimal(1-366)
  • + *
  • %%m -- Month as decimal(1-12)
  • + *
  • %%M -- Minute as decimal(0-59)
  • + *
  • %%p -- Locale's equivalent of AM or PM
  • + *
  • %%q -- milliseconds as decimal(0-999) -- Log4CPLUS specific + *
  • %%Q -- fractional milliseconds as decimal(0-999.999) -- Log4CPLUS specific + *
  • %%S -- Second as decimal(0-59)
  • + *
  • %%U -- Week of year, Sunday being first day(0-53)
  • + *
  • %%w -- Weekday as a decimal(0-6, Sunday being 0)
  • + *
  • %%W -- Week of year, Monday being first day(0-53)
  • + *
  • %%x -- Standard date string
  • + *
  • %%X -- Standard time string
  • + *
  • %%y -- Year in decimal without century(0-99)
  • + *
  • %%Y -- Year including century as decimal
  • + *
  • %%Z -- Time zone name
  • + *
  • %% -- The percent sign
  • + *
+ * + * Lookup the documentation for the strftime() function + * found in the <ctime> header for more information. + *
DUsed to output the date of the logging event in local time. + * + * All of the above information applies. + *
EUsed to output the value of a given environment variable. The + * name of is supplied as an argument in brackets. If the variable does + * exist then empty string will be used. + * + * For example, the pattern %E{HOME} will output the contents + * of the HOME environment variable. + *
FUsed to output the file name where the logging request was + * issued. + * + * NOTE Unlike log4j, there is no performance penalty for + * calling this method.
hUsed to output the hostname of this system (as returned + * by gethostname(2)). + * + * NOTE The hostname is only retrieved once at + * initialization. + * + *
HUsed to output the fully-qualified domain name of this + * system (as returned by gethostbyname(2) for the hostname + * returned by gethostname(2)). + * + * NOTE The hostname is only retrieved once at + * initialization. + * + *
lEquivalent to using "%F:%L" + * + * NOTE: Unlike log4j, there is no performance penalty for + * calling this method. + * + *
LUsed to output the line number from where the logging request + * was issued. + * + * NOTE: Unlike log4j, there is no performance penalty for + * calling this method. + * + *
mUsed to output the application supplied message associated with + * the logging event.
MUsed to output function name using + * __FUNCTION__ or similar macro. + * + * NOTE The __FUNCTION__ macro is not + * standard but it is common extension provided by all compilers + * (as of 2010). In case it is missing or in case this feature + * is disabled using the + * LOG4CPLUS_DISABLE_FUNCTION_MACRO macro, %M + * expands to an empty string.
nOutputs the platform dependent line separator character or + * characters. + *
pUsed to output the LogLevel of the logging event.
rUsed to output miliseconds since program start + * of the logging event.
tUsed to output the name of the thread that generated the + * logging event.
TUsed to output alternative name of the thread that generated the + * logging event.
iUsed to output the process ID of the process that generated the + * logging event.
xUsed to output the NDC (nested diagnostic context) associated + * with the thread that generated the logging event. + *
XUsed to output the MDC (mapped diagnostic context) + * associated with the thread that generated the logging + * event. It takes optional key parameter. Without the key + * paramter (%%X), it outputs the whole MDC map. With the key + * (%%X{key}), it outputs just the key's value. + *
"%%"The sequence "%%" outputs a single percent sign. + *
+ * + * By default the relevant information is output as is. However, + * with the aid of format modifiers it is possible to change the + * minimum field width, the maximum field width and justification. + * + * The optional format modifier is placed between the percent sign + * and the conversion character. + * + * The first optional format modifier is the left justification + * flag which is just the minus (-) character. Then comes the + * optional minimum field width modifier. This is a decimal + * constant that represents the minimum number of characters to + * output. If the data item requires fewer characters, it is padded on + * either the left or the right until the minimum width is + * reached. The default is to pad on the left (right justify) but you + * can specify right padding with the left justification flag. The + * padding character is space. If the data item is larger than the + * minimum field width, the field is expanded to accommodate the + * data. The value is never truncated. + * + * This behavior can be changed using the maximum field + * width modifier which is designated by a period followed by a + * decimal constant. If the data item is longer than the maximum + * field, then the extra characters are removed from the + * beginning of the data item and not from the end. For + * example, it the maximum field width is eight and the data item is + * ten characters long, then the first two characters of the data item + * are dropped. This behavior deviates from the printf function in C + * where truncation is done from the end. + * + * Below are various format modifier examples for the logger + * conversion specifier. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Format modifierleft justifyminimum widthmaximum widthcomment
%20cfalse20noneLeft pad with spaces if the logger name is less than 20 + * characters long. + *
%-20c true 20 none Right pad with + * spaces if the logger name is less than 20 characters long. + *
%.30cNAnone30Truncate from the beginning if the logger name is longer than 30 + * characters. + *
%20.30cfalse2030Left pad with spaces if the logger name is shorter than 20 + * characters. However, if logger name is longer than 30 characters, + * then truncate from the beginning. + *
%-20.30ctrue2030Right pad with spaces if the logger name is shorter than 20 + * characters. However, if logger name is longer than 30 characters, + * then truncate from the beginning. + *
+ * + * Below are some examples of conversion patterns. + * + *
+ * + *
"%r [%t] %-5p %c %x - %m%n" + *
This is essentially the TTCC layout. + * + *
"%-6r [%15.15t] %-5p %30.30c %x - %m%n" + * + *
Similar to the TTCC layout except that the relative time is + * right padded if less than 6 digits, thread name is right padded if + * less than 15 characters and truncated if longer and the logger + * name is left padded if shorter than 30 characters and truncated if + * longer. + * + *
+ * + * The above text is largely inspired from Peter A. Darnell and + * Philip E. Margolis' highly recommended book "C -- a Software + * Engineering Approach", ISBN 0-387-97389-3. + * + *

Properties

+ * + *
+ *
NDCMaxDepth
+ *
This property limits how many deepest NDC components will + * be printed by %%x specifier.
+ * + *
ConversionPattern
+ *
This property specifies conversion pattern.
+ *
+ * + */ + class LOG4CPLUS_EXPORT PatternLayout + : public Layout + { + public: + // Ctors and dtor + PatternLayout(const log4cplus::tstring& pattern); + PatternLayout(const log4cplus::helpers::Properties& properties); + virtual ~PatternLayout(); + + virtual void formatAndAppend(log4cplus::tostream& output, + const log4cplus::spi::InternalLoggingEvent& event); + + protected: + void init(const log4cplus::tstring& pattern, unsigned ndcMaxDepth = 0); + + // Data + log4cplus::tstring pattern; + std::vector parsedPattern; + + private: + // Disallow copying of instances of this class + PatternLayout(const PatternLayout&); + PatternLayout& operator=(const PatternLayout&); + }; + + + +} // end namespace log4cplus + +#endif // LOG4CPLUS_LAYOUT_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/log4judpappender.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/log4judpappender.h new file mode 100644 index 0000000..51302c7 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/log4judpappender.h @@ -0,0 +1,86 @@ +// -*- C++ -*- +// Module: LOG4CPLUS +// File: log4judpappender.h +// Created: 7/2012 +// Author: Siva Chandran P +// +// +// Copyright 2012-2013 Siva Chandran P +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_LOG4J_UDP_APPENDER_HEADER_ +#define LOG4CPLUS_LOG4J_UDP_APPENDER_HEADER_ + +#include +#include +#include + +namespace log4cplus { + + /** + * Sends log events as Log4j XML to a remote a log server. + * + * The Log4jUdpAppender has the following properties: + * + *
    + *
  • Remote logging is non-intrusive as far as the log event + * is concerned. In other words, the event will be logged with + * the same time stamp, NDC, location info as if it were logged + * locally by the client.
  • + * + *
  • Remote logging uses the UDP protocol.
  • + *
+ * + *

Properties

+ *
+ *
host
+ *
Remote host name to connect and send events to.
+ * + *
port
+ *
Port on remote host to send events to.
+ * + *
+ */ + class LOG4CPLUS_EXPORT Log4jUdpAppender : public Appender { + public: + // Ctors + Log4jUdpAppender(const log4cplus::tstring& host, int port); + Log4jUdpAppender(const log4cplus::helpers::Properties & properties); + + // Dtor + ~Log4jUdpAppender(); + + // Methods + virtual void close(); + + protected: + void openSocket(); + virtual void append(const spi::InternalLoggingEvent& event); + + // Data + log4cplus::helpers::Socket socket; + log4cplus::tstring host; + int port; + + private: + // Disallow copying of instances of this class + Log4jUdpAppender(const Log4jUdpAppender&); + Log4jUdpAppender& operator=(const Log4jUdpAppender&); + }; +} // end namespace log4cplus + +#endif // LOG4CPLUS_LOG4J_UDP_APPENDER_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/logger.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/logger.h new file mode 100644 index 0000000..d039761 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/logger.h @@ -0,0 +1,321 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: logger.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file + * This header defines the Logger class and the logging macros. */ + +#ifndef LOG4CPLUS_LOGGERHEADER_ +#define LOG4CPLUS_LOGGERHEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + +#include + + +namespace log4cplus +{ + // Forward declarations + + class Appender; + class Hierarchy; + class HierarchyLocker; + class DefaultLoggerFactory; + + namespace spi + { + + class LoggerImpl; + + } + + + /** \typedef std::vector LoggerList + * This is a list of {@link Logger Loggers}. */ + typedef std::vector LoggerList; + + + /** + * This is the central class in the log4cplus package. One of the + * distintive features of log4cplus are hierarchical loggers and their + * evaluation. + * + * See the user manual for an + * introduction on this class. + */ + class LOG4CPLUS_EXPORT Logger + : public log4cplus::spi::AppenderAttachable + { + public: + // Static Methods + /** + * Returns true if the named logger exists + * (in the default hierarchy). + * + * @param name The name of the logger to search for. + */ + static bool exists(const log4cplus::tstring& name); + + /* + * Returns all the currently defined loggers in the default + * hierarchy. + * + * The root logger is not included in the returned + * list. + */ + static LoggerList getCurrentLoggers(); + + /** + * Return the default Hierarchy instance. + */ + static Hierarchy& getDefaultHierarchy(); + + /** + * Retrieve a logger with name name. If the named + * logger already exists, then the existing instance will be returned. + * Otherwise, a new instance is created. + * + * By default, loggers do not have a set LogLevel but inherit + * it from the hierarchy. This is one of the central features of + * log4cplus. + * + * @param name The name of the logger to retrieve. + */ + static Logger getInstance(const log4cplus::tstring& name); + + /** + * Like getInstance() except that the type of logger + * instantiated depends on the type returned by the {@link + * spi::LoggerFactory#makeNewLoggerInstance} method of the + * factory parameter. + * + * This method is intended to be used by sub-classes. + * + * @param name The name of the logger to retrieve. + * @param factory A {@link spi::LoggerFactory} implementation that will + * actually create a new Instance. + */ + static Logger getInstance(const log4cplus::tstring& name, spi::LoggerFactory& factory); + + /** + * Return the root of the default logger hierrachy. + * + * The root logger is always instantiated and available. It's + * name is "root". + * + * Nevertheless, calling {@link #getInstance + * Logger.getInstance("root")} does not retrieve the root logger + * but a logger just under root named "root". + */ + static Logger getRoot(); + + /** + * Calling this method will safely close and remove all + * appenders in all the loggers including root contained in the + * default hierachy. + * + * Some appenders such as SocketAppender need to be closed before the + * application exits. Otherwise, pending logging events might be + * lost. + * + * The shutdown method is careful to close nested + * appenders before closing regular appenders. This is allows + * configurations where a regular appender is attached to a logger + * and again to a nested appender. + */ + static void shutdown(); + + // Non-Static Methods + /** + * If assertionVal parameter is false, then + * logs msg with FATAL_LOG_LEVEL log level. + * + * @param assertionVal Truth value of assertion condition. + * @param msg The message to print if assertion is + * false. + */ + void assertion(bool assertionVal, const log4cplus::tstring& msg) const; + + /** + * Close all attached appenders implementing the AppenderAttachable + * interface. + */ + void closeNestedAppenders() const; + + /** + * Check whether this logger is enabled for a given + * LogLevel passed as parameter. + * + * @return boolean True if this logger is enabled for ll. + */ + bool isEnabledFor(LogLevel ll) const; + + /** + * This generic form is intended to be used by wrappers. + */ + void log(LogLevel ll, const log4cplus::tstring& message, + const char* file=NULL, int line=-1) const; + + void log(spi::InternalLoggingEvent const &) const; + + /** + * This method creates a new logging event and logs the event + * without further checks. + */ + void forcedLog(LogLevel ll, const log4cplus::tstring& message, + const char* file=NULL, int line=-1) const; + + void forcedLog(spi::InternalLoggingEvent const &) const; + + /** + * Call the appenders in the hierrachy starting at + * this. If no appenders could be found, emit a + * warning. + * + * This method calls all the appenders inherited from the + * hierarchy circumventing any evaluation of whether to log or not + * to log the particular log request. + * + * @param event the event to log. + */ + void callAppenders(const spi::InternalLoggingEvent& event) const; + + /** + * Starting from this logger, search the logger hierarchy for a + * "set" LogLevel and return it. Otherwise, return the LogLevel of the + * root logger. + * + * The Logger class is designed so that this method executes as + * quickly as possible. + */ + LogLevel getChainedLogLevel() const; + + /** + * Returns the assigned LogLevel, if any, for this Logger. + * + * @return LogLevel - the assigned LogLevel, can be NOT_SET_LOG_LEVEL. + */ + LogLevel getLogLevel() const; + + /** + * Set the LogLevel of this Logger. + */ + void setLogLevel(LogLevel ll); + + /** + * Return the the {@link Hierarchy} where this Logger instance is + * attached. + */ + Hierarchy& getHierarchy() const; + + /** + * Return the logger name. + */ + log4cplus::tstring const & getName() const; + + /** + * Get the additivity flag for this Logger instance. + */ + bool getAdditivity() const; + + /** + * Set the additivity flag for this Logger instance. + */ + void setAdditivity(bool additive); + + // AppenderAttachable Methods + virtual void addAppender(SharedAppenderPtr newAppender); + + virtual SharedAppenderPtrList getAllAppenders(); + + virtual SharedAppenderPtr getAppender(const log4cplus::tstring& name); + + virtual void removeAllAppenders(); + + virtual void removeAppender(SharedAppenderPtr appender); + + virtual void removeAppender(const log4cplus::tstring& name); + + Logger (); + Logger(const Logger& rhs); + Logger& operator=(const Logger& rhs); +#if defined (LOG4CPLUS_HAVE_RVALUE_REFS) + Logger (Logger && rhs); + Logger & operator = (Logger && rhs); +#endif + virtual ~Logger(); + + void swap (Logger &); + + /** + * Used to retrieve the parent of this Logger in the + * Logger tree. + */ + Logger getParent() const; + + protected: + // Data + /** This is a pointer to the implementation class. */ + spi::LoggerImpl * value; + + private: + // Ctors + /** + * This constructor created a new Logger instance + * with a pointer to a Logger implementation. + * + * You should not create loggers directly. + * + * @param ptr A pointer to the Logger implementation. This value + * cannot be NULL. + */ + LOG4CPLUS_PRIVATE Logger(spi::LoggerImpl * ptr); + + // Friends + friend class log4cplus::spi::LoggerImpl; + friend class log4cplus::Hierarchy; + friend class log4cplus::HierarchyLocker; + friend class log4cplus::DefaultLoggerFactory; + }; + + + /** + * This class is used to create the default implementation of + * the Logger class + */ + class LOG4CPLUS_EXPORT DefaultLoggerFactory : public spi::LoggerFactory { + public: + Logger makeNewLoggerInstance(const log4cplus::tstring& name, Hierarchy& h); + }; + + +} // end namespace log4cplus + + +#endif // LOG4CPLUS_LOGGERHEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/loggingmacros.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/loggingmacros.h new file mode 100644 index 0000000..4e108b8 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/loggingmacros.h @@ -0,0 +1,457 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: loggingmacros.h +// Created: 8/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file + * This header defines the logging macros. */ + +#ifndef LOG4CPLUS_LOGGING_MACROS_HEADER_ +#define LOG4CPLUS_LOGGING_MACROS_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include + + +#if defined(_MSC_VER) +#define LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + __pragma (warning (push)) \ + __pragma (warning (disable:4127)) + +#define LOG4CPLUS_RESTORE_DOWHILE_WARNING() \ + __pragma (warning (pop)) + +#else +#define LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() /* empty */ +#define LOG4CPLUS_RESTORE_DOWHILE_WARNING() /* empty */ + +#endif + +#define LOG4CPLUS_DOWHILE_NOTHING() \ + LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + do { } while (0) \ + LOG4CPLUS_RESTORE_DOWHILE_WARNING() + +#if defined(LOG4CPLUS_DISABLE_FATAL) && !defined(LOG4CPLUS_DISABLE_ERROR) +#define LOG4CPLUS_DISABLE_ERROR +#endif +#if defined(LOG4CPLUS_DISABLE_ERROR) && !defined(LOG4CPLUS_DISABLE_WARN) +#define LOG4CPLUS_DISABLE_WARN +#endif +#if defined(LOG4CPLUS_DISABLE_WARN) && !defined(LOG4CPLUS_DISABLE_INFO) +#define LOG4CPLUS_DISABLE_INFO +#endif +#if defined(LOG4CPLUS_DISABLE_INFO) && !defined(LOG4CPLUS_DISABLE_DEBUG) +#define LOG4CPLUS_DISABLE_DEBUG +#endif +#if defined(LOG4CPLUS_DISABLE_DEBUG) && !defined(LOG4CPLUS_DISABLE_TRACE) +#define LOG4CPLUS_DISABLE_TRACE +#endif + + +namespace log4cplus +{ + +namespace detail +{ + + +inline +Logger +macros_get_logger (Logger const & logger) +{ + return logger; +} + + +inline +Logger const & +macros_get_logger (Logger & logger) +{ + return logger; +} + + +#if defined (LOG4CPLUS_HAVE_RVALUE_REFS) +inline +Logger +macros_get_logger (Logger && logger) +{ + return std::move (logger); +} + +#endif + + +inline +Logger +macros_get_logger (tstring const & logger) +{ + return Logger::getInstance (logger); +} + + +inline +Logger +macros_get_logger (tchar const * logger) +{ + return Logger::getInstance (logger); +} + + +LOG4CPLUS_EXPORT void clear_tostringstream (tostringstream &); + + +LOG4CPLUS_EXPORT log4cplus::tostringstream & get_macro_body_oss (); +LOG4CPLUS_EXPORT log4cplus::helpers::snprintf_buf & get_macro_body_snprintf_buf (); +LOG4CPLUS_EXPORT void macro_forced_log (log4cplus::Logger const &, + log4cplus::LogLevel, log4cplus::tstring const &, char const *, int, + char const *); + + +} // namespace detail + +} // namespace log4cplus + + +#if ! defined (LOG4CPLUS_DISABLE_FUNCTION_MACRO) \ + && ! defined (LOG4CPLUS_MACRO_FUNCTION) +# if defined (LOG4CPLUS_HAVE_FUNCSIG_MACRO) +# define LOG4CPLUS_MACRO_FUNCTION() __FUNCSIG__ +# elif defined (LOG4CPLUS_HAVE_PRETTY_FUNCTION_MACRO) +# define LOG4CPLUS_MACRO_FUNCTION() __PRETTY_FUNCTION__ +# elif defined (LOG4CPLUS_HAVE_FUNCTION_MACRO) +# define LOG4CPLUS_MACRO_FUNCTION() __FUNCTION__ +# elif defined (LOG4CPLUS_HAVE_FUNC_SYMBOL) +# define LOG4CPLUS_MACRO_FUNCTION() __func__ +# endif +#endif + +#if ! defined (LOG4CPLUS_MACRO_FUNCTION) +# define LOG4CPLUS_MACRO_FUNCTION() 0 +#endif + +// Make TRACE and DEBUG log level unlikely and INFO, WARN, ERROR and +// FATAL log level likely. +#define LOG4CPLUS_MACRO_TRACE_LOG_LEVEL(pred) \ + LOG4CPLUS_UNLIKELY (pred) +#define LOG4CPLUS_MACRO_DEBUG_LOG_LEVEL(pred) \ + LOG4CPLUS_UNLIKELY (pred) +#define LOG4CPLUS_MACRO_INFO_LOG_LEVEL(pred) \ + LOG4CPLUS_LIKELY (pred) +#define LOG4CPLUS_MACRO_WARN_LOG_LEVEL(pred) \ + LOG4CPLUS_LIKELY (pred) +#define LOG4CPLUS_MACRO_ERROR_LOG_LEVEL(pred) \ + LOG4CPLUS_LIKELY (pred) +#define LOG4CPLUS_MACRO_FATAL_LOG_LEVEL(pred) \ + LOG4CPLUS_LIKELY (pred) + + +//! Dispatch to LOG4CPLUS_MACRO_LOGLEVEL_* depending on log level. +#define LOG4CPLUS_MACRO_LOGLEVEL_PRED(pred, logLevel) \ + LOG4CPLUS_MACRO_ ## logLevel (pred) + + +// Either use temporary instances of ostringstream +// and snprintf_buf, or use thread-local instances. +#if defined (LOG4CPLUS_MACRO_DISABLE_TLS) +# define LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM(var) \ + log4cplus::tostringstream var + +# define LOG4CPLUS_MACRO_INSTANTIATE_SNPRINTF_BUF(var) \ + log4cplus::helpers::snprintf_buf var + +#else +# define LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM(var) \ + log4cplus::tostringstream & var \ + = log4cplus::detail::get_macro_body_oss () + +# define LOG4CPLUS_MACRO_INSTANTIATE_SNPRINTF_BUF(var) \ + log4cplus::helpers::snprintf_buf & var \ + = log4cplus::detail::get_macro_body_snprintf_buf () + +#endif + + +#define LOG4CPLUS_MACRO_BODY(logger, logEvent, logLevel) \ + LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + do { \ + log4cplus::Logger const & _l \ + = log4cplus::detail::macros_get_logger (logger); \ + if (LOG4CPLUS_MACRO_LOGLEVEL_PRED ( \ + _l.isEnabledFor (log4cplus::logLevel), logLevel)) { \ + LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM (_log4cplus_buf); \ + _log4cplus_buf << logEvent; \ + log4cplus::detail::macro_forced_log (_l, \ + log4cplus::logLevel, _log4cplus_buf.str(), \ + __FILE__, __LINE__, LOG4CPLUS_MACRO_FUNCTION ()); \ + } \ + } while (0) \ + LOG4CPLUS_RESTORE_DOWHILE_WARNING() + + +#define LOG4CPLUS_MACRO_STR_BODY(logger, logEvent, logLevel) \ + LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + do { \ + log4cplus::Logger const & _l \ + = log4cplus::detail::macros_get_logger (logger); \ + if (LOG4CPLUS_MACRO_LOGLEVEL_PRED ( \ + _l.isEnabledFor (log4cplus::logLevel), logLevel)) { \ + log4cplus::detail::macro_forced_log (_l, \ + log4cplus::logLevel, logEvent, \ + __FILE__, __LINE__, LOG4CPLUS_MACRO_FUNCTION ()); \ + } \ + } while(0) \ + LOG4CPLUS_RESTORE_DOWHILE_WARNING() + +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_MACRO_FMT_BODY(logger, logLevel, ...) \ + LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + do { \ + log4cplus::Logger const & _l \ + = log4cplus::detail::macros_get_logger (logger); \ + if (LOG4CPLUS_MACRO_LOGLEVEL_PRED ( \ + _l.isEnabledFor (log4cplus::logLevel), logLevel)) { \ + LOG4CPLUS_MACRO_INSTANTIATE_SNPRINTF_BUF (_snpbuf); \ + log4cplus::tchar const * _logEvent \ + = _snpbuf.print (__VA_ARGS__); \ + log4cplus::detail::macro_forced_log (_l, \ + log4cplus::logLevel, _logEvent, \ + __FILE__, __LINE__, LOG4CPLUS_MACRO_FUNCTION ()); \ + } \ + } while(0) \ + LOG4CPLUS_RESTORE_DOWHILE_WARNING() + +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_MACRO_FMT_BODY(logger, logLevel, logArgs...) \ + LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \ + do { \ + log4cplus::Logger const & _l \ + = log4cplus::detail::macros_get_logger (logger); \ + if (LOG4CPLUS_MACRO_LOGLEVEL_PRED ( \ + _l.isEnabledFor (log4cplus::logLevel), logLevel)) { \ + LOG4CPLUS_MACRO_INSTANTIATE_SNPRINTF_BUF (_snpbuf); \ + log4cplus::tchar const * _logEvent \ + = _snpbuf.print (logArgs); \ + log4cplus::detail::macro_forced_log (_l, \ + log4cplus::logLevel, _logEvent, \ + __FILE__, __LINE__, LOG4CPLUS_MACRO_FUNCTION ()); \ + } \ + } while(0) \ + LOG4CPLUS_RESTORE_DOWHILE_WARNING() + +#endif + + +/** + * @def LOG4CPLUS_TRACE(logger, logEvent) This macro creates a + * TraceLogger to log a TRACE_LOG_LEVEL message to logger + * upon entry and exiting of a method. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_TRACE) +#define LOG4CPLUS_TRACE_METHOD(logger, logEvent) \ + log4cplus::TraceLogger _log4cplus_trace_logger(logger, logEvent, \ + __FILE__, __LINE__); +#define LOG4CPLUS_TRACE(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, TRACE_LOG_LEVEL) +#define LOG4CPLUS_TRACE_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, TRACE_LOG_LEVEL) + +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_TRACE_FMT(logger, ...) \ + LOG4CPLUS_MACRO_FMT_BODY (logger, TRACE_LOG_LEVEL, __VA_ARGS__) +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_TRACE_FMT(logger, logArgs...) \ + LOG4CPLUS_MACRO_FMT_BODY(logger, TRACE_LOG_LEVEL, logArgs) +#endif + +#else +#define LOG4CPLUS_TRACE_METHOD(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_TRACE(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_TRACE_STR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_TRACE_FMT(logger, logFmt, ...) LOG4CPLUS_DOWHILE_NOTHING() +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_TRACE_FMT(logger, logFmt, logArgs...) LOG4CPLUS_DOWHILE_NOTHING() +#endif + +#endif + +/** + * @def LOG4CPLUS_DEBUG(logger, logEvent) This macro is used to log a + * DEBUG_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_DEBUG) +#define LOG4CPLUS_DEBUG(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, DEBUG_LOG_LEVEL) +#define LOG4CPLUS_DEBUG_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, DEBUG_LOG_LEVEL) + +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_DEBUG_FMT(logger, ...) \ + LOG4CPLUS_MACRO_FMT_BODY (logger, DEBUG_LOG_LEVEL, __VA_ARGS__) +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_DEBUG_FMT(logger, logArgs...) \ + LOG4CPLUS_MACRO_FMT_BODY(logger, DEBUG_LOG_LEVEL, logArgs) +#endif + +#else +#define LOG4CPLUS_DEBUG(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_DEBUG_STR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_DEBUG_FMT(logger, ...) LOG4CPLUS_DOWHILE_NOTHING() +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_DEBUG_FMT(logger, logArgs...) LOG4CPLUS_DOWHILE_NOTHING() +#endif + +#endif + +/** + * @def LOG4CPLUS_INFO(logger, logEvent) This macro is used to log a + * INFO_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_INFO) +#define LOG4CPLUS_INFO(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, INFO_LOG_LEVEL) +#define LOG4CPLUS_INFO_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, INFO_LOG_LEVEL) + +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_INFO_FMT(logger, ...) \ + LOG4CPLUS_MACRO_FMT_BODY (logger, INFO_LOG_LEVEL, __VA_ARGS__) +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_INFO_FMT(logger, logArgs...) \ + LOG4CPLUS_MACRO_FMT_BODY(logger, INFO_LOG_LEVEL, logArgs) +#endif + +#else +#define LOG4CPLUS_INFO(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_INFO_STR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_INFO_FMT(logger, ...) LOG4CPLUS_DOWHILE_NOTHING() +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_INFO_FMT(logger, logArgs...) LOG4CPLUS_DOWHILE_NOTHING() +#endif + +#endif + +/** + * @def LOG4CPLUS_WARN(logger, logEvent) This macro is used to log a + * WARN_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_WARN) +#define LOG4CPLUS_WARN(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, WARN_LOG_LEVEL) +#define LOG4CPLUS_WARN_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, WARN_LOG_LEVEL) + +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_WARN_FMT(logger, ...) \ + LOG4CPLUS_MACRO_FMT_BODY (logger, WARN_LOG_LEVEL, __VA_ARGS__) +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_WARN_FMT(logger, logArgs...) \ + LOG4CPLUS_MACRO_FMT_BODY(logger, WARN_LOG_LEVEL, logArgs) +#endif + +#else +#define LOG4CPLUS_WARN(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_WARN_STR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_WARN_FMT(logger, ...) LOG4CPLUS_DOWHILE_NOTHING() +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_WARN_FMT(logger, logArgs...) LOG4CPLUS_DOWHILE_NOTHING() +#endif + +#endif + +/** + * @def LOG4CPLUS_ERROR(logger, logEvent) This macro is used to log a + * ERROR_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_ERROR) +#define LOG4CPLUS_ERROR(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, ERROR_LOG_LEVEL) +#define LOG4CPLUS_ERROR_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, ERROR_LOG_LEVEL) + +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_ERROR_FMT(logger, ...) \ + LOG4CPLUS_MACRO_FMT_BODY (logger, ERROR_LOG_LEVEL, __VA_ARGS__) +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_ERROR_FMT(logger, logArgs...) \ + LOG4CPLUS_MACRO_FMT_BODY(logger, ERROR_LOG_LEVEL, logArgs) +#endif + +#else +#define LOG4CPLUS_ERROR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_ERROR_STR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_ERROR_FMT(logger, ...) LOG4CPLUS_DOWHILE_NOTHING() +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_ERROR_FMT(logger, logArgs...) LOG4CPLUS_DOWHILE_NOTHING() +#endif + +#endif + +/** + * @def LOG4CPLUS_FATAL(logger, logEvent) This macro is used to log a + * FATAL_LOG_LEVEL message to logger. + * logEvent will be streamed into an ostream. + */ +#if !defined(LOG4CPLUS_DISABLE_FATAL) +#define LOG4CPLUS_FATAL(logger, logEvent) \ + LOG4CPLUS_MACRO_BODY (logger, logEvent, FATAL_LOG_LEVEL) +#define LOG4CPLUS_FATAL_STR(logger, logEvent) \ + LOG4CPLUS_MACRO_STR_BODY (logger, logEvent, FATAL_LOG_LEVEL) + +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_FATAL_FMT(logger, ...) \ + LOG4CPLUS_MACRO_FMT_BODY (logger, FATAL_LOG_LEVEL, __VA_ARGS__) +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_FATAL_FMT(logger, logArgs...) \ + LOG4CPLUS_MACRO_FMT_BODY(logger, FATAL_LOG_LEVEL, logArgs) +#endif + +#else +#define LOG4CPLUS_FATAL(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#define LOG4CPLUS_FATAL_STR(logger, logEvent) LOG4CPLUS_DOWHILE_NOTHING() +#if defined (LOG4CPLUS_HAVE_C99_VARIADIC_MACROS) +#define LOG4CPLUS_FATAL_FMT(logger, ...) LOG4CPLUS_DOWHILE_NOTHING() +#elif defined (LOG4CPLUS_HAVE_GNU_VARIADIC_MACROS) +#define LOG4CPLUS_FATAL_FMT(logger, logArgs...) LOG4CPLUS_DOWHILE_NOTHING() +#endif + +#endif + +#endif /* LOG4CPLUS_LOGGING_MACROS_HEADER_ */ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/loglevel.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/loglevel.h new file mode 100644 index 0000000..d7e0db2 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/loglevel.h @@ -0,0 +1,209 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: loglevel.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file + * This header defines the LogLevel type. + */ + +#ifndef LOG4CPLUS_LOGLEVEL_HEADER_ +#define LOG4CPLUS_LOGLEVEL_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus { + + /** + * \typedef int LogLevel + * Defines the minimum set of priorities recognized by the system, + * that is {@link #FATAL_LOG_LEVEL}, {@link #ERROR_LOG_LEVEL}, {@link + * #WARN_LOG_LEVEL}, {@link #INFO_LOG_LEVEL}, {@link #DEBUG_LOG_LEVEL}, + * and {@link #TRACE_LOG_LEVEL}. + */ + typedef int LogLevel; + + /** \var const LogLevel OFF_LOG_LEVEL + * The OFF_LOG_LEVEL LogLevel is used during configuration to + * turn off logging. */ + const LogLevel OFF_LOG_LEVEL = 60000; + + /** \var const LogLevel FATAL_LOG_LEVEL + * The FATAL_LOG_LEVEL LogLevel designates very severe error + * events that will presumably lead the application to abort. */ + const LogLevel FATAL_LOG_LEVEL = 50000; + + /** \var const LogLevel ERROR_LOG_LEVEL + * The ERROR_LOG_LEVEL LogLevel designates error events that + * might still allow the application to continue running. */ + const LogLevel ERROR_LOG_LEVEL = 40000; + + /** \var const LogLevel WARN_LOG_LEVEL + * The WARN_LOG_LEVEL LogLevel designates potentially harmful + * situations. */ + const LogLevel WARN_LOG_LEVEL = 30000; + + /** \var const LogLevel INFO_LOG_LEVEL + * The INFO_LOG_LEVEL LogLevel designates informational + * messages that highlight the progress of the application at + * coarse-grained level. */ + const LogLevel INFO_LOG_LEVEL = 20000; + + /** \var const LogLevel DEBUG_LOG_LEVEL + * The DEBUG_LOG_LEVEL LogLevel designates fine-grained + * informational events that are most useful to debug an application. */ + const LogLevel DEBUG_LOG_LEVEL = 10000; + + /** \var const LogLevel TRACE_LOG_LEVEL + * The TRACE_LOG_LEVEL LogLevel is used to "trace" entry + * and exiting of methods. */ + const LogLevel TRACE_LOG_LEVEL = 0; + + /** \var const LogLevel ALL_LOG_LEVEL + * The ALL_LOG_LEVEL LogLevel is used during configuration to + * turn on all logging. */ + const LogLevel ALL_LOG_LEVEL = TRACE_LOG_LEVEL; + + /** \var const LogLevel NOT_SET_LOG_LEVEL + * The NOT_SET_LOG_LEVEL LogLevel is used to indicated that + * no particular LogLevel is desired and that the default should be used. + */ + const LogLevel NOT_SET_LOG_LEVEL = -1; + + + /** + * This method type defined the signature of methods that convert LogLevels + * into strings. + * + * Note: Must return an empty tstring for unrecognized values. + */ + typedef log4cplus::tstring const & (*LogLevelToStringMethod)(LogLevel); + + //! This function type is for log4cplus 1.0.x callbacks. + typedef log4cplus::tstring (*LogLevelToStringMethod_1_0) (LogLevel); + + + /** + * This method type defined the signature of methods that convert strings + * into LogLevels. + * + * Note: Must return NOT_SET_LOG_LEVEL for unrecognized values. + */ + typedef LogLevel (*StringToLogLevelMethod)(const log4cplus::tstring&); + + + + /** + * This class is used to "manage" LogLevel definitions. This class is also + * how "derived" LogLevels are created. Here are the steps to creating a + * "derived" LogLevel: + *
    + *
  1. Create a LogLevel constant (greater than 0)
  2. + *
  3. Define a string to represent that constant
  4. + *
  5. Implement a LogLevelToStringMethod method.
  6. + *
  7. Implement a StringToLogLevelMethod method.
  8. + *
  9. create a "static initializer" that registers those 2 methods + * with the LogLevelManager singleton.
  10. + *
+ */ + class LOG4CPLUS_EXPORT LogLevelManager { + public: + LogLevelManager(); + ~LogLevelManager(); + + /** + * This method is called by all Layout classes to convert a LogLevel + * into a string. + * + * Note: It traverses the list of LogLevelToStringMethod + * to do this, so all "derived" LogLevels are recognized as well. + */ + log4cplus::tstring const & toString(LogLevel ll) const; + + /** + * This method is called by all classes internally to log4cplus to + * convert a string into a LogLevel. + * + * Note: It traverses the list of StringToLogLevelMethod + * to do this, so all "derived" LogLevels are recognized as well. + */ + LogLevel fromString(const log4cplus::tstring& s) const; + + /** + * When creating a "derived" LogLevel, a LogLevelToStringMethod + * should be defined and registered with the LogLevelManager by calling + * this method. + * + * @see pushFromStringMethod + */ + void pushToStringMethod(LogLevelToStringMethod newToString); + + //! For compatibility with log4cplus 1.0.x. + void pushToStringMethod(LogLevelToStringMethod_1_0 newToString); + + /** + * When creating a "derived" LogLevel, a StringToLogLevelMethod + * should be defined and registered with the LogLevelManager by calling + * this method. + * + * @see pushToStringMethod + */ + void pushFromStringMethod(StringToLogLevelMethod newFromString); + + private: + // Data + struct LogLevelToStringMethodRec + { + union + { + LogLevelToStringMethod func; + LogLevelToStringMethod_1_0 func_1_0; + }; + bool use_1_0; + }; + + typedef std::vector LogLevelToStringMethodList; + LogLevelToStringMethodList toStringMethods; + + typedef std::vector StringToLogLevelMethodList; + StringToLogLevelMethodList fromStringMethods; + + // Disable Copy + LogLevelManager(const LogLevelManager&); + LogLevelManager& operator=(const LogLevelManager&); + }; + + /** + * Returns the singleton LogLevelManager. + */ + LOG4CPLUS_EXPORT LogLevelManager& getLogLevelManager(); + +} + + +#endif // LOG4CPLUS_LOGLEVEL_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/mdc.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/mdc.h new file mode 100644 index 0000000..ff23774 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/mdc.h @@ -0,0 +1,77 @@ +// -*- C++ -*- +// Copyright (C) 2010-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_MDC_H_HEADER +#define LOG4CPLUS_MDC_H_HEADER + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#include + + +namespace log4cplus +{ + + +typedef std::map MappedDiagnosticContextMap; + + +class LOG4CPLUS_EXPORT MDC +{ +public: + /** + * Clear any nested diagnostic information if any. This method is + * useful in cases where the same thread can be potentially used + * over and over in different unrelated contexts. + */ + void clear(); + + void put (tstring const & key, tstring const & value); + bool get (tstring * value, tstring const & key) const; + void remove (tstring const & key); + + MappedDiagnosticContextMap const & getContext () const; + + // Public ctor and dtor but only to be used by internal::DefaultContext. + MDC (); + virtual ~MDC (); + +private: + LOG4CPLUS_PRIVATE static MappedDiagnosticContextMap * getPtr (); +}; + + +LOG4CPLUS_EXPORT MDC & getMDC (); + + +} // namespace log4cplus + + +#endif // LOG4CPLUS_MDC_H_HEADER diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/ndc.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/ndc.h new file mode 100644 index 0000000..26e1b59 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/ndc.h @@ -0,0 +1,332 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: ndc.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file + * This header defined the NDC class. + */ + +#ifndef _LO4CPLUS_NDC_HEADER_ +#define _LO4CPLUS_NDC_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#include +#include + + +namespace log4cplus { + // Forward declarations + struct DiagnosticContext; + typedef std::deque DiagnosticContextStack; + + /** + * The NDC class implements nested diagnostic contexts as + * defined by Neil Harrison in the article "Patterns for Logging + * Diagnostic Messages" part of the book "Pattern Languages of + * Program Design 3" edited by Martin et al. + * + * A Nested Diagnostic Context, or NDC in short, is an instrument + * to distinguish interleaved log output from different sources. Log + * output is typically interleaved when a server handles multiple + * clients near-simultaneously. + * + * Interleaved log output can still be meaningful if each log entry + * from different contexts had a distinctive stamp. This is where NDCs + * come into play. + * + * Note that NDCs are managed on a per thread + * basis. NDC operations such as {@link #push}, {@link + * #pop}, {@link #clear}, {@link #getDepth} and {@link #setMaxDepth} + * affect the NDC of the current thread only. NDCs of other + * threads remain unaffected. + * + * For example, a server can build a per client request NDC + * consisting the clients host name and other information contained in + * the the request. Cookies are another source of distinctive + * information. To build an NDC one uses the {@link #push} + * operation. Simply put, + * + *
    + *
  • Contexts can be nested. + * + *
  • When entering a context, call getNDC().push(). As a + * side effect, if there is no nested diagnostic context for the + * current thread, this method will create it. + * + *
  • When leaving a context, call getNDC().pop(). + * + *
  • When exiting a thread make sure to call {@link #remove + * NDC.remove()}. + *
+ * + * There is no penalty for forgetting to match each + * push operation with a corresponding pop, + * except the obvious mismatch between the real application context + * and the context set in the NDC. Use of the {@link NDCContextCreator} + * class can automate this process and make your code exception-safe. + * + * If configured to do so, {@link log4cplus::PatternLayout} and + * {@link log4cplus::TTCCLayout} instances automatically retrieve + * the nested diagnostic context for the current thread without + * any user intervention. Hence, even if a server is serving + * multiple clients simultaneously, the logs emanating from the + * same code (belonging to the same logger) can still be + * distinguished because each client request will have a different + * NDC tag. + * + * Heavy duty systems should call the {@link #remove} method when + * leaving the run method of a thread. This ensures that the memory + * used by the thread can be freed. + * + * A thread may inherit the nested diagnostic context of another + * (possibly parent) thread using the {@link #inherit inherit} + * method. A thread may obtain a copy of its NDC with the {@link + * #cloneStack cloneStack} method and pass the reference to any other + * thread, in particular to a child. + */ + class LOG4CPLUS_EXPORT NDC + { + public: + /** + * Clear any nested diagnostic information if any. This method is + * useful in cases where the same thread can be potentially used + * over and over in different unrelated contexts. + * + * This method is equivalent to calling the {@link #setMaxDepth} + * method with a zero maxDepth argument. + */ + void clear(); + + /** + * Clone the diagnostic context for the current thread. + * + * Internally a diagnostic context is represented as a stack. A + * given thread can supply the stack (i.e. diagnostic context) to a + * child thread so that the child can inherit the parent thread's + * diagnostic context. + * + * The child thread uses the {@link #inherit inherit} method to + * inherit the parent's diagnostic context. + * + * @return Stack A clone of the current thread's diagnostic context. + */ + DiagnosticContextStack cloneStack() const; + + /** + * Inherit the diagnostic context of another thread. + * + * The parent thread can obtain a reference to its diagnostic + * context using the {@link #cloneStack} method. It should + * communicate this information to its child so that it may inherit + * the parent's diagnostic context. + * + * The parent's diagnostic context is cloned before being + * inherited. In other words, once inherited, the two diagnostic + * contexts can be managed independently. + * + * @param stack The diagnostic context of the parent thread. + */ + void inherit(const DiagnosticContextStack& stack); + + /** + * Used when printing the diagnostic context. + */ + log4cplus::tstring const & get() const; + + /** + * Get the current nesting depth of this diagnostic context. + * + * @see #setMaxDepth + */ + std::size_t getDepth() const; + + /** + * Clients should call this method before leaving a diagnostic + * context. + * + * The returned value is the value that was pushed last. If no + * context is available, then the empty string "" is + * returned. If each call to push() is paired with a call to + * pop() (even in presence of thrown exceptions), the last + * pop() call frees the memory used by NDC for this + * thread. Otherwise, remove() must be called at the end of + * the thread to free the memory used by NDC for the thread. + * + * @return String The innermost diagnostic context. + * + * @see NDCContextCreator, remove(), push() + */ + log4cplus::tstring pop(); + + /** + * Same as pop() but without the return value. + */ + void pop_void (); + + /** + * Looks at the last diagnostic context at the top of this NDC + * without removing it. + * + * The returned value is the value that was pushed last. If no + * context is available, then the empty string "" is returned. + * + * @return String The innermost diagnostic context. + */ + log4cplus::tstring const & peek() const; + + /** + * Push new diagnostic context information for the current thread. + * + * The contents of the message parameter is + * determined solely by the client. Each call to push() should + * be paired with a call to pop(). + * + * @param message The new diagnostic context information. + * + * @see NDCContextCreator, pop(), remove() + */ + void push(const log4cplus::tstring& message); + void push(tchar const * message); + + /** + * Remove the diagnostic context for this thread. + * + * Each thread that created a diagnostic context by calling + * push() should call this method before exiting. Otherwise, + * the memory used by the thread cannot be reclaimed. It is + * possible to omit this call if and only if each push() call + * is always paired with a pop() call (even in presence of + * thrown exceptions). Then the memory used by NDC will be + * returned by the last pop() call and a call to remove() will + * be no-op. + */ + void remove(); + + /** + * Set maximum depth of this diagnostic context. If the current + * depth is smaller or equal to maxDepth, then no + * action is taken. + * + * This method is a convenient alternative to multiple {@link + * #pop} calls. Moreover, it is often the case that at the end of + * complex call sequences, the depth of the NDC is + * unpredictable. The setMaxDepth method circumvents + * this problem. + * + * For example, the combination + *
+         *    void foo() {
+         *       std::size_t depth = NDC.getDepth();
+         *
+         *       ... complex sequence of calls
+         *
+         *       NDC.setMaxDepth(depth);
+         *    }
+         * 
+ * + * ensures that between the entry and exit of foo the depth of the + * diagnostic stack is conserved. + * + * Note: Use of the {@link NDCContextCreator} class will solve + * this particular problem. + * + * @see #getDepth + */ + void setMaxDepth(std::size_t maxDepth); + + // Public ctor but only to be used by internal::DefaultContext. + NDC(); + + // Dtor + virtual ~NDC(); + + private: + // Methods + LOG4CPLUS_PRIVATE static DiagnosticContextStack* getPtr(); + + template + LOG4CPLUS_PRIVATE + void push_worker (StringType const &); + + // Disallow construction (and copying) except by getNDC() + NDC(const NDC&); + NDC& operator=(const NDC&); + }; + + + /** + * Return a reference to the singleton object. + */ + LOG4CPLUS_EXPORT NDC& getNDC(); + + + /** + * This is the internal object that is stored on the NDC stack. + */ + struct LOG4CPLUS_EXPORT DiagnosticContext + { + // Ctors + DiagnosticContext(const log4cplus::tstring& message, + DiagnosticContext const * parent); + DiagnosticContext(tchar const * message, + DiagnosticContext const * parent); + DiagnosticContext(const log4cplus::tstring& message); + DiagnosticContext(tchar const * message); + DiagnosticContext(DiagnosticContext const &); + DiagnosticContext & operator = (DiagnosticContext const &); + +#if defined (LOG4CPLUS_HAVE_RVALUE_REFS) + DiagnosticContext(DiagnosticContext &&); + DiagnosticContext & operator = (DiagnosticContext &&); +#endif + + void swap (DiagnosticContext &); + + // Data + log4cplus::tstring message; /*!< The message at this context level. */ + log4cplus::tstring fullMessage; /*!< The entire message stack. */ + }; + + + /** + * This class ensures that a {@link NDC#push} call is always matched with + * a {@link NDC#pop} call even in the face of exceptions. + */ + class LOG4CPLUS_EXPORT NDCContextCreator { + public: + /** Pushes msg onto the NDC stack. */ + NDCContextCreator(const log4cplus::tstring& msg); + NDCContextCreator(tchar const * msg); + + /** Pops the NDC stack. */ + ~NDCContextCreator(); + }; + +} // end namespace log4cplus + + +#endif // _LO4CPLUS_NDC_HEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/nteventlogappender.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/nteventlogappender.h new file mode 100644 index 0000000..9ea3a89 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/nteventlogappender.h @@ -0,0 +1,84 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: nteventlogappender.h +// Created: 4/2003 +// Author: Michael CATANZARITI +// +// Copyright 2003-2013 Michael CATANZARITI +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_NT_EVENT_LOG_APPENDER_HEADER_ +#define LOG4CPLUS_NT_EVENT_LOG_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (LOG4CPLUS_HAVE_NT_EVENT_LOG) + +#include +#include + + +namespace log4cplus { + + /** + * Appends log events to NT EventLog. + */ + class LOG4CPLUS_EXPORT NTEventLogAppender : public Appender { + public: + // ctors + NTEventLogAppender(const log4cplus::tstring& server, + const log4cplus::tstring& log, + const log4cplus::tstring& source); + NTEventLogAppender(const log4cplus::helpers::Properties & properties); + + // dtor + virtual ~NTEventLogAppender(); + + // public Methods + virtual void close(); + + protected: + virtual void append(const spi::InternalLoggingEvent& event); + virtual WORD getEventType(const spi::InternalLoggingEvent& event); + virtual WORD getEventCategory(const spi::InternalLoggingEvent& event); + void init(); + + /* + * Add this source with appropriate configuration keys to the registry. + */ + void addRegistryInfo(); + + // Data + log4cplus::tstring server; + log4cplus::tstring log; + log4cplus::tstring source; + HANDLE hEventLog; + SID* pCurrentUserSID; + + private: + // Disallow copying of instances of this class + NTEventLogAppender(const NTEventLogAppender&); + NTEventLogAppender& operator=(const NTEventLogAppender&); + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_HAVE_NT_EVENT_LOG +#endif //LOG4CPLUS_NT_EVENT_LOG_APPENDER_HEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/nullappender.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/nullappender.h new file mode 100644 index 0000000..15456fc --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/nullappender.h @@ -0,0 +1,65 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: nullappender.h +// Created: 6/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_NULL_APPENDER_HEADER_ +#define LOG4CPLUS_NULL_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + + +namespace log4cplus { + + /** + * Appends log events to a file. + */ + class LOG4CPLUS_EXPORT NullAppender : public Appender { + public: + // Ctors + NullAppender(); + NullAppender(const log4cplus::helpers::Properties&); + + // Dtor + virtual ~NullAppender(); + + // Methods + virtual void close(); + + protected: + virtual void append(const log4cplus::spi::InternalLoggingEvent& event); + + private: + // Disallow copying of instances of this class + NullAppender(const NullAppender&); + NullAppender& operator=(const NullAppender&); + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_NULL_APPENDER_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/qt4debugappender.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/qt4debugappender.h new file mode 100644 index 0000000..8908a6e --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/qt4debugappender.h @@ -0,0 +1,103 @@ +// -*- C++ -*- +// Module: Log4cplus +// File: qt4debugappender.h +// Created: 5/2012 +// Author: Vaclav Zeman +// +// +// Copyright (C) 2012-2013, Vaclav Zeman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// + +/** @file */ + +#ifndef LOG4CPLUS_QT4DEBUGAPPENDER_H +#define LOG4CPLUS_QT4DEBUGAPPENDER_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#if defined (_WIN32) + #if defined (log4cplusqt4debugappender_EXPORTS) \ + || defined (log4cplusqt4debugappenderU_EXPORTS) \ + || defined (DLL_EXPORT) + #undef LOG4CPLUS_QT4DEBUGAPPENDER_BUILD_DLL + #define LOG4CPLUS_QT4DEBUGAPPENDER_BUILD_DLL + #endif + #if defined (LOG4CPLUS_QT4DEBUGAPPENDER_BUILD_DLL) + #if defined (INSIDE_LOG4CPLUS_QT4DEBUGAPPENDER) + #define LOG4CPLUS_QT4DEBUGAPPENDER_EXPORT __declspec(dllexport) + #else + #define LOG4CPLUS_QT4DEBUGAPPENDER_EXPORT __declspec(dllimport) + #endif + #else + #define LOG4CPLUS_QT4DEBUGAPPENDER_EXPORT + #endif +#else + #if defined (INSIDE_LOG4CPLUS_QT4DEBUGAPPENDER) + #define LOG4CPLUS_QT4DEBUGAPPENDER_EXPORT LOG4CPLUS_DECLSPEC_EXPORT + #else + #define LOG4CPLUS_QT4DEBUGAPPENDER_EXPORT LOG4CPLUS_DECLSPEC_IMPORT + #endif // defined (INSIDE_LOG4CPLUS_QT4DEBUGAPPENDER) +#endif // !_WIN32 + + +namespace log4cplus +{ + + +class LOG4CPLUS_QT4DEBUGAPPENDER_EXPORT Qt4DebugAppender + : public Appender +{ +public: + Qt4DebugAppender (); + explicit Qt4DebugAppender (helpers::Properties const &); + virtual ~Qt4DebugAppender (); + + virtual void close (); + + static void registerAppender (); + +protected: + virtual void append (spi::InternalLoggingEvent const &); + +private: + Qt4DebugAppender (Qt4DebugAppender const &); + Qt4DebugAppender & operator = (Qt4DebugAppender const &); +}; + + +typedef helpers::SharedObjectPtr Qt4DebugAppenderPtr; + + +} // namespace log4cplus + + +#endif // LOG4CPLUS_QT4DEBUGAPPENDER_H diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/socketappender.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/socketappender.h new file mode 100644 index 0000000..a288c51 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/socketappender.h @@ -0,0 +1,170 @@ +// -*- C++ -*- +// Module: LOG4CPLUS +// File: socketappender.h +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SOCKET_APPENDER_HEADER_ +#define LOG4CPLUS_SOCKET_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + + +namespace log4cplus +{ + + +#ifndef UNICODE + std::size_t const LOG4CPLUS_MAX_MESSAGE_SIZE = 8*1024; +#else + std::size_t const LOG4CPLUS_MAX_MESSAGE_SIZE = 2*8*1024; +#endif + + + /** + * Sends {@link spi::InternalLoggingEvent} objects to a remote a log server. + * + * The SocketAppender has the following properties: + * + *
    + * + *
  • Remote logging is non-intrusive as far as the log event + * is concerned. In other words, the event will be logged with + * the same time stamp, NDC, location info as if it were logged + * locally by the client. + * + *
  • SocketAppenders do not use a layout. + * + *
  • Remote logging uses the TCP protocol. Consequently, if + * the server is reachable, then log events will eventually arrive + * at the server. + * + *
  • If the remote server is down, the logging requests are + * simply dropped. However, if and when the server comes back up, + * then event transmission is resumed transparently. This + * transparent reconneciton is performed by a connector + * thread which periodically attempts to connect to the server. + * + *
  • Logging events are automatically buffered by the + * native TCP implementation. This means that if the link to server + * is slow but still faster than the rate of (log) event production + * by the client, the client will not be affected by the slow + * network connection. However, if the network connection is slower + * then the rate of event production, then the client can only + * progress at the network rate. In particular, if the network link + * to the the server is down, the client will be blocked. + * + *
  • On the other hand, if the network link is up, but the server + * is down, the client will not be blocked when making log requests + * but the log events will be lost due to server unavailability. + *
+ * + *

Properties

+ *
+ *
host
+ *
Remote host name to connect and send events to.
+ * + *
port
+ *
Port on remote host to send events to.
+ * + *
ServerName
+ *
Host name of event's origin prepended to each event.
+ * + *
+ */ + class LOG4CPLUS_EXPORT SocketAppender : public Appender { + public: + // Ctors + SocketAppender(const log4cplus::tstring& host, unsigned short port, + const log4cplus::tstring& serverName = tstring()); + SocketAppender(const log4cplus::helpers::Properties & properties); + + // Dtor + ~SocketAppender(); + + // Methods + virtual void close(); + + protected: + void openSocket(); + void initConnector (); + virtual void append(const spi::InternalLoggingEvent& event); + + // Data + log4cplus::helpers::Socket socket; + log4cplus::tstring host; + unsigned int port; + log4cplus::tstring serverName; + +#if ! defined (LOG4CPLUS_SINGLE_THREADED) + class LOG4CPLUS_EXPORT ConnectorThread; + friend class ConnectorThread; + + class LOG4CPLUS_EXPORT ConnectorThread + : public thread::AbstractThread + { + public: + ConnectorThread (SocketAppender &); + virtual ~ConnectorThread (); + + virtual void run(); + + void terminate (); + void trigger (); + + protected: + SocketAppender & sa; + thread::ManualResetEvent trigger_ev; + bool exit_flag; + }; + + volatile bool connected; + helpers::SharedObjectPtr connector; +#endif + + private: + // Disallow copying of instances of this class + SocketAppender(const SocketAppender&); + SocketAppender& operator=(const SocketAppender&); + }; + + namespace helpers { + LOG4CPLUS_EXPORT + void convertToBuffer (SocketBuffer & buffer, + const log4cplus::spi::InternalLoggingEvent& event, + const log4cplus::tstring& serverName); + + LOG4CPLUS_EXPORT + log4cplus::spi::InternalLoggingEvent readFromBuffer(SocketBuffer& buffer); + } // end namespace helpers + +} // end namespace log4cplus + +#endif // LOG4CPLUS_SOCKET_APPENDER_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/appenderattachable.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/appenderattachable.h new file mode 100644 index 0000000..986bf9b --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/appenderattachable.h @@ -0,0 +1,90 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: appenderattachable.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_APPENDER_ATTACHABLE_HEADER_ +#define LOG4CPLUS_SPI_APPENDER_ATTACHABLE_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include + +namespace log4cplus { + // Forward Declarations + typedef helpers::SharedObjectPtr SharedAppenderPtr; + typedef std::vector SharedAppenderPtrList; + + namespace spi { + + /** + * This Interface is for attaching Appenders to objects. + */ + class LOG4CPLUS_EXPORT AppenderAttachable { + public: + // Methods + /** + * Add an appender. + */ + virtual void addAppender(SharedAppenderPtr newAppender) = 0; + + /** + * Get all previously added appenders as an Enumeration. + */ + virtual SharedAppenderPtrList getAllAppenders() = 0; + + /** + * Get an appender by name. + */ + virtual SharedAppenderPtr getAppender(const log4cplus::tstring& name) = 0; + + /** + * Remove all previously added appenders. + */ + virtual void removeAllAppenders() = 0; + + /** + * Remove the appender passed as parameter from the list of appenders. + */ + virtual void removeAppender(SharedAppenderPtr appender) = 0; + + /** + * Remove the appender with the name passed as parameter from the + * list of appenders. + */ + virtual void removeAppender(const log4cplus::tstring& name) = 0; + + // Dtor + virtual ~AppenderAttachable() = 0; + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif // LOG4CPLUS_SPI_APPENDER_ATTACHABLE_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/factory.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/factory.h new file mode 100644 index 0000000..709edf5 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/factory.h @@ -0,0 +1,273 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: factory.h +// Created: 2/2002 +// Author: Tad E. Smith +// +// +// Copyright 2002-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_FACTORY_HEADER_ +#define LOG4CPLUS_SPI_FACTORY_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace log4cplus { + namespace spi { + + /** + * This is the base class for all factories. + */ + class LOG4CPLUS_EXPORT BaseFactory { + public: + virtual ~BaseFactory() = 0; + + /** + * Returns the typename of the objects this factory creates. + */ + virtual log4cplus::tstring const & getTypeName() const = 0; + }; + + + /** + * This abstract class defines the "Factory" interface to create "Appender" + * objects. + */ + class LOG4CPLUS_EXPORT AppenderFactory : public BaseFactory { + public: + typedef Appender ProductType; + typedef SharedAppenderPtr ProductPtr; + + AppenderFactory(); + virtual ~AppenderFactory() = 0; + + /** + * Create an "Appender" object. + */ + virtual SharedAppenderPtr createObject(const log4cplus::helpers::Properties& props) = 0; + }; + + + + /** + * This abstract class defines the "Factory" interface to create "Layout" + * objects. + */ + class LOG4CPLUS_EXPORT LayoutFactory : public BaseFactory { + public: + typedef Layout ProductType; + typedef std::auto_ptr ProductPtr; + + LayoutFactory(); + virtual ~LayoutFactory() = 0; + + /** + * Create a "Layout" object. + */ + virtual std::auto_ptr createObject(const log4cplus::helpers::Properties& props) = 0; + }; + + + + /** + * This abstract class defines the "Factory" interface to create "Appender" + * objects. + */ + class LOG4CPLUS_EXPORT FilterFactory : public BaseFactory { + public: + typedef Filter ProductType; + typedef FilterPtr ProductPtr; + + FilterFactory(); + virtual ~FilterFactory() = 0; + + /** + * Create a "Filter" object. + */ + virtual FilterPtr createObject(const log4cplus::helpers::Properties& props) = 0; + }; + + + /** + * This abstract class defines the "Factory" interface to + * create std::locale instances. + */ + class LOG4CPLUS_EXPORT LocaleFactory + : public BaseFactory + { + public: + typedef std::locale ProductType; + typedef std::locale ProductPtr; + + LocaleFactory(); + virtual ~LocaleFactory() = 0; + + //! \returns std::locale instance + virtual ProductPtr createObject ( + const log4cplus::helpers::Properties & props) = 0; + }; + + + /** + * This template class is used as a "Factory Registry". Objects are + * "entered" into the registry with a "name" using the + * put() method. (The registry then owns the object.) + * These object can then be retrieved using the get() + * method. + * + * Note: This class is Thread-safe. + */ + template + class LOG4CPLUS_EXPORT FactoryRegistry : ObjectRegistryBase { + public: + typedef T product_type; + + virtual ~FactoryRegistry() { + clear(); + } + + // public methods + /** + * Used to enter an object into the registry. (The registry now + * owns object.) + */ + bool put(std::auto_ptr object) { + bool putValResult = putVal(object->getTypeName(), object.get()); + object.release(); + return putValResult; + } + + /** + * Used to retrieve an object from the registry. (The registry + * owns the returned pointer.) + */ + T* get(const log4cplus::tstring& name) const { + return static_cast(getVal(name)); + } + + protected: + virtual void deleteObject(void *object) const { + delete static_cast(object); + } + }; + + + typedef FactoryRegistry AppenderFactoryRegistry; + typedef FactoryRegistry LayoutFactoryRegistry; + typedef FactoryRegistry FilterFactoryRegistry; + typedef FactoryRegistry LocaleFactoryRegistry; + + + /** + * Returns the "singleton" AppenderFactoryRegistry. + */ + LOG4CPLUS_EXPORT AppenderFactoryRegistry& getAppenderFactoryRegistry(); + + /** + * Returns the "singleton" LayoutFactoryRegistry. + */ + LOG4CPLUS_EXPORT LayoutFactoryRegistry& getLayoutFactoryRegistry(); + + /** + * Returns the "singleton" FilterFactoryRegistry. + */ + LOG4CPLUS_EXPORT FilterFactoryRegistry& getFilterFactoryRegistry(); + + /** + * Returns the "singleton" LocaleFactoryRegistry. + */ + LOG4CPLUS_EXPORT LocaleFactoryRegistry& getLocaleFactoryRegistry(); + + + template + class LocalFactoryBase + : public ProductFactoryBase + { + public: + LocalFactoryBase (tchar const * n) + : name (n) + { } + + virtual log4cplus::tstring const & getTypeName() const + { + return name; + } + + private: + log4cplus::tstring name; + }; + + + template + class FactoryTempl + : public LocalFactoryBase + { + public: + typedef typename ProductFactoryBase::ProductPtr ProductPtr; + + FactoryTempl (tchar const * n) + : LocalFactoryBase (n) + { } + + virtual ProductPtr createObject (helpers::Properties const & props) + { + return ProductPtr (new LocalProduct (props)); + } + }; + + + #define LOG4CPLUS_REG_PRODUCT(reg, productprefix, productname, productns, productfact) \ + reg.put ( \ + std::auto_ptr ( \ + new log4cplus::spi::FactoryTempl ( \ + LOG4CPLUS_TEXT(productprefix) \ + LOG4CPLUS_TEXT(#productname)))) + + #define LOG4CPLUS_REG_APPENDER(reg, appendername) \ + LOG4CPLUS_REG_PRODUCT (reg, "log4cplus::", appendername, log4cplus::, \ + log4cplus::spi::AppenderFactory) + + #define LOG4CPLUS_REG_LAYOUT(reg, layoutname) \ + LOG4CPLUS_REG_PRODUCT (reg, "log4cplus::", layoutname, log4cplus::, \ + log4cplus::spi::LayoutFactory) + + #define LOG4CPLUS_REG_FILTER(reg, filtername) \ + LOG4CPLUS_REG_PRODUCT (reg, "log4cplus::spi::", filtername, log4cplus::spi::, \ + log4cplus::spi::FilterFactory) + + #define LOG4CPLUS_REG_LOCALE(reg, name, factory) \ + reg.put (std::auto_ptr ( \ + new factory (name))) + } // namespace spi +} + + +#endif // LOG4CPLUS_SPI_FACTORY_HEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/filter.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/filter.h new file mode 100644 index 0000000..1febd23 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/filter.h @@ -0,0 +1,287 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: filter.h +// Created: 5/2003 +// Author: Tad E. Smith +// +// +// Copyright 1999-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file + * This header defines Filter and all of it's subclasses. */ + +#ifndef LOG4CPLUS_SPI_FILTER_HEADER_ +#define LOG4CPLUS_SPI_FILTER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus { + + namespace helpers + { + + class Properties; + + } + + namespace spi { + + + enum FilterResult { DENY, /**< The log event must be dropped immediately + * without consulting with the remaining + * filters, if any, in the chain. */ + NEUTRAL, /**< This filter is neutral with respect to + * the log event; the remaining filters, if + * if any, should be consulted for a final + * decision. */ + ACCEPT /**< The log event must be logged immediately + * without consulting with the remaining + * filters, if any, in the chain. */ + }; + + // Forward Declarations + class Filter; + class InternalLoggingEvent; + + + /** + * This method is used to filter an InternalLoggingEvent. + * + * Note: filter can be NULL. + */ + LOG4CPLUS_EXPORT FilterResult checkFilter(const Filter* filter, + const InternalLoggingEvent& event); + + typedef helpers::SharedObjectPtr FilterPtr; + + + /** + * Users should extend this class to implement customized logging + * event filtering. Note that the {@link Logger} and {@link + * Appender} classes have built-in filtering rules. It is suggested + * that you first use and understand the built-in rules before rushing + * to write your own custom filters. + * + * This abstract class assumes and also imposes that filters be + * organized in a linear chain. The {@link #decide + * decide(LoggingEvent)} method of each filter is called sequentially, + * in the order of their addition to the chain. + * + * If the value {@link #DENY} is returned, then the log event is + * dropped immediately without consulting with the remaining + * filters. + * + * If the value {@link #NEUTRAL} is returned, then the next filter + * in the chain is consulted. If there are no more filters in the + * chain, then the log event is logged. Thus, in the presence of no + * filters, the default behaviour is to log all logging events. + * + * If the value {@link #ACCEPT} is returned, then the log + * event is logged without consulting the remaining filters. + * + * The philosophy of log4cplus filters is largely inspired from the + * Linux ipchains. + */ + class LOG4CPLUS_EXPORT Filter + : public virtual log4cplus::helpers::SharedObject + { + public: + // ctor and dtor + Filter(); + virtual ~Filter(); + + // Methods + /** + * Appends filter to the end of this filter chain. + */ + void appendFilter(FilterPtr filter); + + /** + * If the decision is DENY, then the event will be + * dropped. If the decision is NEUTRAL, then the next + * filter, if any, will be invoked. If the decision is ACCEPT then + * the event will be logged without consulting with other filters in + * the chain. + * + * @param event The LoggingEvent to decide upon. + * @return The decision of the filter. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const = 0; + + // Data + /** + * Points to the next filter in the filter chain. + */ + FilterPtr next; + }; + + + + /** + * This filter drops all logging events. + * + * You can add this filter to the end of a filter chain to + * switch from the default "accept all unless instructed otherwise" + * filtering behaviour to a "deny all unless instructed otherwise" + * behaviour. + */ + class LOG4CPLUS_EXPORT DenyAllFilter : public Filter { + public: + DenyAllFilter (); + DenyAllFilter (const log4cplus::helpers::Properties&); + + /** + * Always returns the {@link #DENY} regardless of the + * {@link InternalLoggingEvent} parameter. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const; + }; + + + /** + * This is a very simple filter based on LogLevel matching. + * + * The filter admits two options LogLevelToMatch and + * AcceptOnMatch. If there is an exact match between the value + * of the LogLevelToMatch option and the LogLevel of the {@link + * spi::InternalLoggingEvent}, then the {@link #decide} method returns + * {@link #ACCEPT} in case the AcceptOnMatch option value is set + * to true, if it is false then {@link #DENY} + * is returned. If there is no match, {@link #NEUTRAL} is returned. + */ + class LOG4CPLUS_EXPORT LogLevelMatchFilter : public Filter { + public: + LogLevelMatchFilter(); + LogLevelMatchFilter(const log4cplus::helpers::Properties& p); + + /** + * Return the decision of this filter. + * + * Returns {@link #NEUTRAL} if the LogLevelToMatch + * option is not set or if there is no match. Otherwise, if + * there is a match, then the returned decision is {@link #ACCEPT} + * if the AcceptOnMatch property is set to true. + * The returned decision is {@link #DENY} if the AcceptOnMatch + * property is set to false. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const; + + private: + // Methods + LOG4CPLUS_PRIVATE void init(); + + // Data + /** Do we return ACCEPT when a match occurs. Default is true. */ + bool acceptOnMatch; + LogLevel logLevelToMatch; + }; + + + + /** + * This is a very simple filter based on LogLevel matching, which can be + * used to reject messages with LogLevels outside a certain range. + * + * The filter admits three options LogLevelMin, LogLevelMax + * and AcceptOnMatch. + * + * If the LogLevel of the Logging event is not between Min and Max + * (inclusive), then {@link #DENY} is returned. + * + * If the Logging event LogLevel is within the specified range, then if + * AcceptOnMatch is true, {@link #ACCEPT} is returned, and if + * AcceptOnMatch is false, {@link #NEUTRAL} is returned. + * + * If LogLevelMin is not defined, then there is no + * minimum acceptable LogLevel (ie a LogLevel is never rejected for + * being too "low"/unimportant). If LogLevelMax is not + * defined, then there is no maximum acceptable LogLevel (ie a + * LogLevel is never rejected for beeing too "high"/important). + * + * Refer to the {@link + * Appender#setThreshold setThreshold} method + * available to all appenders for a more convenient way to + * filter out events by LogLevel. + */ + class LOG4CPLUS_EXPORT LogLevelRangeFilter : public Filter { + public: + // ctors + LogLevelRangeFilter(); + LogLevelRangeFilter(const log4cplus::helpers::Properties& p); + + /** + * Return the decision of this filter. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const; + + private: + // Methods + LOG4CPLUS_PRIVATE void init(); + + // Data + /** Do we return ACCEPT when a match occurs. Default is true. */ + bool acceptOnMatch; + LogLevel logLevelMin; + LogLevel logLevelMax; + }; + + + + /** + * This is a very simple filter based on string matching. + * + * The filter admits two options StringToMatch and + * AcceptOnMatch. If there is a match between the value of the + * StringToMatch option and the message of the Logging event, + * then the {@link #decide} method returns {@link #ACCEPT} if + * the AcceptOnMatch option value is true, if it is false then + * {@link #DENY} is returned. If there is no match, {@link #NEUTRAL} + * is returned. + */ + class LOG4CPLUS_EXPORT StringMatchFilter : public Filter { + public: + // ctors + StringMatchFilter(); + StringMatchFilter(const log4cplus::helpers::Properties& p); + + /** + * Returns {@link #NEUTRAL} is there is no string match. + */ + virtual FilterResult decide(const InternalLoggingEvent& event) const; + + private: + // Methods + LOG4CPLUS_PRIVATE void init(); + + // Data + /** Do we return ACCEPT when a match occurs. Default is true. */ + bool acceptOnMatch; + log4cplus::tstring stringToMatch; + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif /* LOG4CPLUS_SPI_FILTER_HEADER_ */ + + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/loggerfactory.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/loggerfactory.h new file mode 100644 index 0000000..ad735f1 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/loggerfactory.h @@ -0,0 +1,60 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: loggerfactory.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_LOGGER_FACTORY_HEADER +#define LOG4CPLUS_SPI_LOGGER_FACTORY_HEADER + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + + +namespace log4cplus { + // Forward Declarations + class Logger; + class Hierarchy; + + namespace spi { + /** + * Implement this interface to create new instances of Logger or + * a sub-class of Logger. + */ + class LOG4CPLUS_EXPORT LoggerFactory { + public: + /** + * Creates a new Logger object. + */ + virtual Logger makeNewLoggerInstance(const log4cplus::tstring& name, + Hierarchy& h) = 0; + virtual ~LoggerFactory() = 0; + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif // LOG4CPLUS_SPI_LOGGER_FACTORY_HEADER + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/loggerimpl.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/loggerimpl.h new file mode 100644 index 0000000..c7e4633 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/loggerimpl.h @@ -0,0 +1,219 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: loggerimpl.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_LOGGER_HEADER_ +#define LOG4CPLUS_SPI_LOGGER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include + + +namespace log4cplus { + class DefaultLoggerFactory; + + namespace spi { + + /** + * This is the central class in the log4cplus package. One of the + * distintive features of log4cplus are hierarchical loggers and their + * evaluation. + * + * See the user manual for an + * introduction on this class. + */ + class LOG4CPLUS_EXPORT LoggerImpl + : public virtual log4cplus::helpers::SharedObject, + public log4cplus::helpers::AppenderAttachableImpl + { + public: + typedef helpers::SharedObjectPtr SharedLoggerImplPtr; + + // Methods + + /** + * Call the appenders in the hierrachy starting at + * this. If no appenders could be found, emit a + * warning. + * + * This method calls all the appenders inherited from the + * hierarchy circumventing any evaluation of whether to log or not + * to log the particular log request. + * + * @param event The event to log. + */ + virtual void callAppenders(const InternalLoggingEvent& event); + + /** + * Close all attached appenders implementing the AppenderAttachable + * interface. + */ + virtual void closeNestedAppenders(); + + /** + * Check whether this logger is enabled for a given LogLevel passed + * as parameter. + * + * @return boolean True if this logger is enabled for ll. + */ + virtual bool isEnabledFor(LogLevel ll) const; + + /** + * This generic form is intended to be used by wrappers. + */ + virtual void log(LogLevel ll, const log4cplus::tstring& message, + const char* file=NULL, int line=-1); + + virtual void log(spi::InternalLoggingEvent const &); + + /** + * Starting from this logger, search the logger hierarchy for a + * "set" LogLevel and return it. Otherwise, return the LogLevel of the + * root logger. + * + * The Logger class is designed so that this method executes as + * quickly as possible. + */ + virtual LogLevel getChainedLogLevel() const; + + /** + * Returns the assigned LogLevel, if any, for this Logger. + * + * @return LogLevel - the assigned LogLevel. + */ + LogLevel getLogLevel() const { return this->ll; } + + /** + * Set the LogLevel of this Logger. + */ + void setLogLevel(LogLevel _ll) { this->ll = _ll; } + + /** + * Return the the {@link Hierarchy} where this Logger + * instance is attached. + */ + virtual Hierarchy& getHierarchy() const; + + /** + * Return the logger name. + */ + log4cplus::tstring const & getName() const { return name; } + + /** + * Get the additivity flag for this Logger instance. + */ + bool getAdditivity() const; + + /** + * Set the additivity flag for this Logger instance. + */ + void setAdditivity(bool additive); + + virtual ~LoggerImpl(); + + protected: + // Ctors + /** + * This constructor created a new Logger instance and + * sets its name. + * + * It is intended to be used by sub-classes only. You should not + * create loggers directly. + * + * @param name The name of the logger. + * @param h Hierarchy + */ + LoggerImpl(const log4cplus::tstring& name, Hierarchy& h); + + + // Methods + /** + * This method creates a new logging event and logs the event + * without further checks. + */ + virtual void forcedLog(LogLevel ll, + const log4cplus::tstring& message, + const char* file=NULL, + int line=-1); + + virtual void forcedLog(spi::InternalLoggingEvent const & ev); + + + // Data + /** The name of this logger */ + log4cplus::tstring name; + + /** + * The assigned LogLevel of this logger. + */ + LogLevel ll; + + /** + * The parent of this logger. All loggers have at least one + * ancestor which is the root logger. + */ + SharedLoggerImplPtr parent; + + /** + * Additivity is set to true by default, that is children inherit + * the appenders of their ancestors by default. If this variable is + * set to false then the appenders found in the + * ancestors of this logger are not used. However, the children + * of this logger will inherit its appenders, unless the children + * have their additivity flag set to false too. See + * the user manual for more details. + */ + bool additive; + + private: + // Data + /** Loggers need to know what Hierarchy they are in. */ + Hierarchy& hierarchy; + + // Disallow copying of instances of this class + LoggerImpl(const LoggerImpl&); + LoggerImpl& operator=(const LoggerImpl&); + + // Friends + friend class log4cplus::Logger; + friend class log4cplus::DefaultLoggerFactory; + friend class log4cplus::Hierarchy; + }; + + typedef LoggerImpl::SharedLoggerImplPtr SharedLoggerImplPtr; + + } // end namespace spi +} // end namespace log4cplus + +#endif // LOG4CPLUS_SPI_LOGGER_HEADER_ + + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/loggingevent.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/loggingevent.h new file mode 100644 index 0000000..e57bd6e --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/loggingevent.h @@ -0,0 +1,228 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: loggingevent.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_INTERNAL_LOGGING_EVENT_HEADER_ +#define LOG4CPLUS_SPI_INTERNAL_LOGGING_EVENT_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + +namespace log4cplus { + namespace spi { + /** + * The internal representation of logging events. When an affirmative + * decision is made to log then a InternalLoggingEvent + * instance is created. This instance is passed around to the + * different log4cplus components. + * + * This class is of concern to those wishing to extend log4cplus. + */ + class LOG4CPLUS_EXPORT InternalLoggingEvent { + public: + // Ctors + /** + * Instantiate a LoggingEvent from the supplied parameters. + * + * @param logger The logger of this event. + * @param loglevel The LogLevel of this event. + * @param message The message of this event. + * @param filename Name of file where this event has occurred, + * can be NULL. + * @param line Line number in file specified by + * the filename parameter. + */ + InternalLoggingEvent(const log4cplus::tstring& logger, + LogLevel loglevel, const log4cplus::tstring& message, + const char* filename, int line); + + InternalLoggingEvent(const log4cplus::tstring& logger, + LogLevel loglevel, const log4cplus::tstring& ndc, + MappedDiagnosticContextMap const & mdc, + const log4cplus::tstring& message, + const log4cplus::tstring& thread, + log4cplus::helpers::Time time, const log4cplus::tstring& file, + int line); + + InternalLoggingEvent (); + + InternalLoggingEvent( + const log4cplus::spi::InternalLoggingEvent& rhs); + + virtual ~InternalLoggingEvent(); + + void setLoggingEvent (const log4cplus::tstring & logger, + LogLevel ll, const log4cplus::tstring & message, + const char * filename, int line); + + void setFunction (char const * func); + void setFunction (log4cplus::tstring const &); + + + // public virtual methods + /** The application supplied message of logging event. */ + virtual const log4cplus::tstring& getMessage() const; + + /** Returns the 'type' of InternalLoggingEvent. Derived classes + * should override this method. (NOTE: Values <= 1000 are + * reserved for log4cplus and should not be used.) + */ + virtual unsigned int getType() const; + + /** Returns a copy of this object. Derived classes + * should override this method. + */ + virtual std::auto_ptr clone() const; + + + + // public methods + /** The logger of the logging event. It is set by + * the LoggingEvent constructor. + */ + const log4cplus::tstring& getLoggerName() const + { + return loggerName; + } + + /** LogLevel of logging event. */ + LogLevel getLogLevel() const + { + return ll; + } + + /** The nested diagnostic context (NDC) of logging event. */ + const log4cplus::tstring& getNDC() const + { + if (!ndcCached) + { + ndc = log4cplus::getNDC().get(); + ndcCached = true; + } + return ndc; + } + + MappedDiagnosticContextMap const & getMDCCopy () const + { + if (!mdcCached) + { + mdc = log4cplus::getMDC().getContext (); + mdcCached = true; + } + return mdc; + } + + tstring const & getMDC (tstring const & key) const; + + /** The name of thread in which this logging event was generated. */ + const log4cplus::tstring& getThread() const + { + if (! threadCached) + { + thread = thread::getCurrentThreadName (); + threadCached = true; + } + return thread; + } + + //! The alternative name of thread in which this logging event + //! was generated. + const log4cplus::tstring& getThread2() const + { + if (! thread2Cached) + { + thread2 = thread::getCurrentThreadName2 (); + thread2Cached = true; + } + return thread2; + } + + + /** The number of milliseconds elapsed from 1/1/1970 until + * logging event was created. */ + const log4cplus::helpers::Time& getTimestamp() const + { + return timestamp; + } + + /** The is the file where this log statement was written */ + const log4cplus::tstring& getFile() const + { + return file; + } + + /** The is the line where this log statement was written */ + int getLine() const { return line; } + + log4cplus::tstring const & getFunction () const + { + return function; + } + + void gatherThreadSpecificData () const; + + void swap (InternalLoggingEvent &); + + // public operators + log4cplus::spi::InternalLoggingEvent& + operator=(const log4cplus::spi::InternalLoggingEvent& rhs); + + // static methods + static unsigned int getDefaultType(); + + protected: + // Data + log4cplus::tstring message; + log4cplus::tstring loggerName; + LogLevel ll; + mutable log4cplus::tstring ndc; + mutable MappedDiagnosticContextMap mdc; + mutable log4cplus::tstring thread; + mutable log4cplus::tstring thread2; + log4cplus::helpers::Time timestamp; + log4cplus::tstring file; + log4cplus::tstring function; + int line; + /** Indicates whether or not the Threadname has been retrieved. */ + mutable bool threadCached; + mutable bool thread2Cached; + /** Indicates whether or not the NDC has been retrieved. */ + mutable bool ndcCached; + /** Indicates whether or not the MDC has been retrieved. */ + mutable bool mdcCached; + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif // LOG4CPLUS_SPI_INTERNAL_LOGGING_EVENT_HEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/objectregistry.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/objectregistry.h new file mode 100644 index 0000000..d059474 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/objectregistry.h @@ -0,0 +1,106 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: objectregistry.h +// Created: 3/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_OBJECT_REGISTRY_HEADER_ +#define LOG4CPLUS_SPI_OBJECT_REGISTRY_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include +#include +#include +#include + + +namespace log4cplus { + namespace spi { + + /** + * This is the base class used to implement the functionality required + * by the ObjectRegistry template class. + */ + class LOG4CPLUS_EXPORT ObjectRegistryBase { + public: + // public methods + /** + * Tests to see whether or not an object is bound in the + * registry as name. + */ + bool exists(const log4cplus::tstring& name) const; + + /** + * Returns the names of all registered objects. + */ + std::vector getAllNames() const; + + protected: + // Ctor and Dtor + ObjectRegistryBase(); + virtual ~ObjectRegistryBase(); + + // protected methods + /** + * Used to enter an object into the registry. (The registry now + * owns object.) + */ + bool putVal(const log4cplus::tstring& name, void* object); + + /** + * Used to retrieve an object from the registry. (The registry + * owns the returned pointer.) + */ + void* getVal(const log4cplus::tstring& name) const; + + /** + * Deletes object. + */ + virtual void deleteObject(void *object) const = 0; + + /** + * Deletes all objects from this registry. + */ + virtual void clear(); + + // Types + typedef std::map ObjectMap; + + // Data + thread::Mutex mutex; + ObjectMap data; + + private: + ObjectRegistryBase (ObjectRegistryBase const &); + ObjectRegistryBase & operator = (ObjectRegistryBase const &); + }; + + } +} + + +#endif // LOG4CPLUS_SPI_OBJECT_REGISTRY_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/rootlogger.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/rootlogger.h new file mode 100644 index 0000000..6c466c2 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/spi/rootlogger.h @@ -0,0 +1,75 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: rootlogger.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SPI_ROOT_LOGGER_HEADER_ +#define LOG4CPLUS_SPI_ROOT_LOGGER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +namespace log4cplus { + namespace spi { + + /** + * RootLogger sits at the top of the logger hierachy. It is a + * regular logger except that it provides several guarantees. + * + * First, it cannot be assigned a NOT_SET_LOG_LEVEL + * LogLevel. Second, since root logger cannot have a parent, the + * getChainedLogLevel method always returns the value of the + * ll field without walking the hierarchy. + */ + class LOG4CPLUS_EXPORT RootLogger : public LoggerImpl { + public: + // Ctors + /** + * The root logger names itself as "root". However, the root + * logger cannot be retrieved by name. + */ + RootLogger(Hierarchy& h, LogLevel ll); + + // Methods + /** + * Return the assigned LogLevel value without walking the logger + * hierarchy. + */ + virtual LogLevel getChainedLogLevel() const; + + /** + * Setting a NOT_SET_LOG_LEVEL value to the LogLevel of the root logger + * may have catastrophic results. We prevent this here. + */ + void setLogLevel(LogLevel ll); + + }; + + } // end namespace spi +} // end namespace log4cplus + +#endif // LOG4CPLUS_SPI_ROOT_LOGGER_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/stamp-h1 b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/stamp-h1 new file mode 100644 index 0000000..6218c71 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/stamp-h1 @@ -0,0 +1 @@ +timestamp for include/log4cplus/config.h diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/streams.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/streams.h new file mode 100644 index 0000000..df33c4d --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/streams.h @@ -0,0 +1,55 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: streams.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_STREAMS_HEADER_ +#define LOG4CPLUS_STREAMS_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + +#include + + +namespace log4cplus +{ + typedef std::basic_ostream tostream; + typedef std::basic_istream tistream; + typedef std::basic_ostringstream tostringstream; + typedef std::basic_istringstream tistringstream; + extern LOG4CPLUS_EXPORT tostream & tcout; + extern LOG4CPLUS_EXPORT tostream & tcerr; +} + +#if defined (UNICODE) && defined (LOG4CPLUS_ENABLE_GLOBAL_C_STRING_STREAM_INSERTER) + +LOG4CPLUS_EXPORT log4cplus::tostream& operator <<(log4cplus::tostream&, const char* psz ); + +#endif + +#endif // LOG4CPLUS_STREAMS_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/syslogappender.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/syslogappender.h new file mode 100644 index 0000000..60e06bd --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/syslogappender.h @@ -0,0 +1,118 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: syslogappender.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_SYSLOG_APPENDER_HEADER_ +#define LOG4CPLUS_SYSLOG_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus +{ + + /** + * Appends log events to a file. + * + *

Properties

+ *
+ *
ident
+ *
First argument to openlog(), a string that + * will be prepended to every message.
+ * + *
facility
+ *
Facility is used in combination with syslog level in first + * argument to syslog(). It can be one of the supported facility + * names (case insensitive), e.g. auth, cron, kern, mail, news + * etc.
+ * + *
host
+ *
Destination syslog host. When this property is specified, + * messages are sent using UDP to destination host, otherwise + * messages are logged to local syslog.
+ * + *
port
+ *
Destination port of syslog service on host specified by the + * host property. The default value is port 514.
+ *
+ * + * \note Messages sent to remote syslog using UDP are conforming + * to RFC5424. + */ + class LOG4CPLUS_EXPORT SysLogAppender : public Appender { + public: + // Ctors +#if defined (LOG4CPLUS_HAVE_SYSLOG_H) + SysLogAppender(const tstring& ident); +#endif + SysLogAppender(const tstring& ident, const tstring & host, + int port = 514, const tstring & facility = tstring ()); + SysLogAppender(const log4cplus::helpers::Properties & properties); + + // Dtor + virtual ~SysLogAppender(); + + // Methods + virtual void close(); + + protected: + virtual int getSysLogLevel(const LogLevel& ll) const; + virtual void append(const spi::InternalLoggingEvent& event); +#if defined (LOG4CPLUS_HAVE_SYSLOG_H) + void appendLocal(const spi::InternalLoggingEvent& event); +#endif + void appendRemote(const spi::InternalLoggingEvent& event); + + // Data + tstring ident; + int facility; + + typedef void (SysLogAppender:: * AppendFuncType) ( + const spi::InternalLoggingEvent&); + AppendFuncType appendFunc; + + tstring host; + int port; + helpers::Socket syslogSocket; + + static tstring const remoteTimeFormat; + + private: + // Disallow copying of instances of this class + SysLogAppender(const SysLogAppender&); + SysLogAppender& operator=(const SysLogAppender&); + + std::string identStr; + tstring hostname; + }; + +} // end namespace log4cplus + + +#endif // LOG4CPLUS_SYSLOG_APPENDER_HEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/tchar.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/tchar.h new file mode 100644 index 0000000..217fc76 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/tchar.h @@ -0,0 +1,63 @@ +// -*- C++ -*- +// Copyright (C) 2010-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +/** @file */ + +#ifndef LOG4CPLUS_TCHAR_HEADER_ +#define LOG4CPLUS_TCHAR_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (_WIN32) +#include +#endif + + +#ifdef UNICODE +# define LOG4CPLUS_TEXT2(STRING) L##STRING +#else +# define LOG4CPLUS_TEXT2(STRING) STRING +#endif // UNICODE +#define LOG4CPLUS_TEXT(STRING) LOG4CPLUS_TEXT2(STRING) + + +namespace log4cplus +{ + +#if defined (UNICODE) +typedef wchar_t tchar; + +#else +typedef char tchar; + +#endif + +} // namespace log4cplus + + +#endif // LOG4CPLUS_TCHAR_HEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/impl/syncprims-impl.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/impl/syncprims-impl.h new file mode 100644 index 0000000..6a2df91 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/impl/syncprims-impl.h @@ -0,0 +1,240 @@ +// -*- C++ -*- +// Copyright (C) 2009-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_THREAD_SYNCPRIMS_IMPL_H +#define LOG4CPLUS_THREAD_SYNCPRIMS_IMPL_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + +#include +#include +#if defined (_WIN32) +# include + +#elif defined (LOG4CPLUS_USE_PTHREADS) +# include +# include +# include +# if defined (LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE) +# include +# include +# if defined (LOG4CPLUS_HAVE_SYS_TYPES_H) +# include +# endif +# if defined (LOG4CPLUS_HAVE_UNISTD_H) +# include +# endif +# endif +# if defined (LOG4CPLUS_HAVE_FCNTL_H) +# include +# endif +# include + +#endif + + +namespace log4cplus { namespace thread { namespace impl { + + +LOG4CPLUS_EXPORT void LOG4CPLUS_ATTRIBUTE_NORETURN + syncprims_throw_exception (char const * const msg, + char const * const file, int line); + + +#define LOG4CPLUS_THROW_RTE(msg) \ + do { syncprims_throw_exception (msg, __FILE__, __LINE__); } while (0) + + +class ManualResetEvent; + + +class Mutex + : public MutexImplBase +{ +public: + explicit Mutex (log4cplus::thread::Mutex::Type); + ~Mutex (); + + void lock () const; + void unlock () const; + +private: +#if defined (LOG4CPLUS_USE_PTHREADS) + mutable pthread_mutex_t mtx; + friend class ManualResetEvent; +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) + mutable CRITICAL_SECTION cs; +#endif + + Mutex (Mutex const &); + Mutex & operator = (Mutex &); +}; + + +typedef SyncGuard MutexGuard; + + +class Semaphore + : public SemaphoreImplBase +{ +public: + Semaphore (unsigned max, unsigned initial); + ~Semaphore (); + + void lock () const; + void unlock () const; + +private: +#if defined (LOG4CPLUS_USE_PTHREADS) +# if defined (LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE) + sem_t * sem; +# else + mutable sem_t sem; +# endif +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) + HANDLE sem; +#endif + + Semaphore (Semaphore const &); + Semaphore & operator = (Semaphore const &); +}; + + +typedef SyncGuard SemaphoreGuard; + + +class FairMutex + : public FairMutexImplBase +{ +public: + FairMutex (); + ~FairMutex (); + + void lock () const; + void unlock () const; + +private: +#if defined (LOG4CPLUS_USE_PTHREADS) + Semaphore sem; +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) + HANDLE mtx; +#endif + + FairMutex (FairMutex const &); + FairMutex & operator = (FairMutex &); +}; + + +typedef SyncGuard FairMutexGuard; + + +class ManualResetEvent + : public ManualResetEventImplBase +{ +public: + ManualResetEvent (bool = false); + ~ManualResetEvent (); + + void signal () const; + void wait () const; + bool timed_wait (unsigned long msec) const; + void reset () const; + +private: +#if defined (LOG4CPLUS_USE_PTHREADS) + mutable pthread_cond_t cv; + mutable Mutex mtx; + mutable volatile unsigned sigcount; + mutable volatile bool signaled; +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) + HANDLE ev; +#endif + + ManualResetEvent (ManualResetEvent const &); + ManualResetEvent & operator = (ManualResetEvent const &); +}; + + +class SharedMutex + : public SharedMutexImplBase +{ +public: + SharedMutex (); + ~SharedMutex (); + + void rdlock () const; + void wrlock () const; + void rdunlock () const; + void wrunlock () const; + +private: +#if defined (LOG4CPLUS_POOR_MANS_SHAREDMUTEX) + Mutex m1; + Mutex m2; + Mutex m3; + Semaphore w; + mutable unsigned writer_count; + Semaphore r; + mutable unsigned reader_count; + +#elif defined (LOG4CPLUS_USE_PTHREADS) + void unlock () const; + + mutable pthread_rwlock_t rwl; + +#elif defined (LOG4CPLUS_USE_SRW_LOCK) + mutable SRWLOCK srwl; + +#endif + + SharedMutex (SharedMutex const &); + SharedMutex & operator = (SharedMutex const &); +}; + + +} } } // namespace log4cplus { namespace thread { namespace impl { + + +// Include the appropriate implementations of the classes declared +// above. + +#if defined (LOG4CPLUS_USE_PTHREADS) +# include +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) +# include +#endif + + +#undef LOG4CPLUS_THROW_RTE + + +#endif // LOG4CPLUS_THREAD_SYNCPRIMS_IMPL_H diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/impl/syncprims-pmsm.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/impl/syncprims-pmsm.h new file mode 100644 index 0000000..34b315d --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/impl/syncprims-pmsm.h @@ -0,0 +1,119 @@ +// -*- C++ -*- +// Copyright (C) 2010-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//! @file +//! This file contains implementations of reader-writer locking +//! primitive using other primitives, IOW poor man's rwlock. +//! It does not contain any include guards because it is only a fragment +//! to be included by syncprims-{pthreads,win32}.h. + + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + + +// This implements algorithm described in "Concurrent Control with "Readers" +// and "Writers"; P.J. Courtois, F. Heymans, and D.L. Parnas; +// MBLE Research Laboratory; Brussels, Belgium" + + +inline +SharedMutex::SharedMutex () + : m1 (log4cplus::thread::Mutex::DEFAULT) + , m2 (log4cplus::thread::Mutex::DEFAULT) + , m3 (log4cplus::thread::Mutex::DEFAULT) + , w (1, 1) + , writer_count (0) + , r (1, 1) + , reader_count (0) +{ } + + +inline +SharedMutex::~SharedMutex () +{ } + + +inline +void +SharedMutex::rdlock () const +{ + MutexGuard m3_guard (m3); + SemaphoreGuard r_guard (r); + MutexGuard m1_guard (m1); + if (reader_count + 1 == 1) + w.lock (); + + reader_count += 1; +} + + +inline +void +SharedMutex::rdunlock () const +{ + MutexGuard m1_guard (m1); + if (reader_count - 1 == 0) + w.unlock (); + + reader_count -= 1; +} + + +inline +void +SharedMutex::wrlock () const +{ + { + MutexGuard m2_guard (m2); + if (writer_count + 1 == 1) + r.lock (); + + writer_count += 1; + } + try + { + w.lock (); + } + catch (...) + { + MutexGuard m2_guard (m2); + writer_count -= 1; + throw; + } +} + + +inline +void +SharedMutex::wrunlock () const +{ + w.unlock (); + MutexGuard m2_guard (m2); + if (writer_count - 1 == 0) + r.unlock (); + + writer_count -= 1; +} diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/impl/syncprims-pthreads.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/impl/syncprims-pthreads.h new file mode 100644 index 0000000..0d3167c --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/impl/syncprims-pthreads.h @@ -0,0 +1,507 @@ +// -*- C++ -*- +// Copyright (C) 2009-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//! @file +//! This file contains implementations of synchronization +//! primitives using the POSIX threads. It does not contain any +//! include guards because it is only a fragment to be included by +//! syncprims.h. + +#include "log4cplus/thread/threads.h" +#include +#include + + +namespace log4cplus { namespace thread { namespace impl { + + +struct PthreadMutexAttr +{ + PthreadMutexAttr () + { + int ret = pthread_mutexattr_init (&attr); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("PthreadMutexAttr::PthreadMutexAttr"); + } + + + ~PthreadMutexAttr () + { + try + { + int ret = pthread_mutexattr_destroy (&attr); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("PthreadMutexAttr::~PthreadMutexAttr"); + } + catch (...) + { } + } + + + void + set_type (log4cplus::thread::Mutex::Type t) + { + int mutex_type; + switch (t) + { + case log4cplus::thread::Mutex::RECURSIVE: + mutex_type = PTHREAD_MUTEX_RECURSIVE; + break; + + default: + mutex_type = PTHREAD_MUTEX_DEFAULT; + } + + int ret = pthread_mutexattr_settype (&attr, mutex_type); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("PthreadMutexAttr::set_type"); + } + + + pthread_mutexattr_t attr; +}; + + +// +// +// + +inline +Mutex::Mutex (log4cplus::thread::Mutex::Type t) +{ + PthreadMutexAttr attr; + attr.set_type (t); + + int ret = pthread_mutex_init (&mtx, &attr.attr); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Mutex::Mutex"); +} + + +inline +Mutex::~Mutex () +{ + try + { + int ret = pthread_mutex_destroy (&mtx); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Mutex::~Mutex"); + } + catch (...) + { } +} + + +inline +void +Mutex::lock () const +{ + int ret = pthread_mutex_lock (&mtx); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Mutex::lock"); +} + + +inline +void +Mutex::unlock () const +{ + int ret = pthread_mutex_unlock (&mtx); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Mutex::unlock"); +} + + +// +// +// + +inline +Semaphore::Semaphore (unsigned max, unsigned initial) +{ + unsigned const sem_value_max = +#if defined (SEM_VALUE_MAX) + SEM_VALUE_MAX +#else + (std::numeric_limits::max) () +#endif + ; + + unsigned const limited_max = (std::min) (max, sem_value_max); + unsigned const limited_initial = (std::min) (initial, limited_max); + int ret = 0; + +#if defined (LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE) + std::ostringstream oss; + char size_check[2 * (static_cast(sizeof (std::ptrdiff_t)) + - static_cast(sizeof (this))) + 1]; + (void)size_check; + oss << getpid () << "-" << reinterpret_cast(this); + std::string name (oss.str ()); + + sem = sem_open (name.c_str (), O_CREAT, S_IRWXU | S_IRWXG, limited_max); + ret = sem == SEM_FAILED; + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::Semaphore"); + + try + { + // Unlink the semaphore early to simulate anonymous semaphore. + ret = sem_unlink (name.c_str ()); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::Semaphore"); + } + catch (std::runtime_error const &) + { + ret = sem_close (sem); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::~Semaphore"); + + throw; + } + +#else + ret = sem_init (&sem, 0, limited_max); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::Semaphore"); + +#endif + + try + { + for (unsigned i = limited_initial; i < limited_max; ++i) + lock (); + } + catch (std::runtime_error const &) + { +#if defined (LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE) + ret = sem_close (sem); +#else + ret = sem_destroy (&sem); +#endif + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::~Semaphore"); + + throw; + } +} + + +inline +Semaphore::~Semaphore () +{ + try + { + int ret = 0; +#if defined (LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE) + ret = sem_close (sem); +#else + ret = sem_destroy (&sem); +#endif + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::~Semaphore"); + } + catch (...) + { } +} + + +inline +void +Semaphore::unlock () const +{ +#if defined (LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE) + int ret = sem_post (sem); +#else + int ret = sem_post (&sem); +#endif + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::unlock"); +} + + +inline +void +Semaphore::lock () const +{ +#if defined (LOG4CPLUS_USE_NAMED_POSIX_SEMAPHORE) + int ret = sem_wait (sem); +#else + int ret = sem_wait (&sem); +#endif + if (ret != 0) + LOG4CPLUS_THROW_RTE ("Semaphore::lock"); +} + + +// +// +// + + +inline +FairMutex::FairMutex () + : sem (1, 1) +{ } + + +inline +FairMutex::~FairMutex () +{ } + + +inline +void +FairMutex::lock () const +{ + sem.lock (); +} + + +inline +void +FairMutex::unlock () const +{ + sem.unlock (); +} + + +// +// +// + +inline +ManualResetEvent::ManualResetEvent (bool sig) + : mtx (log4cplus::thread::Mutex::DEFAULT) + , sigcount (0) + , signaled (sig) +{ + int ret = pthread_cond_init (&cv, 0); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("ManualResetEvent::ManualResetEvent"); +} + + +inline +ManualResetEvent::~ManualResetEvent () +{ + try + { + int ret = pthread_cond_destroy (&cv); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("ManualResetEvent::~ManualResetEvent"); + } + catch (...) + { } +} + + +inline +void +ManualResetEvent::signal () const +{ + MutexGuard mguard (mtx); + + signaled = true; + sigcount += 1; + int ret = pthread_cond_broadcast (&cv); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("ManualResetEVent::signal"); + +} + + +inline +void +ManualResetEvent::wait () const +{ + MutexGuard mguard (mtx); + + if (! signaled) + { + unsigned prev_count = sigcount; + do + { + int ret = pthread_cond_wait (&cv, &mtx.mtx); + if (ret != 0) + { + mguard.unlock (); + mguard.detach (); + LOG4CPLUS_THROW_RTE ("ManualResetEvent::wait"); + } + } + while (prev_count == sigcount); + } +} + + +inline +bool +ManualResetEvent::timed_wait (unsigned long msec) const +{ + MutexGuard mguard (mtx); + + if (! signaled) + { + helpers::Time const wakeup_time (helpers::Time::gettimeofday () + + helpers::Time (msec / 1000, (msec % 1000) * 1000)); + struct timespec const ts = {wakeup_time.sec (), + wakeup_time.usec () * 1000}; + unsigned prev_count = sigcount; + do + { + int ret = pthread_cond_timedwait (&cv, &mtx.mtx, &ts); + switch (ret) + { + case 0: + break; + + case ETIMEDOUT: + return false; + + default: + mguard.unlock (); + mguard.detach (); + LOG4CPLUS_THROW_RTE ("ManualResetEvent::timed_wait"); + } + } + while (prev_count == sigcount); + } + + return true; +} + + +inline +void +ManualResetEvent::reset () const +{ + MutexGuard mguard (mtx); + + signaled = false; +} + + +// +// +// + +#if defined (LOG4CPLUS_POOR_MANS_SHAREDMUTEX) +#include "log4cplus/thread/impl/syncprims-pmsm.h" + +#else +inline +SharedMutex::SharedMutex () +{ + int ret = pthread_rwlock_init (&rwl, 0); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("SharedMutex::SharedMutex"); +} + + +inline +SharedMutex::~SharedMutex () +{ + try + { + int ret = pthread_rwlock_destroy (&rwl); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("SharedMutex::~SharedMutex"); + } + catch (...) + { } +} + + +inline +void +SharedMutex::rdlock () const +{ + int ret; + + do + { + ret = pthread_rwlock_rdlock (&rwl); + switch (ret) + { + case EAGAIN: + // The read lock could not be acquired because the maximum + // number of read locks for rwlock has been exceeded. + + log4cplus::thread::yield (); + // Fall through. + + case 0: + break; + + default: + LOG4CPLUS_THROW_RTE ("SharedMutex::rdlock"); + + } + } + while (ret != 0); +} + + +inline +void +SharedMutex::rdunlock () const +{ + unlock (); +} + + +inline +void +SharedMutex::wrlock () const +{ + int ret = pthread_rwlock_wrlock (&rwl); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("SharedMutex::wrlock"); +} + + +inline +void +SharedMutex::wrunlock () const +{ + unlock (); +} + + +inline +void +SharedMutex::unlock () const +{ + int ret = pthread_rwlock_unlock (&rwl); + if (ret != 0) + LOG4CPLUS_THROW_RTE ("SharedMutex::unlock"); + +} + + +#endif + + +} } } // namespace log4cplus { namespace thread { namespace impl { diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/impl/syncprims-win32.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/impl/syncprims-win32.h new file mode 100644 index 0000000..35cc423 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/impl/syncprims-win32.h @@ -0,0 +1,328 @@ +// -*- C++ -*- +// Copyright (C) 2009-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +//! @file +//! This file contains implementations of synchronization +//! primitives using the Win32 API. It does not contain any include +//! guards because it is only a fragment to be included by +//! syncprims.h. + +#include + + +namespace log4cplus { namespace thread { namespace impl { + + +// +// +// + +inline +bool +InitializeCriticalSection_wrapInternal (LPCRITICAL_SECTION cs) +{ +#if defined (_MSC_VER) + __try + { +#endif + + InitializeCriticalSection (cs); + +#if defined (_MSC_VER) + } + __except (GetExceptionCode() == STATUS_NO_MEMORY + ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) + { + return false; + } +#endif + + return true; +} + + +inline +void +InitializeCriticalSection_wrap (LPCRITICAL_SECTION cs) +{ + if (! InitializeCriticalSection_wrapInternal (cs)) + throw std::runtime_error ( + "InitializeCriticalSection: STATUS_NO_MEMORY"); +} + + +inline +Mutex::Mutex (log4cplus::thread::Mutex::Type) +{ + InitializeCriticalSection_wrap (&cs); +} + + +inline +Mutex::~Mutex () +{ + DeleteCriticalSection (&cs); +} + + +inline +void +Mutex::lock () const +{ + EnterCriticalSection (&cs); +} + + +inline +void +Mutex::unlock () const +{ + LeaveCriticalSection (&cs); +} + + +// +// +// + +inline +Semaphore::Semaphore (unsigned max, unsigned initial) +{ + sem = CreateSemaphore (0, initial, max, 0); + if (! sem) + LOG4CPLUS_THROW_RTE ("Semaphore::Semaphore"); +} + + +inline +Semaphore::~Semaphore () +{ + try + { + if (! CloseHandle (sem)) + LOG4CPLUS_THROW_RTE ("Semaphore::~Semaphore"); + } + catch (...) + { } +} + + +inline +void +Semaphore::unlock () const +{ + DWORD ret = ReleaseSemaphore (sem, 1, 0); + if (! ret) + LOG4CPLUS_THROW_RTE ("Semaphore::unlock"); +} + + +inline +void +Semaphore::lock () const +{ + DWORD ret = WaitForSingleObject (sem, INFINITE); + if (ret != WAIT_OBJECT_0) + LOG4CPLUS_THROW_RTE ("Semaphore::lock"); +} + + +// +// +// + + +inline +FairMutex::FairMutex () +{ + mtx = CreateMutex (0, false, 0); + if (! mtx) + LOG4CPLUS_THROW_RTE ("FairMutex::FairMutex"); +} + + +inline +FairMutex::~FairMutex () +{ + try + { + if (! CloseHandle (mtx)) + LOG4CPLUS_THROW_RTE ("FairMutex::~FairMutex"); + } + catch (...) + { } +} + + +inline +void +FairMutex::lock () const +{ + DWORD ret = WaitForSingleObject (mtx, INFINITE); + if (ret != WAIT_OBJECT_0) + LOG4CPLUS_THROW_RTE ("FairMutex::lock"); +} + + +inline +void +FairMutex::unlock () const +{ + if (! ReleaseMutex (mtx)) + LOG4CPLUS_THROW_RTE ("FairMutex::unlock"); +} + + +// +// +// + +inline +ManualResetEvent::ManualResetEvent (bool sig) +{ + ev = CreateEvent (0, true, sig, 0); + if (! ev) + LOG4CPLUS_THROW_RTE ("ManualResetEvent::ManualResetEvent"); +} + + +inline +ManualResetEvent::~ManualResetEvent () +{ + try + { + if (! CloseHandle (ev)) + LOG4CPLUS_THROW_RTE ("ManualResetEvent::~ManualResetEvent"); + } + catch (...) + { } +} + + +inline +void +ManualResetEvent::signal () const +{ + if (! SetEvent (ev)) + LOG4CPLUS_THROW_RTE ("ManualResetEVent::signal"); +} + + +inline +void +ManualResetEvent::wait () const +{ + DWORD ret = WaitForSingleObject (ev, INFINITE); + if (ret != WAIT_OBJECT_0) + LOG4CPLUS_THROW_RTE ("ManualResetEvent::wait"); +} + + +inline +bool +ManualResetEvent::timed_wait (unsigned long msec) const +{ + DWORD ret = WaitForSingleObject (ev, static_cast(msec)); + switch(ret) + { + case WAIT_OBJECT_0: + return true; + + case WAIT_TIMEOUT: + return false; + + default: + LOG4CPLUS_THROW_RTE ("ManualResetEvent::timed_wait"); + // Silence warnings about not returning any value from function + // returning bool. + return false; + } +} + + +inline +void +ManualResetEvent::reset () const +{ + if (! ResetEvent (ev)) + LOG4CPLUS_THROW_RTE ("ManualResetEvent::reset"); +} + + +// +// +// + +#if defined (LOG4CPLUS_POOR_MANS_SHAREDMUTEX) +#include "log4cplus/thread/impl/syncprims-pmsm.h" + +#else +inline +SharedMutex::SharedMutex () +{ + InitializeSRWLock (&srwl); +} + + +inline +SharedMutex::~SharedMutex () +{ } + + +inline +void +SharedMutex::rdlock () const +{ + AcquireSRWLockShared (&srwl); +} + + +inline +void +SharedMutex::rdunlock () const +{ + ReleaseSRWLockShared (&srwl); +} + + +inline +void +SharedMutex::wrlock () const +{ + AcquireSRWLockExclusive (&srwl); +} + + +inline +void +SharedMutex::wrunlock () const +{ + ReleaseSRWLockExclusive (&srwl); +} + + +#endif + + +} } } // namespace log4cplus { namespace thread { namespace impl { diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/impl/threads-impl.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/impl/threads-impl.h new file mode 100644 index 0000000..88b40b2 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/impl/threads-impl.h @@ -0,0 +1,160 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: threads.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_IMPL_THREADS_IMPL_HEADER_ +#define LOG4CPLUS_IMPL_THREADS_IMPL_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (_WIN32) +#include +#endif +#include +#include +#include + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + + +namespace log4cplus { namespace thread { namespace impl { + + +#if defined (LOG4CPLUS_USE_PTHREADS) + +typedef pthread_t os_handle_type; +typedef pthread_t os_id_type; + + +inline +pthread_t +getCurrentThreadId () +{ + return pthread_self (); +} + + +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) + +typedef HANDLE os_handle_type; +typedef DWORD os_id_type; + + +inline +DWORD +getCurrentThreadId () +{ + return GetCurrentThreadId (); +} + + +#elif defined (LOG4CPLUS_SINGLE_THREADED) + +typedef void * os_handle_type; +typedef int os_id_type; + + +inline +int +getCurrentThreadId () +{ + return 1; +} + + +#endif + + +#ifndef LOG4CPLUS_SINGLE_THREADED + + +struct ThreadStart +{ +# ifdef LOG4CPLUS_USE_PTHREADS +static void* threadStartFuncWorker(void *); +# elif defined(LOG4CPLUS_USE_WIN32_THREADS) +static unsigned threadStartFuncWorker(void *); +# endif +}; + + +/** + * There are many cross-platform C++ Threading libraries. The goal of + * this class is not to replace (or match in functionality) those + * libraries. The goal of this class is to provide a simple Threading + * class with basic functionality. + */ +class Thread + : public ThreadImplBase +{ +public: + Thread(); + bool isRunning() const; + os_id_type getThreadId() const; + os_handle_type getThreadHandle () const; + void start(); + void join (); + +protected: + // Force objects to be constructed on the heap + virtual ~Thread(); + virtual void run() = 0; + +private: + // Friends. + friend struct ThreadStart; + + enum Flags + { + fRUNNING = 0x01, + fJOINED = 0x02 + }; + + unsigned flags; + + os_handle_type handle; + +# if defined(LOG4CPLUS_USE_WIN32_THREADS) + unsigned thread_id; +# endif + + // Disallow copying of instances of this class. + Thread(const Thread&); + Thread& operator=(const Thread&); +}; + +typedef helpers::SharedObjectPtr ThreadPtr; + + +#endif // LOG4CPLUS_SINGLE_THREADED + + +} } } // namespace log4cplus { namespace thread { namespace impl { + + +#endif // LOG4CPLUS_IMPL_THREADS_IMPL_HEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/impl/tls.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/impl/tls.h new file mode 100644 index 0000000..5a390ae --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/impl/tls.h @@ -0,0 +1,180 @@ +// -*- C++ -*- +// Copyright (C) 2010-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_THREAD_IMPL_TLS_H +#define LOG4CPLUS_THREAD_IMPL_TLS_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + +#if ! defined (INSIDE_LOG4CPLUS) +# error "This header must not be be used outside log4cplus' implementation files." +#endif + +#ifdef LOG4CPLUS_USE_PTHREADS +# include + +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) +# include + +#elif defined (LOG4CPLUS_SINGLE_THREADED) +# include + +#endif + + +namespace log4cplus { namespace thread { namespace impl { + + +typedef void * tls_value_type; +typedef void (* tls_init_cleanup_func_type)(void *); + +#ifdef LOG4CPLUS_USE_PTHREADS +typedef pthread_key_t * tls_key_type; + +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) +typedef DWORD tls_key_type; + +#elif defined (LOG4CPLUS_SINGLE_THREADED) +typedef std::size_t tls_key_type; + +#endif + + +inline tls_key_type tls_init (tls_init_cleanup_func_type); +inline tls_value_type tls_get_value (tls_key_type); +inline void tls_set_value (tls_key_type, tls_value_type); +inline void tls_cleanup (tls_key_type); + + +#if defined (LOG4CPLUS_USE_PTHREADS) +tls_key_type +tls_init (tls_init_cleanup_func_type cleanupfunc) +{ + pthread_key_t * key = new pthread_key_t; + pthread_key_create (key, cleanupfunc); + return key; +} + + +tls_value_type +tls_get_value (tls_key_type key) +{ + return pthread_getspecific (*key); +} + + +void +tls_set_value (tls_key_type key, tls_value_type value) +{ + pthread_setspecific(*key, value); +} + + +void +tls_cleanup (tls_key_type key) +{ + pthread_key_delete (*key); + delete key; +} + + +#elif defined (LOG4CPLUS_USE_WIN32_THREADS) +tls_key_type +tls_init (tls_init_cleanup_func_type) +{ + return TlsAlloc (); +} + + +tls_value_type tls_get_value (tls_key_type k) +{ + return TlsGetValue (k); +} + + +void +tls_set_value (tls_key_type k, tls_value_type value) +{ + TlsSetValue (k, value); +} + + +void +tls_cleanup (tls_key_type k) +{ + TlsFree (k); +} + + +#elif defined (LOG4CPLUS_SINGLE_THREADED) +extern std::vector * tls_single_threaded_values; + + +tls_key_type +tls_init (tls_init_cleanup_func_type) +{ + if (! tls_single_threaded_values) + tls_single_threaded_values = new std::vector; + tls_key_type key = tls_single_threaded_values->size (); + tls_single_threaded_values->resize (key + 1); + return key; +} + + +tls_value_type +tls_get_value (tls_key_type k) +{ + assert (k < tls_single_threaded_values->size ()); + return (*tls_single_threaded_values)[k]; +} + + +void +tls_set_value (tls_key_type k, tls_value_type val) +{ + assert (k < tls_single_threaded_values->size ()); + (*tls_single_threaded_values)[k] = val; +} + + +void +tls_cleanup (tls_key_type k) +{ + assert (k < tls_single_threaded_values->size ()); + (*tls_single_threaded_values)[k] = 0; +} + +#endif + + +} } } // namespace log4cplus { namespace thread { namespace impl { + +#endif // LOG4CPLUS_THREAD_IMPL_TLS_H diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/syncprims-pub-impl.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/syncprims-pub-impl.h new file mode 100644 index 0000000..15e045c --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/syncprims-pub-impl.h @@ -0,0 +1,306 @@ +// -*- C++ -*- +// Copyright (C) 2010-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_THREAD_SYNCPRIMS_PUB_IMPL_H +#define LOG4CPLUS_THREAD_SYNCPRIMS_PUB_IMPL_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if (defined (LOG4CPLUS_INLINES_ARE_EXPORTED) \ + && defined (LOG4CPLUS_BUILD_DLL)) \ + || defined (LOG4CPLUS_ENABLE_SYNCPRIMS_PUB_IMPL) +#include + +#if defined (LOG4CPLUS_SINGLE_THREADED) +# define LOG4CPLUS_THREADED(x) +# define LOG4CPLUS_THREADED2(x, y) (y) +#else +# include +# define LOG4CPLUS_THREADED(x) (x) +# define LOG4CPLUS_THREADED2(x, y) (x) +#endif + + +namespace log4cplus { namespace thread { + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +MutexImplBase::~MutexImplBase () +{ } + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +Mutex::Mutex (Mutex::Type LOG4CPLUS_THREADED (t)) + : mtx (LOG4CPLUS_THREADED2 (new impl::Mutex (t), + static_cast(0))) +{ } + + +LOG4CPLUS_INLINE_EXPORT +Mutex::~Mutex () +{ + LOG4CPLUS_THREADED (delete static_cast(mtx)); +} + + +LOG4CPLUS_INLINE_EXPORT +void +Mutex::lock () const +{ + LOG4CPLUS_THREADED (static_cast(mtx)->lock ()); +} + + +LOG4CPLUS_INLINE_EXPORT +void +Mutex::unlock () const +{ + LOG4CPLUS_THREADED (static_cast(mtx)->unlock ()); +} + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +SemaphoreImplBase::~SemaphoreImplBase () +{ } + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +Semaphore::Semaphore (unsigned LOG4CPLUS_THREADED (max), + unsigned LOG4CPLUS_THREADED (initial)) + : sem (LOG4CPLUS_THREADED2 (new impl::Semaphore (max, initial), + static_cast(0))) +{ } + + +LOG4CPLUS_INLINE_EXPORT +Semaphore::~Semaphore () +{ + LOG4CPLUS_THREADED (delete static_cast(sem)); +} + + +LOG4CPLUS_INLINE_EXPORT +void +Semaphore::lock () const +{ + LOG4CPLUS_THREADED (static_cast(sem)->lock ()); +} + + +LOG4CPLUS_INLINE_EXPORT +void +Semaphore::unlock () const +{ + LOG4CPLUS_THREADED (static_cast(sem)->unlock ()); +} + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +FairMutexImplBase::~FairMutexImplBase () +{ } + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +FairMutex::FairMutex () + : mtx (LOG4CPLUS_THREADED2 (new impl::FairMutex, + static_cast(0))) +{ } + + +LOG4CPLUS_INLINE_EXPORT +FairMutex::~FairMutex () +{ + LOG4CPLUS_THREADED (delete static_cast(mtx)); +} + + +LOG4CPLUS_INLINE_EXPORT +void +FairMutex::lock () const +{ + LOG4CPLUS_THREADED (static_cast(mtx)->lock ()); +} + + +LOG4CPLUS_INLINE_EXPORT +void +FairMutex::unlock () const +{ + LOG4CPLUS_THREADED (static_cast(mtx)->unlock ()); +} + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +ManualResetEventImplBase::~ManualResetEventImplBase () +{ } + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +ManualResetEvent::ManualResetEvent (bool LOG4CPLUS_THREADED (sig)) + : ev (LOG4CPLUS_THREADED2 (new impl::ManualResetEvent (sig), + static_cast(0))) +{ } + + +LOG4CPLUS_INLINE_EXPORT +ManualResetEvent::~ManualResetEvent () +{ + LOG4CPLUS_THREADED (delete static_cast(ev)); +} + + +LOG4CPLUS_INLINE_EXPORT +void +ManualResetEvent::signal () const +{ + LOG4CPLUS_THREADED (static_cast(ev)->signal ()); +} + + +LOG4CPLUS_INLINE_EXPORT +void +ManualResetEvent::wait () const +{ + LOG4CPLUS_THREADED (static_cast(ev)->wait ()); +} + + +LOG4CPLUS_INLINE_EXPORT +bool +ManualResetEvent::timed_wait (unsigned long LOG4CPLUS_THREADED (msec)) const +{ +#if defined (LOG4CPLUS_SINGLE_THREADED) + return true; +#else + return static_cast(ev)->timed_wait (msec); +#endif +} + + +LOG4CPLUS_INLINE_EXPORT +void +ManualResetEvent::reset () const +{ + LOG4CPLUS_THREADED (static_cast(ev)->reset ()); +} + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +SharedMutexImplBase::~SharedMutexImplBase () +{ } + + +// +// +// + +LOG4CPLUS_INLINE_EXPORT +SharedMutex::SharedMutex () + : sm (LOG4CPLUS_THREADED2 (new impl::SharedMutex, + static_cast(0))) +{ } + + +LOG4CPLUS_INLINE_EXPORT +SharedMutex::~SharedMutex () +{ } + + +LOG4CPLUS_INLINE_EXPORT +void +SharedMutex::rdlock () const +{ + LOG4CPLUS_THREADED (static_cast(sm)->rdlock ()); +} + + +LOG4CPLUS_INLINE_EXPORT +void +SharedMutex::wrlock () const +{ + LOG4CPLUS_THREADED (static_cast(sm)->wrlock ()); +} + + +LOG4CPLUS_INLINE_EXPORT +void +SharedMutex::rdunlock () const +{ + LOG4CPLUS_THREADED (static_cast(sm)->rdunlock ()); +} + + +LOG4CPLUS_INLINE_EXPORT +void +SharedMutex::wrunlock () const +{ + LOG4CPLUS_THREADED (static_cast(sm)->wrunlock ()); +} + + +} } // namespace log4cplus { namespace thread { + +#endif // LOG4CPLUS_ENABLE_SYNCPRIMS_PUB_IMPL + +#endif // LOG4CPLUS_THREAD_SYNCPRIMS_PUB_IMPL_H diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/syncprims.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/syncprims.h new file mode 100644 index 0000000..d043845 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/syncprims.h @@ -0,0 +1,382 @@ +// -*- C++ -*- +// Copyright (C) 2010-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_THREAD_SYNCPRIMS_H +#define LOG4CPLUS_THREAD_SYNCPRIMS_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + + +namespace log4cplus { namespace thread { + + +template +class SyncGuard +{ +public: + SyncGuard (); + SyncGuard (SP const &); + ~SyncGuard (); + + void lock (); + void unlock (); + void attach (SP const &); + void attach_and_lock (SP const &); + void detach (); + +private: + SP const * sp; + + SyncGuard (SyncGuard const &); + SyncGuard & operator = (SyncGuard const &); +}; + + +class ManualResetEvent; + + +class MutexImplBase +{ +protected: + ~MutexImplBase (); +}; + + +class LOG4CPLUS_EXPORT Mutex +{ +public: + enum Type + { + DEFAULT, + RECURSIVE + }; + + explicit Mutex (Type = RECURSIVE); + ~Mutex (); + + void lock () const; + void unlock () const; + +private: + MutexImplBase * mtx; + + Mutex (Mutex const &); + Mutex & operator = (Mutex &); +}; + + +typedef SyncGuard MutexGuard; + + +class SemaphoreImplBase +{ +protected: + ~SemaphoreImplBase (); +}; + + +class LOG4CPLUS_EXPORT Semaphore +{ +public: + Semaphore (unsigned max, unsigned initial); + ~Semaphore (); + + void lock () const; + void unlock () const; + +private: + SemaphoreImplBase * sem; + + Semaphore (Semaphore const &); + Semaphore & operator = (Semaphore const &); +}; + + +typedef SyncGuard SemaphoreGuard; + + +class FairMutexImplBase +{ +protected: + ~FairMutexImplBase (); +}; + + +class LOG4CPLUS_EXPORT FairMutex +{ +public: + FairMutex (); + ~FairMutex (); + + void lock () const; + void unlock () const; + +private: + FairMutexImplBase * mtx; + + FairMutex (FairMutex const &); + FairMutex & operator = (FairMutex &); +}; + + +typedef SyncGuard FairMutexGuard; + + +class ManualResetEventImplBase +{ +protected: + ~ManualResetEventImplBase (); +}; + + +class LOG4CPLUS_EXPORT ManualResetEvent +{ +public: + ManualResetEvent (bool = false); + ~ManualResetEvent (); + + void signal () const; + void wait () const; + bool timed_wait (unsigned long msec) const; + void reset () const; + +private: + ManualResetEventImplBase * ev; + + ManualResetEvent (ManualResetEvent const &); + ManualResetEvent & operator = (ManualResetEvent const &); +}; + + +class SharedMutexImplBase +{ +protected: + ~SharedMutexImplBase (); +}; + + +template +class SyncGuardFunc +{ +public: + SyncGuardFunc (SP const &); + ~SyncGuardFunc (); + + void lock (); + void unlock (); + void attach (SP const &); + void detach (); + +private: + SP const * sp; + + SyncGuardFunc (SyncGuardFunc const &); + SyncGuardFunc & operator = (SyncGuardFunc const &); +}; + + +class LOG4CPLUS_EXPORT SharedMutex +{ +public: + SharedMutex (); + ~SharedMutex (); + + void rdlock () const; + void rdunlock () const; + + void wrlock () const; + void wrunlock () const; + +private: + SharedMutexImplBase * sm; + + SharedMutex (SharedMutex const &); + SharedMutex & operator = (SharedMutex const &); +}; + + +typedef SyncGuardFunc SharedMutexReaderGuard; + + +typedef SyncGuardFunc SharedMutexWriterGuard; + + +// +// +// + +template +inline +SyncGuard::SyncGuard () + : sp (0) +{ } + + +template +inline +SyncGuard::SyncGuard (SP const & m) + : sp (&m) +{ + sp->lock (); +} + + +template +inline +SyncGuard::~SyncGuard () +{ + if (sp) + sp->unlock (); +} + + +template +inline +void +SyncGuard::lock () +{ + sp->lock (); +} + + +template +inline +void +SyncGuard::unlock () +{ + sp->unlock (); +} + + +template +inline +void +SyncGuard::attach (SP const & m) +{ + sp = &m; +} + + +template +inline +void +SyncGuard::attach_and_lock (SP const & m) +{ + attach (m); + try + { + lock(); + } + catch (...) + { + detach (); + throw; + } +} + + +template +inline +void +SyncGuard::detach () +{ + sp = 0; +} + + +// +// +// + +template +inline +SyncGuardFunc::SyncGuardFunc (SP const & m) + : sp (&m) +{ + (sp->*lock_func) (); +} + + +template +inline +SyncGuardFunc::~SyncGuardFunc () +{ + if (sp) + (sp->*unlock_func) (); +} + + +template +inline +void +SyncGuardFunc::lock () +{ + (sp->*lock_func) (); +} + + +template +inline +void +SyncGuardFunc::unlock () +{ + (sp->*unlock_func) (); +} + + +template +inline +void +SyncGuardFunc::attach (SP const & m) +{ + sp = &m; +} + + +template +inline +void +SyncGuardFunc::detach () +{ + sp = 0; +} + + +} } // namespace log4cplus { namespace thread { + + +#endif // LOG4CPLUS_THREAD_SYNCPRIMS_H diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/threads.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/threads.h new file mode 100644 index 0000000..82149c4 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/thread/threads.h @@ -0,0 +1,96 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: threads.h +// Created: 6/2001 +// Author: Tad E. Smith +// +// +// Copyright 2001-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_THREADS_HEADER_ +#define LOG4CPLUS_THREADS_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + + +namespace log4cplus { namespace thread { + + +LOG4CPLUS_EXPORT log4cplus::tstring const & getCurrentThreadName(); +LOG4CPLUS_EXPORT log4cplus::tstring const & getCurrentThreadName2(); +LOG4CPLUS_EXPORT void setCurrentThreadName(const log4cplus::tstring & name); +LOG4CPLUS_EXPORT void setCurrentThreadName2(const log4cplus::tstring & name); +LOG4CPLUS_EXPORT void yield(); +LOG4CPLUS_EXPORT void blockAllSignals(); + + +#ifndef LOG4CPLUS_SINGLE_THREADED + +class ThreadImplBase + : public virtual log4cplus::helpers::SharedObject +{ +protected: + virtual ~ThreadImplBase (); +}; + + +/** + * There are many cross-platform C++ Threading libraries. The goal of + * this class is not to replace (or match in functionality) those + * libraries. The goal of this class is to provide a simple Threading + * class with basic functionality. + */ +class LOG4CPLUS_EXPORT AbstractThread + : public virtual log4cplus::helpers::SharedObject +{ +public: + AbstractThread(); + bool isRunning() const; + virtual void start(); + void join () const; + virtual void run() = 0; + +protected: + // Force objects to be constructed on the heap + virtual ~AbstractThread(); + +private: + helpers::SharedObjectPtr thread; + + // Disallow copying of instances of this class. + AbstractThread(const AbstractThread&); + AbstractThread& operator=(const AbstractThread&); +}; + +typedef helpers::SharedObjectPtr AbstractThreadPtr; + + +#endif // LOG4CPLUS_SINGLE_THREADED + + +} } // namespace log4cplus { namespace thread { + + +#endif // LOG4CPLUS_THREADS_HEADER_ + diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/tracelogger.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/tracelogger.h new file mode 100644 index 0000000..a056ccd --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/tracelogger.h @@ -0,0 +1,79 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: tracelogger.h +// Created: 1/2009 +// Author: Vaclav Haisman +// +// +// Copyright 2009-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_TRACELOGGER_H +#define LOG4CPLUS_TRACELOGGER_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include + + +namespace log4cplus +{ + + +/** + * This class is used to produce "Trace" logging. When an instance of + * this class is created, it will log a "ENTER: " + msg + * log message if TRACE_LOG_LEVEL is enabled for logger. + * When an instance of this class is destroyed, it will log a + * "ENTER: " + msg log message if TRACE_LOG_LEVEL is enabled + * for logger. + *

+ * @see LOG4CPLUS_TRACE + */ +class TraceLogger +{ +public: + TraceLogger(const Logger& l, const log4cplus::tstring& _msg, + const char* _file=NULL, int _line=-1) + : logger(l), msg(_msg), file(_file), line(_line) + { if(logger.isEnabledFor(TRACE_LOG_LEVEL)) + logger.forcedLog(TRACE_LOG_LEVEL, LOG4CPLUS_TEXT("ENTER: ") + msg, file, line); + } + + ~TraceLogger() + { if(logger.isEnabledFor(TRACE_LOG_LEVEL)) + logger.forcedLog(TRACE_LOG_LEVEL, LOG4CPLUS_TEXT("EXIT: ") + msg, file, line); + } + +private: + TraceLogger (TraceLogger const &); + TraceLogger & operator = (TraceLogger const &); + + Logger logger; + log4cplus::tstring msg; + const char* file; + int line; +}; + + +} // log4cplus + + +#endif // LOG4CPLUS_TRACELOGGER_H diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/tstring.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/tstring.h new file mode 100644 index 0000000..587aaa1 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/tstring.h @@ -0,0 +1,134 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: tstring.h +// Created: 4/2003 +// Author: Tad E. Smith +// +// +// Copyright 2003-2013 Tad E. Smith +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_TSTRING_HEADER_ +#define LOG4CPLUS_TSTRING_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#include +#include + +namespace log4cplus +{ + +typedef std::basic_string tstring; + + +namespace helpers +{ + +inline +std::string +tostring (char const * str) +{ + return std::string (str); +} + +inline +std::string +tostring (std::string const & str) +{ + return str; +} + +inline +std::string const & +tostring (std::string & str) +{ + return str; +} + +#ifdef LOG4CPLUS_HAVE_RVALUE_REFS +inline +std::string +tostring (std::string && str) +{ + return std::move (str); +} + +#endif + + + +inline +std::wstring +towstring (wchar_t const * str) +{ + return std::wstring (str); +} + +inline +std::wstring +towstring (std::wstring const & str) +{ + return str; +} + +inline +std::wstring const & +towstring (std::wstring & str) +{ + return str; +} + +#ifdef LOG4CPLUS_HAVE_RVALUE_REFS +inline +std::wstring +towstring (std::wstring && str) +{ + return std::move (str); +} + +#endif + +LOG4CPLUS_EXPORT std::string tostring(const std::wstring&); +LOG4CPLUS_EXPORT std::string tostring(wchar_t const *); + +LOG4CPLUS_EXPORT std::wstring towstring(const std::string&); +LOG4CPLUS_EXPORT std::wstring towstring(char const *); + +} // namespace helpers + +#ifdef UNICODE + +#define LOG4CPLUS_C_STR_TO_TSTRING(STRING) log4cplus::helpers::towstring(STRING) +#define LOG4CPLUS_STRING_TO_TSTRING(STRING) log4cplus::helpers::towstring(STRING) +#define LOG4CPLUS_TSTRING_TO_STRING(STRING) log4cplus::helpers::tostring(STRING) + +#else // UNICODE + +#define LOG4CPLUS_C_STR_TO_TSTRING(STRING) std::string(STRING) +#define LOG4CPLUS_STRING_TO_TSTRING(STRING) STRING +#define LOG4CPLUS_TSTRING_TO_STRING(STRING) STRING + +#endif // UNICODE + +} // namespace log4cplus + + +#endif // LOG4CPLUS_TSTRING_HEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/version.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/version.h new file mode 100644 index 0000000..0481df9 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/version.h @@ -0,0 +1,53 @@ +// -*- C++ -*- +// Copyright (C) 2010-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +#if ! defined (LOG4CPLUS_VERSION_H) +#define LOG4CPLUS_VERSION_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#define LOG4CPLUS_MAKE_VERSION(major, minor, point) \ + (major * 1000 * 1000u + minor * 1000u + point) + +#define LOG4CPLUS_MAKE_VERSION_STR(major, minor, point) \ + #major "." #minor "." #point + +#define LOG4CPLUS_VERSION LOG4CPLUS_MAKE_VERSION(1, 1, 3) +#define LOG4CPLUS_VERSION_STR LOG4CPLUS_MAKE_VERSION_STR(1, 1, 3) + + +namespace log4cplus +{ + +extern LOG4CPLUS_EXPORT unsigned const version; +extern LOG4CPLUS_EXPORT char const versionStr[]; + +} + +#endif diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/win32consoleappender.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/win32consoleappender.h new file mode 100644 index 0000000..c98eb55 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/win32consoleappender.h @@ -0,0 +1,93 @@ +// -*- C++ -*- +// Copyright (C) 2009-2013, Vaclav Haisman. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modifica- +// tion, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +// APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- +// DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef LOG4CPLUS_WIN32CONSOLEAPPENDER_H +#define LOG4CPLUS_WIN32CONSOLEAPPENDER_H + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined(_WIN32) && defined (LOG4CPLUS_HAVE_WIN32_CONSOLE) + +#include + + +namespace log4cplus +{ + + /** + * Prints events to Win32 console. + * + *

Properties

+ *
+ *
AllocConsole
+ *
This boolean property specifies whether or not this appender + * will try to allocate new console using the + * AllocConsole() Win32 function.
+ * + *
logToStdErr
+ *
When it is set true, the output will be into + * STD_ERROR_HANDLE instead of STD_OUTPUT_HANDLE. + *
+ * + *
TextColor
+ *
See MSDN documentation for + * + * Character Attributes. + *
+ */ + class LOG4CPLUS_EXPORT Win32ConsoleAppender + : public Appender + { + public: + explicit Win32ConsoleAppender (bool allocConsole = true, + bool logToStdErr = false, unsigned int textColor = 0); + Win32ConsoleAppender (helpers::Properties const & properties); + virtual ~Win32ConsoleAppender (); + + virtual void close (); + + protected: + virtual void append (spi::InternalLoggingEvent const &); + + void write_handle (void *, tchar const *, std::size_t); + void write_console (void *, tchar const *, std::size_t); + + bool alloc_console; + bool log_to_std_err; + unsigned int text_color; + + private: + Win32ConsoleAppender (Win32ConsoleAppender const &); + Win32ConsoleAppender & operator = (Win32ConsoleAppender const &); + }; + +} // namespace log4cplus + +#endif + +#endif // LOG4CPLUS_WIN32CONSOLEAPPENDER_H diff --git a/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/win32debugappender.h b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/win32debugappender.h new file mode 100644 index 0000000..50059d4 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/include/log4cplus/win32debugappender.h @@ -0,0 +1,69 @@ +// -*- C++ -*- +// Module: Log4CPLUS +// File: win32debugappender.h +// Created: 12/2003 +// Author: Eduardo Francos, Odalio SARL +// +// +// Copyright 2003-2013 Odalio SARL +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** @file */ + +#ifndef LOG4CPLUS_WIN32DEBUG_APPENDER_HEADER_ +#define LOG4CPLUS_WIN32DEBUG_APPENDER_HEADER_ + +#include + +#if defined (LOG4CPLUS_HAVE_PRAGMA_ONCE) +#pragma once +#endif + +#if defined (LOG4CPLUS_HAVE_OUTPUTDEBUGSTRING) + +#include + + +namespace log4cplus { + + /** + * Prints log events using OutputDebugString(). + */ + class LOG4CPLUS_EXPORT Win32DebugAppender + : public Appender + { + public: + // Ctors + Win32DebugAppender(); + Win32DebugAppender(const log4cplus::helpers::Properties& properties); + + // Dtor + virtual ~Win32DebugAppender(); + + // Methods + virtual void close(); + + protected: + virtual void append(const log4cplus::spi::InternalLoggingEvent& event); + + private: + // Disallow copying of instances of this class + Win32DebugAppender(const Win32DebugAppender&); + Win32DebugAppender& operator=(const Win32DebugAppender&); + }; + +} // end namespace log4cplus + +#endif // LOG4CPLUS_HAVE_OUTPUTDEBUGSTRING +#endif // LOG4CPLUS_WIN32DEBUG_APPENDER_HEADER_ diff --git a/sg_agent/thrid_party/logs/log4cplus/log4cplus.conf b/sg_agent/thrid_party/logs/log4cplus/log4cplus.conf new file mode 100644 index 0000000..820a53d --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/log4cplus.conf @@ -0,0 +1,67 @@ +log4cplus.rootLogger=fatal, error, warn, info, debug +log4cplus.logger.debug=debug +log4cplus.appender.debug=log4cplus::RollingFileAppender +log4cplus.appender.debug.MaxFileSize=50MB +log4cplus.appender.debug.MaxBackupIndex=10 +log4cplus.appender.debug.Append=true +log4cplus.appender.debug.layout=log4cplus::PatternLayout +log4cplus.appender.debug.layout.ConversionPattern=[%D{%Y-%m-%d %H:%M:%S}] [%F:%L] %-5p - %m%n +log4cplus.appender.debug.Threshold=fatal +log4cplus.appender.debug.append=true +log4cplus.appender.debug.File=/var/octo/logs/sg_agent/sg_agent.debug + +log4cplus.logger.info=info +log4cplus.appender.info=log4cplus::RollingFileAppender +log4cplus.appender.info.MaxFileSize=50MB +log4cplus.appender.info.MaxBackupIndex=10 +log4cplus.appender.info.Append=true +log4cplus.appender.info.layout=log4cplus::PatternLayout +log4cplus.appender.info.layout.ConversionPattern=[%D{%Y-%m-%d %H:%M:%S}] [%F:%L] %-5p - %m%n +log4cplus.appender.info.Threshold=info +log4cplus.appender.info.append=true +log4cplus.appender.info.File=/var/octo/logs/sg_agent/sg_agent.info + +log4cplus.logger.warn=warn +log4cplus.appender.warn=log4cplus::RollingFileAppender +log4cplus.appender.warn.MaxFileSize=10MB +log4cplus.appender.warn.MaxBackupIndex=10 +log4cplus.appender.warn.Append=true +log4cplus.appender.warn.layout=log4cplus::PatternLayout +log4cplus.appender.warn.layout.ConversionPattern=[%D{%Y-%m-%d %H:%M:%S}] [%F:%L] %-5p - %m%n +log4cplus.appender.warn.Threshold=warn +log4cplus.appender.warn.append=true +log4cplus.appender.warn.File=/var/octo/logs/sg_agent/sg_agent.warn + +log4cplus.logger.error=error +log4cplus.appender.error=log4cplus::RollingFileAppender +log4cplus.appender.error.MaxFileSize=10MB +log4cplus.appender.error.MaxBackupIndex=10 +log4cplus.appender.error.Append=true +log4cplus.appender.error.layout=log4cplus::PatternLayout +log4cplus.appender.error.layout.ConversionPattern=[%D{%Y-%m-%d %H:%M:%S}] [%F:%L] %-5p - %m%n +log4cplus.appender.error.Threshold=error +log4cplus.appender.error.append=true +log4cplus.appender.error.File=/var/octo/logs/sg_agent/sg_agent.error + +log4cplus.logger.fatal=fatal +log4cplus.appender.fatal=log4cplus::RollingFileAppender +log4cplus.appender.fatal.MaxFileSize=10MB +log4cplus.appender.fatal.MaxBackupIndex=10 +log4cplus.appender.fatal.Append=true +log4cplus.appender.fatal.layout=log4cplus::PatternLayout +log4cplus.appender.fatal.layout.ConversionPattern=[%D{%Y-%m-%d %H:%M:%S}] [%F:%L] %-5p - %m%n +log4cplus.appender.fatal.Threshold=fatal +log4cplus.appender.fatal.append=true +log4cplus.appender.fatal.File=/var/octo/logs/sg_agent/sg_agent.fatal + +log4cplus.logger.statLogger=warn, stat + +log4cplus.appender.stat=log4cplus::RollingFileAppender +log4cplus.appender.stat.MaxFileSize=10MB +log4cplus.appender.stat.MaxBackupIndex=10 +log4cplus.appender.stat.Append=true +log4cplus.appender.stat.layout=log4cplus::PatternLayout +log4cplus.appender.stat.layout.ConversionPattern=[%D{%Y-%m-%d %H:%M:%S}] [%F:%L] %-5p - %m%n +log4cplus.appender.stat.Threshold=warn +log4cplus.appender.stat.append=true +log4cplus.appender.stat.File=/var/octo/logs/sg_agent/sg_agent.stat diff --git a/sg_agent/thrid_party/logs/log4cplus/log4cplus.cpp b/sg_agent/thrid_party/logs/log4cplus/log4cplus.cpp new file mode 100644 index 0000000..23b4023 --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/log4cplus.cpp @@ -0,0 +1,15 @@ +#include "log4cplus.h" + +namespace meituan_mns{ + +Logger debug_instance = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("debug")); +Logger info_instance = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("info")); +Logger warn_instance = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("warn")); +Logger error_instance = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("error")); +Logger fatal_instance = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("fatal")); + +//non root Logger +Logger stat_instance = log4cplus::Logger::getInstance(LOG4CPLUS_TEXT("statLogger")); + +} + diff --git a/sg_agent/thrid_party/logs/log4cplus/log4cplus.h b/sg_agent/thrid_party/logs/log4cplus/log4cplus.h new file mode 100644 index 0000000..fc010bf --- /dev/null +++ b/sg_agent/thrid_party/logs/log4cplus/log4cplus.h @@ -0,0 +1,42 @@ +#ifndef __LOG4CPLUS_H__ +#define __LOG4CPLUS_H__ + +#include +#include +#include +#include +#include +#include +#include +#include + +/*采用宏对目前的底层日志库进行封装,如果未来有需要更换日志库,在这里修改即可*/ +namespace meituan_mns{ +using std::auto_ptr; +using log4cplus::Logger; +using log4cplus::ConsoleAppender; +using log4cplus::FileAppender; +using log4cplus::Appender; +using log4cplus::Layout; +using log4cplus::PatternLayout; +using log4cplus::helpers::SharedObjectPtr; + +extern Logger debug_instance; +extern Logger info_instance; +extern Logger warn_instance; +extern Logger error_instance; +extern Logger fatal_instance; +extern Logger stat_instance; + +#define NS_LOG_DEBUG(debugContent) {LOG4CPLUS_DEBUG(debug_instance,debugContent);} +#define NS_LOG_INFO(infoContent) {LOG4CPLUS_INFO(info_instance, infoContent);} +#define NS_LOG_WARN(warnContent) {LOG4CPLUS_WARN(warn_instance, warnContent);} +#define NS_LOG_ERROR(errorContent) {LOG4CPLUS_ERROR(error_instance,errorContent);} +#define NS_LOG_FATAL(fatalContent) {LOG4CPLUS_ERROR(fatal_instance,fatalContent);} +#define NS_LOG_STAT(statContent) {LOG4CPLUS_INFO(stat_instance, statContent);} + +} + + + +#endif diff --git a/sg_agent/thrid_party/thrid/include/mns_sdk/mns_sdk.h b/sg_agent/thrid_party/thrid/include/mns_sdk/mns_sdk.h new file mode 100644 index 0000000..c17712e --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/mns_sdk/mns_sdk.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_MNS_SDK_H_ +#define OCTO_OPEN_SOURCE_MNS_SDK_H_ + +#include "mns_worker.h" + +namespace mns_sdk { + +//获取服务列表回调函数,允许为空,另外注意MNS库的子线程在执行该函数,注意线程安全问题 +typedef boost::function &vec, + const std::string &str_svr_appkey)> + SvrListCallback; + +//获取服务列表的回调函数, 三个vector分别代表服务列表中新增的,需要删除的, +//内容需要改变的, 三者允许任意为空. 另外注意是MNS库的子线程在执行这个函数, 注意线程安全问题 +typedef boost::function &vec_add, + const std::vector &vec_del, + const std::vector &vec_chg, + const std::string &str_svr_appkey)> + UpdateSvrListCallback; + +//启用clog统一日志,初始化日志系统,程序进程调用一次即可 + +int InitMNS(const std::string &mns_path, const double &sec, + const double &timeout = 0.5);//初始化mns_sdk客户端,mns_path 环境配置文件, +// 并设置服务列表拉取间隔(s),仅初始化一次即可。 + +//服务在一个进程中可以既调用StartSvr注册服务,又调用StartClient获取服务列表 +//同步注册服务, 默认等待时间不超过50ms, 返回非0表示注册失败 + +//注册服务 +int8_t StartSvr(const std::string &str_appkey, + const int16_t &i16_port, + const int32_t &i32_svr_type, //0:thrift, 1:http, 2:other + const std::string &str_proto_type = "thrift"); + +int8_t StartSvr(const std::string &str_appkey, + const std::vector &service_name_list, + const int16_t &i16_port, + const int32_t &i32_svr_type, //0:thrift, 1:http, 2:other + const std::string &str_proto_type,//"thrift", "http" + const bool &b_is_uniform = false); + + +//返回服务列表,存入用户传入的res_svr_list中 +int8_t getSvrList(const std::string &str_svr_appkey, + const std::string &str_cli_appkey, + const std::string &str_proto_type, + const std::string &str_service_name, + std::vector *p_svr_list); + +//获取所有类型服务节点,推荐,支持在一条业务线程中多次绑定不同的str_svr_appkey。 +int8_t StartClient(const std::string &str_svr_appkey, + const std::string &str_cli_appkey, + const std::string &str_proto_type, //client支持的协议类型 thrift/http/cellar..., 定期来取的svrlist将按照这个类型进行过滤 + const std::string &str_service_name, //IDL文件中的service名字,可按这个名字来过滤服务节点,可填空串返回全部服务节点 + const SvrListCallback &cb); //异步用回调定期获取服务列表, 返回非0表示参数错误(str_svr_appkey为空等) + +int8_t StartClient(const std::string &str_svr_appkey, + const std::string &str_cli_appkey, + const std::string &str_proto_type, //client支持的协议类型 thrift/http/cellar..., 定期来取的svrlist将按照这个类型进行过滤 + const std::string &str_service_name, //IDL文件中的service名字,可按这个名字来过滤服务节点,可填空串返回全部服务节点 + const UpdateSvrListCallback &cb); //异步用回调定期获取服务列表, 返回非0表示参数错误(str_svr_appkey为空等) + +int8_t AddSvrListCallback(const std::string &str_svr_appkey, + const SvrListCallback &cb, + std::string *p_err_info); + +int8_t AddUpdateSvrListCallback(const std::string &str_svr_appkey, + const UpdateSvrListCallback &cb, + std::string *p_err_info); + +void DestroyMNS(void);//退出时调用 +} +#endif //OCTO_OPEN_SOURCE_MNS_SDK_H_ + diff --git a/sg_agent/thrid_party/thrid/include/mns_sdk/mns_worker.h b/sg_agent/thrid_party/thrid/include/mns_sdk/mns_worker.h new file mode 100644 index 0000000..1317804 --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/mns_sdk/mns_worker.h @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +#ifndef OCTO_OPEN_SOURCE_MNS_WORKER_H_ +#define OCTO_OPEN_SOURCE_MNS_WORKER_H_ + +#include "thrift_client.h" + +namespace mns_sdk { + +class ServerListParams { + public: + ServerListParams(const meituan_mns::ProtocolResponse &rsp, + const meituan_mns::ProtocolRequest &request) : + ret_(-1), + timeout_(false), + rsp_(rsp), + resuest_(request), + cond_ready_read_(mutexlock_conn_ready_) {} + + int ret_; + bool timeout_; + meituan_mns::ProtocolResponse rsp_; + meituan_mns::ProtocolRequest resuest_; + muduo::MutexLock mutexlock_conn_ready_; + muduo::Condition cond_ready_read_; +}; + +class RegisterParams { + public: + RegisterParams(const meituan_mns::SGService &sgService) : + ret_(-1), + timeout_(false), + sgService_(sgService), + cond_ready_read_(mutexlock_conn_ready_) { + } + + int ret_; + bool timeout_; + meituan_mns::SGService sgService_; + muduo::MutexLock mutexlock_conn_ready_; + muduo::Condition cond_ready_read_; +}; + +typedef boost::shared_ptr ServerListParamsPtr; +typedef boost::shared_ptr RegisterParamsPtr; + +struct WeightSort { + bool operator()(const double &a, const double &b) const { + return a > b; + } +}; + +typedef boost::shared_ptr TcpClientSharedPtr; +typedef boost::weak_ptr TcpClientWeakPtr; + +class ConnInfo { + private: + meituan_mns::SGService sgservice_; + TcpClientSharedPtr sp_tcpclient_; + + std::multimap *p_map_weight_tcpclientwp_; + +//for relate to weight index, if not be deleted, safe + std::multimap::iterator + it_map_weight_tcpclientwp_index_; + + public: + ConnInfo(const meituan_mns::SGService &sgservice_tmp, + std::multimap * + p_map_weight_tcpclientwp) : sgservice_(sgservice_tmp), + p_map_weight_tcpclientwp_( + p_map_weight_tcpclientwp) {} + + ~ConnInfo(void) { + if (MNS_UNLIKELY(!p_map_weight_tcpclientwp_)) { + MNS_LOG_ERROR("p_map_weight_tcpclientwp_ NULL"); + } else { + MNS_LOG_INFO("delete appkey " << sgservice_.appkey << " ip: " + << sgservice_.ip << " port: " + << sgservice_.port + << " from weight pool"); + p_map_weight_tcpclientwp_->erase(it_map_weight_tcpclientwp_index_); + } + } + + const meituan_mns::SGService &GetSgservice(void) const { + return sgservice_; + } + + bool CheckConnHealthy(void) const; + + void UptSgservice(const meituan_mns::SGService &sgservice); + + void setSp_tcpclient_(const TcpClientSharedPtr &sp_tcpclient); + + TcpClientSharedPtr &getSp_tcpclient_() { + return sp_tcpclient_; + } + + /*int8_t FetchTcpConnSP(muduo::net::TcpConnectionPtr *p_tcpconn_sp) { + if (sp_tcpclient_.get() && sp_tcpclient_->connection()) { + p_tcpconn_sp->reset((sp_tcpclient_->connection()).get()); + return 0; + } + + LOG_INFO << "sp_tcpclient_ NOT init"; + return -1; + }*/ +}; + +typedef boost::shared_ptr ConnInfoSharedPtr; +typedef boost::weak_ptr ConnInfoWeakPtr; + +struct ConnContext4Worker { + public: + + bool b_highwater; + bool b_occupied; + + ConnInfoWeakPtr wp_conn_info; + + ConnContext4Worker(const ConnInfoSharedPtr &sp_conn_info) + : b_highwater(false), + b_occupied(false), wp_conn_info(sp_conn_info) {} +}; + +typedef boost::shared_ptr Context4WorkerSharedPtr; + +class MnsWorker { + private: + struct CnxtEntry : public muduo::copyable { + MnsWorker *p_worker_; + + explicit CnxtEntry(MnsWorker *parent) + : p_worker_(parent) {} + + ~CnxtEntry(void) { + p_worker_ = NULL; + } + }; + + typedef boost::unordered_map::iterator + UnorderedMapStr2SpConnInfoIter; + + boost::shared_ptr sp_tcpclient_sentinel_; + + muduo::MutexLock mutexlock_avaliable_conn_ready_; + muduo::Condition cond_avaliable_conn_ready_; + + muduo::AtomicInt32 + atomic_avaliable_conn_num_; //exclude disconn/highwater/occupied + + int8_t i8_destructor_flag_; + + char *unzip_buf_; + + muduo::net::InetAddress sentinel_url_addr_; + + boost::unordered_map + map_ipport_sgservice_; //use compare and update svrlist + + boost::shared_ptr sp_sgagent_client_; + + void OnConn4Sentinel(const muduo::net::TcpConnectionPtr &conn); + void OnMsg4Sentinel(const muduo::net::TcpConnectionPtr &conn, + muduo::net::Buffer *buffer, + muduo::Timestamp receiveTime); + + //for common srvlist update + boost::unordered_map + map_ipport_spconninfo_; + + std::multimap + * //ONLY used by conninfo + p_multimap_weight_wptcpcli_; + + typedef boost::unordered_map + ::iterator + UnorderedMapIpPort2ConnInfoSP; + + typedef std::multimap::iterator + MultiMapIter; + + boost::shared_ptr sp_event_thread_; + + muduo::net::EventLoop *p_event_loop_; + + void AddSrv(const std::vector &vec_add_sgservice); + void DelSrv(const std::vector &vec_add_sgservice); + void ChgSrv(const std::vector &vec_add_sgservice); + + void OnConn(const muduo::net::TcpConnectionPtr &conn); + void OnMsg(const muduo::net::TcpConnectionPtr &conn, + muduo::net::Buffer *buffer, + muduo::Timestamp receiveTime); + + void UpdateSvrList + (const std::vector &vec_sgservice); + + void InitWorker(void); + void InitSentinel(void); + void UnInitSentinel(void); + + void CheckLocalSgagent(); + bool CheckLocalSgagentHealth(void); + + int8_t ChooseNextReadyConn(TcpClientWeakPtr *p_wp_tcpcli); + static int8_t CheckRegion(const double &d_weight); + + public: + MnsWorker(); + + void ClearTcpClient(muduo::CountDownLatch *p_clear_countdown) { + MNS_LOG_DEBUG("into worker thread clean resource"); + map_ipport_spconninfo_.clear(); //clear tcpclient, OR may core when + // multiple tcpclient quit + if (sp_tcpclient_sentinel_) { + sp_tcpclient_sentinel_->disconnect(); + sp_tcpclient_sentinel_.reset(); + } + + //p_multimap_weight_wptcpcli_ only need free memory in work thread. + delete p_multimap_weight_wptcpcli_; + p_clear_countdown->countDown(); + } + + virtual ~MnsWorker() { + //set destructor flag + i8_destructor_flag_ = 1; + + muduo::CountDownLatch clear_countdown(1); + p_event_loop_->runInLoop(boost::bind(&MnsWorker::ClearTcpClient, + this, &clear_countdown)); + //wait until end of the destructor + clear_countdown.wait(); + + if (MNS_LIKELY(unzip_buf_)) { + delete unzip_buf_; + } + } + + int32_t GetServiceList(meituan_mns::ProtocolResponse &rsp, + const meituan_mns::ProtocolRequest &request); + + int32_t RegistService(const meituan_mns::SGService &sgService); + + void NotifyRegistService(RegisterParamsPtr params); + + void NotifyGetServiceList(ServerListParamsPtr params); + + void OnGetServiceList(ServerListParamsPtr params); + + void OnRegistService(RegisterParamsPtr params); + + muduo::net::EventLoop *getP_event_loop_(void) const { + return p_event_loop_; + } + + TcpClientSharedPtr GetAvailableConn(); + + int32_t getAtomic_avaliable_conn_num_() { + return atomic_avaliable_conn_num_.get(); + } + + muduo::Condition &getCond_avaliable_conn_ready_() { + return cond_avaliable_conn_ready_; + } + + muduo::MutexLock &getMutexlock_avaliable_conn_ready_(void) { + return mutexlock_avaliable_conn_ready_; + } + + ThriftClientHandler *InitHandler(const std::string &ip, const int port); + + void Init(); +}; +} + +#endif //OCTO_OPEN_SOURCE_MNS_WORKER_H_ diff --git a/sg_agent/thrid_party/thrid/include/mns_sdk/thrift_client.h b/sg_agent/thrid_party/thrid/include/mns_sdk/thrift_client.h new file mode 100644 index 0000000..ec347df --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/mns_sdk/thrift_client.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_THRIFT_CLIENT_H_ +#define OCTO_OPEN_SOURCE_THRIFT_CLIENT_H_ + +#include "util/mns_sdk_common.h" + +namespace mns_sdk { + +enum ProcType { + SG_AEGNT_TYPE, + UNKNOW_TYPE, +}; + +class ThriftClientHandler { + public: + ThriftClientHandler(); + ~ThriftClientHandler(); + int init(const std::string &host, int port, ProcType proc_type, bool local + = true); + int checkConnection(); + int createConnection(); + int closeConnection(); + int checkHandler(); + void *getClient() { + return m_client; + } + bool m_closed; + std::string m_host; + int m_port; + void *m_client; + boost::shared_ptr m_socket; + boost::shared_ptr m_transport; + boost::shared_ptr m_protocol; + ProcType type; +}; +}; +#endif // OCTO_OPEN_SOURCE_THRIFT_CLIENT_H_ \ No newline at end of file diff --git a/sg_agent/thrid_party/thrid/include/mns_sdk/util/mns_common.h b/sg_agent/thrid_party/thrid/include/mns_sdk/util/mns_common.h new file mode 100644 index 0000000..70e917a --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/mns_sdk/util/mns_common.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_UTIL_MNS_COMMON_H_ +#define OCTO_OPEN_SOURCE_UTIL_MNS_COMMON_H_ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "mns_log.h" + +#define MNS_SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } +#define MNS_SAFE_FREE(p) { if(p) { free(p); (p)=NULL; } } +#define MNS_SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } +#define MNS_SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } + +#define kDRetryIntervalSec 10.0 +#define kI32DefaultTimeoutMS 5000 +#define kI32DefaultTimeoutForReuestMS 100 + +typedef enum { + PROD, STAGING, DEV, PPE, TEST +} Appenv; + +#endif // OCTO_OPEN_SOURCE_UTIL_MNS_COMMON_H_ diff --git a/sg_agent/thrid_party/thrid/include/mns_sdk/util/mns_config.h b/sg_agent/thrid_party/thrid/include/mns_sdk/util/mns_config.h new file mode 100644 index 0000000..a9dbc50 --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/mns_sdk/util/mns_config.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_MNS_SDK_SRC_UTIL_MNS_CONFIG_H_ +#define OCTO_OPEN_SOURCE_MNS_SDK_SRC_UTIL_MNS_CONFIG_H_ + +#include "mns_sdk_common.h" + + +namespace mns_sdk { + +enum ONOFFLINE { + ONLINE, + OFFLINE, +}; + +class MnsConfig { + public: + MnsConfig(); + int LoadConfig(const std::string &str_file_path); + + public: + int InitAppnev(const std::map &config_map); + + void GetHostIPInfo(); + + std::string str_env_; + std::string str_octo_env_; + int enum_onoffline_env_; + + std::string url_; + std::string chrion_appkey_; + std::string chrion_sentienl_appkey_; + std::string str_idc_path_; + std::string str_local_chrion_port_; + int local_chrion_port_; + + bool b_use_remote_; + + std::string str_local_ip_; + std::string str_hostname_; + std::string str_host_; + + std::string str_sentinel_http_request_; +}; + +extern mns_sdk::MnsConfig g_config; +} // namespace mns_sdk + + + + +#endif // OCTO_OPEN_SOURCE_MNS_SDK_SRC_UTIL_MNS_CONFIG_H_ diff --git a/sg_agent/thrid_party/thrid/include/mns_sdk/util/mns_log.h b/sg_agent/thrid_party/thrid/include/mns_sdk/util/mns_log.h new file mode 100644 index 0000000..64588e5 --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/mns_sdk/util/mns_log.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_MNS_SDK_SRC_UTIL_MNS_LOG_H_ +#define OCTO_OPEN_SOURCE_MNS_SDK_SRC_UTIL_MNS_LOG_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mns_sdk { + +using std::auto_ptr; +using log4cplus::Logger; +using log4cplus::ConsoleAppender; +using log4cplus::FileAppender; +using log4cplus::Appender; +using log4cplus::Layout; +using log4cplus::PatternLayout; +using log4cplus::helpers::SharedObjectPtr; + +extern Logger debug_instance; +extern Logger info_instance; +extern Logger warn_instance; +extern Logger error_instance; +extern Logger fatal_instance; +extern Logger stat_instance; + +#define MNS_LOG_DEBUG(debugContent) \ + { LOG4CPLUS_DEBUG(debug_instance, debugContent); } +#define MNS_LOG_INFO(infoContent) \ + { LOG4CPLUS_INFO(info_instance, infoContent); } +#define MNS_LOG_WARN(warnContent) \ + { LOG4CPLUS_WARN(warn_instance, warnContent); } +#define MNS_LOG_ERROR(errorContent) \ + { LOG4CPLUS_ERROR(error_instance, errorContent); } +#define MNS_LOG_FATAL(fatalContent) \ + { LOG4CPLUS_ERROR(fatal_instance, fatalContent); } +#define MNS_LOG_STAT(statContent) \ + { LOG4CPLUS_INFO(stat_instance, statContent); } + +} // namespace mns_sdk + +#endif // OCTO_OPEN_SOURCE_MNS_SDK_SRC_UTIL_MNS_LOG_H_ diff --git a/sg_agent/thrid_party/thrid/include/mns_sdk/util/mns_sdk_common.h b/sg_agent/thrid_party/thrid/include/mns_sdk/util/mns_sdk_common.h new file mode 100644 index 0000000..734cb91 --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/mns_sdk/util/mns_sdk_common.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2011-2018, Meituan Dianping. All Rights Reserved. + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef OCTO_OPEN_SOURCE_MNS_SDK_COMMON_H_ +#define OCTO_OPEN_SOURCE_MNS_SDK_COMMON_H_ + +#include "mns_common.h" +#include "mns_config.h" + +namespace mns_sdk { +using namespace std; + +#define MNS_LIKELY(x) (__builtin_expect(!!(x), 1)) +#define MNS_UNLIKELY(x) (__builtin_expect(!!(x), 0)) + +#define ERR_CHECK_CONNECTION -300001 +#define ERR_CREATE_CONNECTION -300002 +#define ERR_CLOSE_CONNECTION -300003 + +#define CONNECTION_RETRY_TIMES 1 +#define SG_SERVER_READ_TIMEOUT 100 +#define SG_SERVER_CONN_TIMEOUT 50 +#define SG_SERVER_WRITE_TIMEOUT 50 +#define SG_LOCAL_SERVER_READ_TIMEOUT 30 +#define SG_LOCAL_SERVER_CONN_TIMEOUT 10 +#define SG_LOCAL_SERVER_WRITE_TIMEOUT 10 + +struct HttpContext { + muduo::net::HttpContext http_context; + uint32_t u32_want_len; +}; +typedef boost::shared_ptr HttpContextSharedPtr; + +class MnsSdkCommon { + public: + MnsSdkCommon(void); + + static std::string SGService2String(const meituan_mns::SGService &sgservice); + + static int8_t ParseSentineSgagentList + (const std::string &str_req, + std::vector *p_vec_sgservice); + + static int Hex2Decimal(const char *begin, const char *end); + static void ParseHttpChunkData(muduo::net::Buffer *pBuf, + muduo::net::HttpContext *pContext); + static bool ParseHttpRequest(uint32_t *pudwWantLen, + muduo::net::Buffer *buf, + muduo::net::HttpContext *context, + muduo::Timestamp receiveTime); + + static int FetchJsonValByKey4Doc(rapidjson::Document &reader, + const std::string &strKey, + rapidjson::Document::MemberIterator *pitr); + + static int FetchJsonValByKey4Val(rapidjson::Value &reader, + const std::string &strKey, + rapidjson::Value::MemberIterator *pitr); + + static void IntranetIp(char ip[INET_ADDRSTRLEN]); + + static int8_t FetchInt32FromJson + (const std::string &strKey, + rapidjson::Value &data_single, + int32_t *p_i32_value); + + static void replace_all_distinct + (const std::string &old_value, + const std::string &new_value, + std::string *p_str); + + static int CheckEmptyJsonStringVal(const + rapidjson::Document::MemberIterator &itr); + static int Httpgzdecompress(Byte *zdata, uLong nzdata, + Byte *data, uLong *ndata); + + static string strToLower(const string &str_tmp); + + static double + FetchOctoWeight(const double &fweight, const double &weight); + + static bool CheckDoubleEqual(const double &d1, const double &d2); + + static void PackDefaultSgservice(const string &str_svr_appkey, + const string &str_local_ip, + const uint16_t &u16_port, + meituan_mns::SGService *p_sgservice); + + static bool CheckOverTime(const muduo::Timestamp ×tamp, + const double &d_overtime_secs, + double *p_d_left_secs); + + const static double kDFirstRegionMin; + const static double kDSecondRegionMin; +}; + +} + +#endif //OCTO_OPEN_SOURCE_MNS_SDK_COMMON_H_ diff --git a/sg_agent/thrid_party/thrid/include/octoidl/MNSCacheService.h b/sg_agent/thrid_party/thrid/include/octoidl/MNSCacheService.h new file mode 100644 index 0000000..0601c18 --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/octoidl/MNSCacheService.h @@ -0,0 +1,937 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef MNSCacheService_H +#define MNSCacheService_H + +#include +#include "mnsc_service_types.h" + +namespace meituan_mns { + +class MNSCacheServiceIf { + public: + virtual ~MNSCacheServiceIf() {} + virtual void getMNSCache(MNSResponse& _return, const std::string& appkey, const std::string& version, const std::string& env) = 0; + virtual void getMNSCacheHttp(MNSResponse& _return, const std::string& appkey, const std::string& version, const std::string& env) = 0; + virtual void getMNSCacheWithVersionCheck(MNSResponse& _return, const MnsRequest& req) = 0; + virtual void getMNSCacheByAppkeys(MNSBatchResponse& _return, const std::vector & appkeys, const std::string& protocol) = 0; + virtual void getProvidersByIP(MNSResponse& _return, const std::string& ip) = 0; + virtual void getAppkeyListByIP(AppKeyListResponse& _return, const std::string& ip) = 0; +}; + +class MNSCacheServiceIfFactory { + public: + typedef MNSCacheServiceIf Handler; + + virtual ~MNSCacheServiceIfFactory() {} + + virtual MNSCacheServiceIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo) = 0; + virtual void releaseHandler(MNSCacheServiceIf* /* handler */) = 0; +}; + +class MNSCacheServiceIfSingletonFactory : virtual public MNSCacheServiceIfFactory { + public: + MNSCacheServiceIfSingletonFactory(const boost::shared_ptr& iface) : iface_(iface) {} + virtual ~MNSCacheServiceIfSingletonFactory() {} + + virtual MNSCacheServiceIf* getHandler(const ::apache::thrift::TConnectionInfo&) { + return iface_.get(); + } + virtual void releaseHandler(MNSCacheServiceIf* /* handler */) {} + + protected: + boost::shared_ptr iface_; +}; + +class MNSCacheServiceNull : virtual public MNSCacheServiceIf { + public: + virtual ~MNSCacheServiceNull() {} + void getMNSCache(MNSResponse& /* _return */, const std::string& /* appkey */, const std::string& /* version */, const std::string& /* env */) { + return; + } + void getMNSCacheHttp(MNSResponse& /* _return */, const std::string& /* appkey */, const std::string& /* version */, const std::string& /* env */) { + return; + } + void getMNSCacheWithVersionCheck(MNSResponse& /* _return */, const MnsRequest& /* req */) { + return; + } + void getMNSCacheByAppkeys(MNSBatchResponse& /* _return */, const std::vector & /* appkeys */, const std::string& /* protocol */) { + return; + } + void getProvidersByIP(MNSResponse& /* _return */, const std::string& /* ip */) { + return; + } + void getAppkeyListByIP(AppKeyListResponse& /* _return */, const std::string& /* ip */) { + return; + } +}; + +typedef struct _MNSCacheService_getMNSCache_args__isset { + _MNSCacheService_getMNSCache_args__isset() : appkey(false), version(false), env(false) {} + bool appkey; + bool version; + bool env; +} _MNSCacheService_getMNSCache_args__isset; + +class MNSCacheService_getMNSCache_args { + public: + + MNSCacheService_getMNSCache_args() : appkey(""), version(""), env("") { + } + + virtual ~MNSCacheService_getMNSCache_args() throw() {} + + std::string appkey; + std::string version; + std::string env; + + _MNSCacheService_getMNSCache_args__isset __isset; + + void __set_appkey(const std::string& val) { + appkey = val; + } + + void __set_version(const std::string& val) { + version = val; + } + + void __set_env(const std::string& val) { + env = val; + } + + bool operator == (const MNSCacheService_getMNSCache_args & rhs) const + { + if (!(appkey == rhs.appkey)) + return false; + if (!(version == rhs.version)) + return false; + if (!(env == rhs.env)) + return false; + return true; + } + bool operator != (const MNSCacheService_getMNSCache_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getMNSCache_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class MNSCacheService_getMNSCache_pargs { + public: + + + virtual ~MNSCacheService_getMNSCache_pargs() throw() {} + + const std::string* appkey; + const std::string* version; + const std::string* env; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getMNSCache_result__isset { + _MNSCacheService_getMNSCache_result__isset() : success(false) {} + bool success; +} _MNSCacheService_getMNSCache_result__isset; + +class MNSCacheService_getMNSCache_result { + public: + + MNSCacheService_getMNSCache_result() { + } + + virtual ~MNSCacheService_getMNSCache_result() throw() {} + + MNSResponse success; + + _MNSCacheService_getMNSCache_result__isset __isset; + + void __set_success(const MNSResponse& val) { + success = val; + } + + bool operator == (const MNSCacheService_getMNSCache_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const MNSCacheService_getMNSCache_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getMNSCache_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getMNSCache_presult__isset { + _MNSCacheService_getMNSCache_presult__isset() : success(false) {} + bool success; +} _MNSCacheService_getMNSCache_presult__isset; + +class MNSCacheService_getMNSCache_presult { + public: + + + virtual ~MNSCacheService_getMNSCache_presult() throw() {} + + MNSResponse* success; + + _MNSCacheService_getMNSCache_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +typedef struct _MNSCacheService_getMNSCacheHttp_args__isset { + _MNSCacheService_getMNSCacheHttp_args__isset() : appkey(false), version(false), env(false) {} + bool appkey; + bool version; + bool env; +} _MNSCacheService_getMNSCacheHttp_args__isset; + +class MNSCacheService_getMNSCacheHttp_args { + public: + + MNSCacheService_getMNSCacheHttp_args() : appkey(""), version(""), env("") { + } + + virtual ~MNSCacheService_getMNSCacheHttp_args() throw() {} + + std::string appkey; + std::string version; + std::string env; + + _MNSCacheService_getMNSCacheHttp_args__isset __isset; + + void __set_appkey(const std::string& val) { + appkey = val; + } + + void __set_version(const std::string& val) { + version = val; + } + + void __set_env(const std::string& val) { + env = val; + } + + bool operator == (const MNSCacheService_getMNSCacheHttp_args & rhs) const + { + if (!(appkey == rhs.appkey)) + return false; + if (!(version == rhs.version)) + return false; + if (!(env == rhs.env)) + return false; + return true; + } + bool operator != (const MNSCacheService_getMNSCacheHttp_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getMNSCacheHttp_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class MNSCacheService_getMNSCacheHttp_pargs { + public: + + + virtual ~MNSCacheService_getMNSCacheHttp_pargs() throw() {} + + const std::string* appkey; + const std::string* version; + const std::string* env; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getMNSCacheHttp_result__isset { + _MNSCacheService_getMNSCacheHttp_result__isset() : success(false) {} + bool success; +} _MNSCacheService_getMNSCacheHttp_result__isset; + +class MNSCacheService_getMNSCacheHttp_result { + public: + + MNSCacheService_getMNSCacheHttp_result() { + } + + virtual ~MNSCacheService_getMNSCacheHttp_result() throw() {} + + MNSResponse success; + + _MNSCacheService_getMNSCacheHttp_result__isset __isset; + + void __set_success(const MNSResponse& val) { + success = val; + } + + bool operator == (const MNSCacheService_getMNSCacheHttp_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const MNSCacheService_getMNSCacheHttp_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getMNSCacheHttp_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getMNSCacheHttp_presult__isset { + _MNSCacheService_getMNSCacheHttp_presult__isset() : success(false) {} + bool success; +} _MNSCacheService_getMNSCacheHttp_presult__isset; + +class MNSCacheService_getMNSCacheHttp_presult { + public: + + + virtual ~MNSCacheService_getMNSCacheHttp_presult() throw() {} + + MNSResponse* success; + + _MNSCacheService_getMNSCacheHttp_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +typedef struct _MNSCacheService_getMNSCacheWithVersionCheck_args__isset { + _MNSCacheService_getMNSCacheWithVersionCheck_args__isset() : req(false) {} + bool req; +} _MNSCacheService_getMNSCacheWithVersionCheck_args__isset; + +class MNSCacheService_getMNSCacheWithVersionCheck_args { + public: + + MNSCacheService_getMNSCacheWithVersionCheck_args() { + } + + virtual ~MNSCacheService_getMNSCacheWithVersionCheck_args() throw() {} + + MnsRequest req; + + _MNSCacheService_getMNSCacheWithVersionCheck_args__isset __isset; + + void __set_req(const MnsRequest& val) { + req = val; + } + + bool operator == (const MNSCacheService_getMNSCacheWithVersionCheck_args & rhs) const + { + if (!(req == rhs.req)) + return false; + return true; + } + bool operator != (const MNSCacheService_getMNSCacheWithVersionCheck_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getMNSCacheWithVersionCheck_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class MNSCacheService_getMNSCacheWithVersionCheck_pargs { + public: + + + virtual ~MNSCacheService_getMNSCacheWithVersionCheck_pargs() throw() {} + + const MnsRequest* req; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getMNSCacheWithVersionCheck_result__isset { + _MNSCacheService_getMNSCacheWithVersionCheck_result__isset() : success(false) {} + bool success; +} _MNSCacheService_getMNSCacheWithVersionCheck_result__isset; + +class MNSCacheService_getMNSCacheWithVersionCheck_result { + public: + + MNSCacheService_getMNSCacheWithVersionCheck_result() { + } + + virtual ~MNSCacheService_getMNSCacheWithVersionCheck_result() throw() {} + + MNSResponse success; + + _MNSCacheService_getMNSCacheWithVersionCheck_result__isset __isset; + + void __set_success(const MNSResponse& val) { + success = val; + } + + bool operator == (const MNSCacheService_getMNSCacheWithVersionCheck_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const MNSCacheService_getMNSCacheWithVersionCheck_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getMNSCacheWithVersionCheck_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getMNSCacheWithVersionCheck_presult__isset { + _MNSCacheService_getMNSCacheWithVersionCheck_presult__isset() : success(false) {} + bool success; +} _MNSCacheService_getMNSCacheWithVersionCheck_presult__isset; + +class MNSCacheService_getMNSCacheWithVersionCheck_presult { + public: + + + virtual ~MNSCacheService_getMNSCacheWithVersionCheck_presult() throw() {} + + MNSResponse* success; + + _MNSCacheService_getMNSCacheWithVersionCheck_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +typedef struct _MNSCacheService_getMNSCacheByAppkeys_args__isset { + _MNSCacheService_getMNSCacheByAppkeys_args__isset() : appkeys(false), protocol(false) {} + bool appkeys; + bool protocol; +} _MNSCacheService_getMNSCacheByAppkeys_args__isset; + +class MNSCacheService_getMNSCacheByAppkeys_args { + public: + + MNSCacheService_getMNSCacheByAppkeys_args() : protocol("") { + } + + virtual ~MNSCacheService_getMNSCacheByAppkeys_args() throw() {} + + std::vector appkeys; + std::string protocol; + + _MNSCacheService_getMNSCacheByAppkeys_args__isset __isset; + + void __set_appkeys(const std::vector & val) { + appkeys = val; + } + + void __set_protocol(const std::string& val) { + protocol = val; + } + + bool operator == (const MNSCacheService_getMNSCacheByAppkeys_args & rhs) const + { + if (!(appkeys == rhs.appkeys)) + return false; + if (!(protocol == rhs.protocol)) + return false; + return true; + } + bool operator != (const MNSCacheService_getMNSCacheByAppkeys_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getMNSCacheByAppkeys_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class MNSCacheService_getMNSCacheByAppkeys_pargs { + public: + + + virtual ~MNSCacheService_getMNSCacheByAppkeys_pargs() throw() {} + + const std::vector * appkeys; + const std::string* protocol; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getMNSCacheByAppkeys_result__isset { + _MNSCacheService_getMNSCacheByAppkeys_result__isset() : success(false) {} + bool success; +} _MNSCacheService_getMNSCacheByAppkeys_result__isset; + +class MNSCacheService_getMNSCacheByAppkeys_result { + public: + + MNSCacheService_getMNSCacheByAppkeys_result() { + } + + virtual ~MNSCacheService_getMNSCacheByAppkeys_result() throw() {} + + MNSBatchResponse success; + + _MNSCacheService_getMNSCacheByAppkeys_result__isset __isset; + + void __set_success(const MNSBatchResponse& val) { + success = val; + } + + bool operator == (const MNSCacheService_getMNSCacheByAppkeys_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const MNSCacheService_getMNSCacheByAppkeys_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getMNSCacheByAppkeys_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getMNSCacheByAppkeys_presult__isset { + _MNSCacheService_getMNSCacheByAppkeys_presult__isset() : success(false) {} + bool success; +} _MNSCacheService_getMNSCacheByAppkeys_presult__isset; + +class MNSCacheService_getMNSCacheByAppkeys_presult { + public: + + + virtual ~MNSCacheService_getMNSCacheByAppkeys_presult() throw() {} + + MNSBatchResponse* success; + + _MNSCacheService_getMNSCacheByAppkeys_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +typedef struct _MNSCacheService_getProvidersByIP_args__isset { + _MNSCacheService_getProvidersByIP_args__isset() : ip(false) {} + bool ip; +} _MNSCacheService_getProvidersByIP_args__isset; + +class MNSCacheService_getProvidersByIP_args { + public: + + MNSCacheService_getProvidersByIP_args() : ip("") { + } + + virtual ~MNSCacheService_getProvidersByIP_args() throw() {} + + std::string ip; + + _MNSCacheService_getProvidersByIP_args__isset __isset; + + void __set_ip(const std::string& val) { + ip = val; + } + + bool operator == (const MNSCacheService_getProvidersByIP_args & rhs) const + { + if (!(ip == rhs.ip)) + return false; + return true; + } + bool operator != (const MNSCacheService_getProvidersByIP_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getProvidersByIP_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class MNSCacheService_getProvidersByIP_pargs { + public: + + + virtual ~MNSCacheService_getProvidersByIP_pargs() throw() {} + + const std::string* ip; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getProvidersByIP_result__isset { + _MNSCacheService_getProvidersByIP_result__isset() : success(false) {} + bool success; +} _MNSCacheService_getProvidersByIP_result__isset; + +class MNSCacheService_getProvidersByIP_result { + public: + + MNSCacheService_getProvidersByIP_result() { + } + + virtual ~MNSCacheService_getProvidersByIP_result() throw() {} + + MNSResponse success; + + _MNSCacheService_getProvidersByIP_result__isset __isset; + + void __set_success(const MNSResponse& val) { + success = val; + } + + bool operator == (const MNSCacheService_getProvidersByIP_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const MNSCacheService_getProvidersByIP_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getProvidersByIP_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getProvidersByIP_presult__isset { + _MNSCacheService_getProvidersByIP_presult__isset() : success(false) {} + bool success; +} _MNSCacheService_getProvidersByIP_presult__isset; + +class MNSCacheService_getProvidersByIP_presult { + public: + + + virtual ~MNSCacheService_getProvidersByIP_presult() throw() {} + + MNSResponse* success; + + _MNSCacheService_getProvidersByIP_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +typedef struct _MNSCacheService_getAppkeyListByIP_args__isset { + _MNSCacheService_getAppkeyListByIP_args__isset() : ip(false) {} + bool ip; +} _MNSCacheService_getAppkeyListByIP_args__isset; + +class MNSCacheService_getAppkeyListByIP_args { + public: + + MNSCacheService_getAppkeyListByIP_args() : ip("") { + } + + virtual ~MNSCacheService_getAppkeyListByIP_args() throw() {} + + std::string ip; + + _MNSCacheService_getAppkeyListByIP_args__isset __isset; + + void __set_ip(const std::string& val) { + ip = val; + } + + bool operator == (const MNSCacheService_getAppkeyListByIP_args & rhs) const + { + if (!(ip == rhs.ip)) + return false; + return true; + } + bool operator != (const MNSCacheService_getAppkeyListByIP_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getAppkeyListByIP_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class MNSCacheService_getAppkeyListByIP_pargs { + public: + + + virtual ~MNSCacheService_getAppkeyListByIP_pargs() throw() {} + + const std::string* ip; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getAppkeyListByIP_result__isset { + _MNSCacheService_getAppkeyListByIP_result__isset() : success(false) {} + bool success; +} _MNSCacheService_getAppkeyListByIP_result__isset; + +class MNSCacheService_getAppkeyListByIP_result { + public: + + MNSCacheService_getAppkeyListByIP_result() { + } + + virtual ~MNSCacheService_getAppkeyListByIP_result() throw() {} + + AppKeyListResponse success; + + _MNSCacheService_getAppkeyListByIP_result__isset __isset; + + void __set_success(const AppKeyListResponse& val) { + success = val; + } + + bool operator == (const MNSCacheService_getAppkeyListByIP_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const MNSCacheService_getAppkeyListByIP_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSCacheService_getAppkeyListByIP_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSCacheService_getAppkeyListByIP_presult__isset { + _MNSCacheService_getAppkeyListByIP_presult__isset() : success(false) {} + bool success; +} _MNSCacheService_getAppkeyListByIP_presult__isset; + +class MNSCacheService_getAppkeyListByIP_presult { + public: + + + virtual ~MNSCacheService_getAppkeyListByIP_presult() throw() {} + + AppKeyListResponse* success; + + _MNSCacheService_getAppkeyListByIP_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +class MNSCacheServiceClient : virtual public MNSCacheServiceIf { + public: + MNSCacheServiceClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> prot) : + piprot_(prot), + poprot_(prot) { + iprot_ = prot.get(); + oprot_ = prot.get(); + } + MNSCacheServiceClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> iprot, boost::shared_ptr< ::apache::thrift::protocol::TProtocol> oprot) : + piprot_(iprot), + poprot_(oprot) { + iprot_ = iprot.get(); + oprot_ = oprot.get(); + } + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol() { + return piprot_; + } + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol() { + return poprot_; + } + void getMNSCache(MNSResponse& _return, const std::string& appkey, const std::string& version, const std::string& env); + void send_getMNSCache(const std::string& appkey, const std::string& version, const std::string& env); + void recv_getMNSCache(MNSResponse& _return); + void getMNSCacheHttp(MNSResponse& _return, const std::string& appkey, const std::string& version, const std::string& env); + void send_getMNSCacheHttp(const std::string& appkey, const std::string& version, const std::string& env); + void recv_getMNSCacheHttp(MNSResponse& _return); + void getMNSCacheWithVersionCheck(MNSResponse& _return, const MnsRequest& req); + void send_getMNSCacheWithVersionCheck(const MnsRequest& req); + void recv_getMNSCacheWithVersionCheck(MNSResponse& _return); + void getMNSCacheByAppkeys(MNSBatchResponse& _return, const std::vector & appkeys, const std::string& protocol); + void send_getMNSCacheByAppkeys(const std::vector & appkeys, const std::string& protocol); + void recv_getMNSCacheByAppkeys(MNSBatchResponse& _return); + void getProvidersByIP(MNSResponse& _return, const std::string& ip); + void send_getProvidersByIP(const std::string& ip); + void recv_getProvidersByIP(MNSResponse& _return); + void getAppkeyListByIP(AppKeyListResponse& _return, const std::string& ip); + void send_getAppkeyListByIP(const std::string& ip); + void recv_getAppkeyListByIP(AppKeyListResponse& _return); + protected: + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> piprot_; + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> poprot_; + ::apache::thrift::protocol::TProtocol* iprot_; + ::apache::thrift::protocol::TProtocol* oprot_; +}; + +class MNSCacheServiceProcessor : public ::apache::thrift::TProcessor { + protected: + boost::shared_ptr iface_; + virtual bool process_fn(apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, std::string& fname, int32_t seqid, void* callContext); + private: + std::map processMap_; + void process_getMNSCache(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_getMNSCacheHttp(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_getMNSCacheWithVersionCheck(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_getMNSCacheByAppkeys(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_getProvidersByIP(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_getAppkeyListByIP(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + public: + MNSCacheServiceProcessor(boost::shared_ptr iface) : + iface_(iface) { + processMap_["getMNSCache"] = &MNSCacheServiceProcessor::process_getMNSCache; + processMap_["getMNSCacheHttp"] = &MNSCacheServiceProcessor::process_getMNSCacheHttp; + processMap_["getMNSCacheWithVersionCheck"] = &MNSCacheServiceProcessor::process_getMNSCacheWithVersionCheck; + processMap_["getMNSCacheByAppkeys"] = &MNSCacheServiceProcessor::process_getMNSCacheByAppkeys; + processMap_["getProvidersByIP"] = &MNSCacheServiceProcessor::process_getProvidersByIP; + processMap_["getAppkeyListByIP"] = &MNSCacheServiceProcessor::process_getAppkeyListByIP; + } + + virtual bool process(boost::shared_ptr piprot, boost::shared_ptr poprot, void* callContext); + virtual ~MNSCacheServiceProcessor() {} +}; + +class MNSCacheServiceProcessorFactory : public ::apache::thrift::TProcessorFactory { + public: + MNSCacheServiceProcessorFactory(const ::boost::shared_ptr< MNSCacheServiceIfFactory >& handlerFactory) : + handlerFactory_(handlerFactory) {} + + ::boost::shared_ptr< ::apache::thrift::TProcessor > getProcessor(const ::apache::thrift::TConnectionInfo& connInfo); + + protected: + ::boost::shared_ptr< MNSCacheServiceIfFactory > handlerFactory_; +}; + +class MNSCacheServiceMultiface : virtual public MNSCacheServiceIf { + public: + MNSCacheServiceMultiface(std::vector >& ifaces) : ifaces_(ifaces) { + } + virtual ~MNSCacheServiceMultiface() {} + protected: + std::vector > ifaces_; + MNSCacheServiceMultiface() {} + void add(boost::shared_ptr iface) { + ifaces_.push_back(iface); + } + public: + void getMNSCache(MNSResponse& _return, const std::string& appkey, const std::string& version, const std::string& env) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getMNSCache(_return, appkey, version, env); + return; + } else { + ifaces_[i]->getMNSCache(_return, appkey, version, env); + } + } + } + + void getMNSCacheHttp(MNSResponse& _return, const std::string& appkey, const std::string& version, const std::string& env) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getMNSCacheHttp(_return, appkey, version, env); + return; + } else { + ifaces_[i]->getMNSCacheHttp(_return, appkey, version, env); + } + } + } + + void getMNSCacheWithVersionCheck(MNSResponse& _return, const MnsRequest& req) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getMNSCacheWithVersionCheck(_return, req); + return; + } else { + ifaces_[i]->getMNSCacheWithVersionCheck(_return, req); + } + } + } + + void getMNSCacheByAppkeys(MNSBatchResponse& _return, const std::vector & appkeys, const std::string& protocol) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getMNSCacheByAppkeys(_return, appkeys, protocol); + return; + } else { + ifaces_[i]->getMNSCacheByAppkeys(_return, appkeys, protocol); + } + } + } + + void getProvidersByIP(MNSResponse& _return, const std::string& ip) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getProvidersByIP(_return, ip); + return; + } else { + ifaces_[i]->getProvidersByIP(_return, ip); + } + } + } + + void getAppkeyListByIP(AppKeyListResponse& _return, const std::string& ip) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getAppkeyListByIP(_return, ip); + return; + } else { + ifaces_[i]->getAppkeyListByIP(_return, ip); + } + } + } + +}; + +} // namespace + +#endif diff --git a/sg_agent/thrid_party/thrid/include/octoidl/ServiceAgent.h b/sg_agent/thrid_party/thrid/include/octoidl/ServiceAgent.h new file mode 100644 index 0000000..b20dd69 --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/octoidl/ServiceAgent.h @@ -0,0 +1,772 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef ServiceAgent_H +#define ServiceAgent_H + +#include +#include "naming_service_types.h" + +namespace meituan_mns { + +class ServiceAgentIf { + public: + virtual ~ServiceAgentIf() {} + virtual void getServiceListByProtocol(ProtocolResponse& _return, const ProtocolRequest& req) = 0; + virtual void getOriginServiceList(ProtocolResponse& _return, const ProtocolRequest& req) = 0; + virtual int32_t registService(const SGService& oService) = 0; + virtual int32_t registServicewithCmd(const int32_t uptCmd, const SGService& oService) = 0; + virtual int32_t unRegistService(const SGService& oService) = 0; +}; + +class ServiceAgentIfFactory { + public: + typedef ServiceAgentIf Handler; + + virtual ~ServiceAgentIfFactory() {} + + virtual ServiceAgentIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo) = 0; + virtual void releaseHandler(ServiceAgentIf* /* handler */) = 0; +}; + +class ServiceAgentIfSingletonFactory : virtual public ServiceAgentIfFactory { + public: + ServiceAgentIfSingletonFactory(const boost::shared_ptr& iface) : iface_(iface) {} + virtual ~ServiceAgentIfSingletonFactory() {} + + virtual ServiceAgentIf* getHandler(const ::apache::thrift::TConnectionInfo&) { + return iface_.get(); + } + virtual void releaseHandler(ServiceAgentIf* /* handler */) {} + + protected: + boost::shared_ptr iface_; +}; + +class ServiceAgentNull : virtual public ServiceAgentIf { + public: + virtual ~ServiceAgentNull() {} + void getServiceListByProtocol(ProtocolResponse& /* _return */, const ProtocolRequest& /* req */) { + return; + } + void getOriginServiceList(ProtocolResponse& /* _return */, const ProtocolRequest& /* req */) { + return; + } + int32_t registService(const SGService& /* oService */) { + int32_t _return = 0; + return _return; + } + int32_t registServicewithCmd(const int32_t /* uptCmd */, const SGService& /* oService */) { + int32_t _return = 0; + return _return; + } + int32_t unRegistService(const SGService& /* oService */) { + int32_t _return = 0; + return _return; + } +}; + +typedef struct _ServiceAgent_getServiceListByProtocol_args__isset { + _ServiceAgent_getServiceListByProtocol_args__isset() : req(false) {} + bool req; +} _ServiceAgent_getServiceListByProtocol_args__isset; + +class ServiceAgent_getServiceListByProtocol_args { + public: + + ServiceAgent_getServiceListByProtocol_args() { + } + + virtual ~ServiceAgent_getServiceListByProtocol_args() throw() {} + + ProtocolRequest req; + + _ServiceAgent_getServiceListByProtocol_args__isset __isset; + + void __set_req(const ProtocolRequest& val) { + req = val; + } + + bool operator == (const ServiceAgent_getServiceListByProtocol_args & rhs) const + { + if (!(req == rhs.req)) + return false; + return true; + } + bool operator != (const ServiceAgent_getServiceListByProtocol_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_getServiceListByProtocol_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class ServiceAgent_getServiceListByProtocol_pargs { + public: + + + virtual ~ServiceAgent_getServiceListByProtocol_pargs() throw() {} + + const ProtocolRequest* req; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_getServiceListByProtocol_result__isset { + _ServiceAgent_getServiceListByProtocol_result__isset() : success(false) {} + bool success; +} _ServiceAgent_getServiceListByProtocol_result__isset; + +class ServiceAgent_getServiceListByProtocol_result { + public: + + ServiceAgent_getServiceListByProtocol_result() { + } + + virtual ~ServiceAgent_getServiceListByProtocol_result() throw() {} + + ProtocolResponse success; + + _ServiceAgent_getServiceListByProtocol_result__isset __isset; + + void __set_success(const ProtocolResponse& val) { + success = val; + } + + bool operator == (const ServiceAgent_getServiceListByProtocol_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const ServiceAgent_getServiceListByProtocol_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_getServiceListByProtocol_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_getServiceListByProtocol_presult__isset { + _ServiceAgent_getServiceListByProtocol_presult__isset() : success(false) {} + bool success; +} _ServiceAgent_getServiceListByProtocol_presult__isset; + +class ServiceAgent_getServiceListByProtocol_presult { + public: + + + virtual ~ServiceAgent_getServiceListByProtocol_presult() throw() {} + + ProtocolResponse* success; + + _ServiceAgent_getServiceListByProtocol_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +typedef struct _ServiceAgent_getOriginServiceList_args__isset { + _ServiceAgent_getOriginServiceList_args__isset() : req(false) {} + bool req; +} _ServiceAgent_getOriginServiceList_args__isset; + +class ServiceAgent_getOriginServiceList_args { + public: + + ServiceAgent_getOriginServiceList_args() { + } + + virtual ~ServiceAgent_getOriginServiceList_args() throw() {} + + ProtocolRequest req; + + _ServiceAgent_getOriginServiceList_args__isset __isset; + + void __set_req(const ProtocolRequest& val) { + req = val; + } + + bool operator == (const ServiceAgent_getOriginServiceList_args & rhs) const + { + if (!(req == rhs.req)) + return false; + return true; + } + bool operator != (const ServiceAgent_getOriginServiceList_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_getOriginServiceList_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class ServiceAgent_getOriginServiceList_pargs { + public: + + + virtual ~ServiceAgent_getOriginServiceList_pargs() throw() {} + + const ProtocolRequest* req; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_getOriginServiceList_result__isset { + _ServiceAgent_getOriginServiceList_result__isset() : success(false) {} + bool success; +} _ServiceAgent_getOriginServiceList_result__isset; + +class ServiceAgent_getOriginServiceList_result { + public: + + ServiceAgent_getOriginServiceList_result() { + } + + virtual ~ServiceAgent_getOriginServiceList_result() throw() {} + + ProtocolResponse success; + + _ServiceAgent_getOriginServiceList_result__isset __isset; + + void __set_success(const ProtocolResponse& val) { + success = val; + } + + bool operator == (const ServiceAgent_getOriginServiceList_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const ServiceAgent_getOriginServiceList_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_getOriginServiceList_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_getOriginServiceList_presult__isset { + _ServiceAgent_getOriginServiceList_presult__isset() : success(false) {} + bool success; +} _ServiceAgent_getOriginServiceList_presult__isset; + +class ServiceAgent_getOriginServiceList_presult { + public: + + + virtual ~ServiceAgent_getOriginServiceList_presult() throw() {} + + ProtocolResponse* success; + + _ServiceAgent_getOriginServiceList_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +typedef struct _ServiceAgent_registService_args__isset { + _ServiceAgent_registService_args__isset() : oService(false) {} + bool oService; +} _ServiceAgent_registService_args__isset; + +class ServiceAgent_registService_args { + public: + + ServiceAgent_registService_args() { + } + + virtual ~ServiceAgent_registService_args() throw() {} + + SGService oService; + + _ServiceAgent_registService_args__isset __isset; + + void __set_oService(const SGService& val) { + oService = val; + } + + bool operator == (const ServiceAgent_registService_args & rhs) const + { + if (!(oService == rhs.oService)) + return false; + return true; + } + bool operator != (const ServiceAgent_registService_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_registService_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class ServiceAgent_registService_pargs { + public: + + + virtual ~ServiceAgent_registService_pargs() throw() {} + + const SGService* oService; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_registService_result__isset { + _ServiceAgent_registService_result__isset() : success(false) {} + bool success; +} _ServiceAgent_registService_result__isset; + +class ServiceAgent_registService_result { + public: + + ServiceAgent_registService_result() : success(0) { + } + + virtual ~ServiceAgent_registService_result() throw() {} + + int32_t success; + + _ServiceAgent_registService_result__isset __isset; + + void __set_success(const int32_t val) { + success = val; + } + + bool operator == (const ServiceAgent_registService_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const ServiceAgent_registService_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_registService_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_registService_presult__isset { + _ServiceAgent_registService_presult__isset() : success(false) {} + bool success; +} _ServiceAgent_registService_presult__isset; + +class ServiceAgent_registService_presult { + public: + + + virtual ~ServiceAgent_registService_presult() throw() {} + + int32_t* success; + + _ServiceAgent_registService_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +typedef struct _ServiceAgent_registServicewithCmd_args__isset { + _ServiceAgent_registServicewithCmd_args__isset() : uptCmd(false), oService(false) {} + bool uptCmd; + bool oService; +} _ServiceAgent_registServicewithCmd_args__isset; + +class ServiceAgent_registServicewithCmd_args { + public: + + ServiceAgent_registServicewithCmd_args() : uptCmd(0) { + } + + virtual ~ServiceAgent_registServicewithCmd_args() throw() {} + + int32_t uptCmd; + SGService oService; + + _ServiceAgent_registServicewithCmd_args__isset __isset; + + void __set_uptCmd(const int32_t val) { + uptCmd = val; + } + + void __set_oService(const SGService& val) { + oService = val; + } + + bool operator == (const ServiceAgent_registServicewithCmd_args & rhs) const + { + if (!(uptCmd == rhs.uptCmd)) + return false; + if (!(oService == rhs.oService)) + return false; + return true; + } + bool operator != (const ServiceAgent_registServicewithCmd_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_registServicewithCmd_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class ServiceAgent_registServicewithCmd_pargs { + public: + + + virtual ~ServiceAgent_registServicewithCmd_pargs() throw() {} + + const int32_t* uptCmd; + const SGService* oService; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_registServicewithCmd_result__isset { + _ServiceAgent_registServicewithCmd_result__isset() : success(false) {} + bool success; +} _ServiceAgent_registServicewithCmd_result__isset; + +class ServiceAgent_registServicewithCmd_result { + public: + + ServiceAgent_registServicewithCmd_result() : success(0) { + } + + virtual ~ServiceAgent_registServicewithCmd_result() throw() {} + + int32_t success; + + _ServiceAgent_registServicewithCmd_result__isset __isset; + + void __set_success(const int32_t val) { + success = val; + } + + bool operator == (const ServiceAgent_registServicewithCmd_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const ServiceAgent_registServicewithCmd_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_registServicewithCmd_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_registServicewithCmd_presult__isset { + _ServiceAgent_registServicewithCmd_presult__isset() : success(false) {} + bool success; +} _ServiceAgent_registServicewithCmd_presult__isset; + +class ServiceAgent_registServicewithCmd_presult { + public: + + + virtual ~ServiceAgent_registServicewithCmd_presult() throw() {} + + int32_t* success; + + _ServiceAgent_registServicewithCmd_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +typedef struct _ServiceAgent_unRegistService_args__isset { + _ServiceAgent_unRegistService_args__isset() : oService(false) {} + bool oService; +} _ServiceAgent_unRegistService_args__isset; + +class ServiceAgent_unRegistService_args { + public: + + ServiceAgent_unRegistService_args() { + } + + virtual ~ServiceAgent_unRegistService_args() throw() {} + + SGService oService; + + _ServiceAgent_unRegistService_args__isset __isset; + + void __set_oService(const SGService& val) { + oService = val; + } + + bool operator == (const ServiceAgent_unRegistService_args & rhs) const + { + if (!(oService == rhs.oService)) + return false; + return true; + } + bool operator != (const ServiceAgent_unRegistService_args &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_unRegistService_args & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class ServiceAgent_unRegistService_pargs { + public: + + + virtual ~ServiceAgent_unRegistService_pargs() throw() {} + + const SGService* oService; + + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_unRegistService_result__isset { + _ServiceAgent_unRegistService_result__isset() : success(false) {} + bool success; +} _ServiceAgent_unRegistService_result__isset; + +class ServiceAgent_unRegistService_result { + public: + + ServiceAgent_unRegistService_result() : success(0) { + } + + virtual ~ServiceAgent_unRegistService_result() throw() {} + + int32_t success; + + _ServiceAgent_unRegistService_result__isset __isset; + + void __set_success(const int32_t val) { + success = val; + } + + bool operator == (const ServiceAgent_unRegistService_result & rhs) const + { + if (!(success == rhs.success)) + return false; + return true; + } + bool operator != (const ServiceAgent_unRegistService_result &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceAgent_unRegistService_result & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceAgent_unRegistService_presult__isset { + _ServiceAgent_unRegistService_presult__isset() : success(false) {} + bool success; +} _ServiceAgent_unRegistService_presult__isset; + +class ServiceAgent_unRegistService_presult { + public: + + + virtual ~ServiceAgent_unRegistService_presult() throw() {} + + int32_t* success; + + _ServiceAgent_unRegistService_presult__isset __isset; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + +}; + +class ServiceAgentClient : virtual public ServiceAgentIf { + public: + ServiceAgentClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> prot) : + piprot_(prot), + poprot_(prot) { + iprot_ = prot.get(); + oprot_ = prot.get(); + } + ServiceAgentClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> iprot, boost::shared_ptr< ::apache::thrift::protocol::TProtocol> oprot) : + piprot_(iprot), + poprot_(oprot) { + iprot_ = iprot.get(); + oprot_ = oprot.get(); + } + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol() { + return piprot_; + } + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol() { + return poprot_; + } + void getServiceListByProtocol(ProtocolResponse& _return, const ProtocolRequest& req); + void send_getServiceListByProtocol(const ProtocolRequest& req); + void recv_getServiceListByProtocol(ProtocolResponse& _return); + void getOriginServiceList(ProtocolResponse& _return, const ProtocolRequest& req); + void send_getOriginServiceList(const ProtocolRequest& req); + void recv_getOriginServiceList(ProtocolResponse& _return); + int32_t registService(const SGService& oService); + void send_registService(const SGService& oService); + int32_t recv_registService(); + int32_t registServicewithCmd(const int32_t uptCmd, const SGService& oService); + void send_registServicewithCmd(const int32_t uptCmd, const SGService& oService); + int32_t recv_registServicewithCmd(); + int32_t unRegistService(const SGService& oService); + void send_unRegistService(const SGService& oService); + int32_t recv_unRegistService(); + protected: + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> piprot_; + boost::shared_ptr< ::apache::thrift::protocol::TProtocol> poprot_; + ::apache::thrift::protocol::TProtocol* iprot_; + ::apache::thrift::protocol::TProtocol* oprot_; +}; + +class ServiceAgentProcessor : public ::apache::thrift::TProcessor { + protected: + boost::shared_ptr iface_; + virtual bool process_fn(apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, std::string& fname, int32_t seqid, void* callContext); + private: + std::map processMap_; + void process_getServiceListByProtocol(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_getOriginServiceList(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_registService(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_registServicewithCmd(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + void process_unRegistService(int32_t seqid, apache::thrift::protocol::TProtocol* iprot, apache::thrift::protocol::TProtocol* oprot, void* callContext); + public: + ServiceAgentProcessor(boost::shared_ptr iface) : + iface_(iface) { + processMap_["getServiceListByProtocol"] = &ServiceAgentProcessor::process_getServiceListByProtocol; + processMap_["getOriginServiceList"] = &ServiceAgentProcessor::process_getOriginServiceList; + processMap_["registService"] = &ServiceAgentProcessor::process_registService; + processMap_["registServicewithCmd"] = &ServiceAgentProcessor::process_registServicewithCmd; + processMap_["unRegistService"] = &ServiceAgentProcessor::process_unRegistService; + } + + virtual bool process(boost::shared_ptr piprot, boost::shared_ptr poprot, void* callContext); + virtual ~ServiceAgentProcessor() {} +}; + +class ServiceAgentProcessorFactory : public ::apache::thrift::TProcessorFactory { + public: + ServiceAgentProcessorFactory(const ::boost::shared_ptr< ServiceAgentIfFactory >& handlerFactory) : + handlerFactory_(handlerFactory) {} + + ::boost::shared_ptr< ::apache::thrift::TProcessor > getProcessor(const ::apache::thrift::TConnectionInfo& connInfo); + + protected: + ::boost::shared_ptr< ServiceAgentIfFactory > handlerFactory_; +}; + +class ServiceAgentMultiface : virtual public ServiceAgentIf { + public: + ServiceAgentMultiface(std::vector >& ifaces) : ifaces_(ifaces) { + } + virtual ~ServiceAgentMultiface() {} + protected: + std::vector > ifaces_; + ServiceAgentMultiface() {} + void add(boost::shared_ptr iface) { + ifaces_.push_back(iface); + } + public: + void getServiceListByProtocol(ProtocolResponse& _return, const ProtocolRequest& req) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getServiceListByProtocol(_return, req); + return; + } else { + ifaces_[i]->getServiceListByProtocol(_return, req); + } + } + } + + void getOriginServiceList(ProtocolResponse& _return, const ProtocolRequest& req) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + ifaces_[i]->getOriginServiceList(_return, req); + return; + } else { + ifaces_[i]->getOriginServiceList(_return, req); + } + } + } + + int32_t registService(const SGService& oService) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + return ifaces_[i]->registService(oService); + } else { + ifaces_[i]->registService(oService); + } + } + } + + int32_t registServicewithCmd(const int32_t uptCmd, const SGService& oService) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + return ifaces_[i]->registServicewithCmd(uptCmd, oService); + } else { + ifaces_[i]->registServicewithCmd(uptCmd, oService); + } + } + } + + int32_t unRegistService(const SGService& oService) { + size_t sz = ifaces_.size(); + for (size_t i = 0; i < sz; ++i) { + if (i == sz - 1) { + return ifaces_[i]->unRegistService(oService); + } else { + ifaces_[i]->unRegistService(oService); + } + } + } + +}; + +} // namespace + +#endif diff --git a/sg_agent/thrid_party/thrid/include/octoidl/ThriftSpans_constants.h b/sg_agent/thrid_party/thrid/include/octoidl/ThriftSpans_constants.h new file mode 100644 index 0000000..d5d80b9 --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/octoidl/ThriftSpans_constants.h @@ -0,0 +1,24 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef ThriftSpans_CONSTANTS_H +#define ThriftSpans_CONSTANTS_H + +#include "ThriftSpans_types.h" + + + +class ThriftSpansConstants { + public: + ThriftSpansConstants(); + +}; + +extern const ThriftSpansConstants g_ThriftSpans_constants; + + + +#endif diff --git a/sg_agent/thrid_party/thrid/include/octoidl/ThriftSpans_types.h b/sg_agent/thrid_party/thrid/include/octoidl/ThriftSpans_types.h new file mode 100644 index 0000000..74b7ead --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/octoidl/ThriftSpans_types.h @@ -0,0 +1,420 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef ThriftSpans_TYPES_H +#define ThriftSpans_TYPES_H + +#include +#include +#include +#include + + + + + +struct StatusCode { + enum type { + SUCCESS = 0, + EXCEPTION = 1, + TIMEOUT = 2, + DROP = 3 + }; +}; + +extern const std::map _StatusCode_VALUES_TO_NAMES; + + +class Endpoint { + public: + + static const char* ascii_fingerprint; // = "C7D2D58463AC91C552EE8B325EA2ACCC"; + static const uint8_t binary_fingerprint[16]; // = {0xC7,0xD2,0xD5,0x84,0x63,0xAC,0x91,0xC5,0x52,0xEE,0x8B,0x32,0x5E,0xA2,0xAC,0xCC}; + + Endpoint() : ip(0), port(0), appKey("") { + } + + virtual ~Endpoint() throw() {} + + int32_t ip; + int16_t port; + std::string appKey; + + void __set_ip(const int32_t val) { + ip = val; + } + + void __set_port(const int16_t val) { + port = val; + } + + void __set_appKey(const std::string& val) { + appKey = val; + } + + bool operator == (const Endpoint & rhs) const + { + if (!(ip == rhs.ip)) + return false; + if (!(port == rhs.port)) + return false; + if (!(appKey == rhs.appKey)) + return false; + return true; + } + bool operator != (const Endpoint &rhs) const { + return !(*this == rhs); + } + + bool operator < (const Endpoint & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _Annotation__isset { + _Annotation__isset() : duration(false) {} + bool duration; +} _Annotation__isset; + +class Annotation { + public: + + static const char* ascii_fingerprint; // = "CE5BE9A8A7BD398538F703F899B08A94"; + static const uint8_t binary_fingerprint[16]; // = {0xCE,0x5B,0xE9,0xA8,0xA7,0xBD,0x39,0x85,0x38,0xF7,0x03,0xF8,0x99,0xB0,0x8A,0x94}; + + Annotation() : value(""), timestamp(0), duration(0) { + } + + virtual ~Annotation() throw() {} + + std::string value; + int64_t timestamp; + int32_t duration; + + _Annotation__isset __isset; + + void __set_value(const std::string& val) { + value = val; + } + + void __set_timestamp(const int64_t val) { + timestamp = val; + } + + void __set_duration(const int32_t val) { + duration = val; + __isset.duration = true; + } + + bool operator == (const Annotation & rhs) const + { + if (!(value == rhs.value)) + return false; + if (!(timestamp == rhs.timestamp)) + return false; + if (__isset.duration != rhs.__isset.duration) + return false; + else if (__isset.duration && !(duration == rhs.duration)) + return false; + return true; + } + bool operator != (const Annotation &rhs) const { + return !(*this == rhs); + } + + bool operator < (const Annotation & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + +class KVAnnotation { + public: + + static const char* ascii_fingerprint; // = "07A9615F837F7D0A952B595DD3020972"; + static const uint8_t binary_fingerprint[16]; // = {0x07,0xA9,0x61,0x5F,0x83,0x7F,0x7D,0x0A,0x95,0x2B,0x59,0x5D,0xD3,0x02,0x09,0x72}; + + KVAnnotation() : key(""), value("") { + } + + virtual ~KVAnnotation() throw() {} + + std::string key; + std::string value; + + void __set_key(const std::string& val) { + key = val; + } + + void __set_value(const std::string& val) { + value = val; + } + + bool operator == (const KVAnnotation & rhs) const + { + if (!(key == rhs.key)) + return false; + if (!(value == rhs.value)) + return false; + return true; + } + bool operator != (const KVAnnotation &rhs) const { + return !(*this == rhs); + } + + bool operator < (const KVAnnotation & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ThriftSpan__isset { + _ThriftSpan__isset() : annotations(false), type(false), packageSize(false), infraName(false), infraVersion(false), kvAnnotations(false), status(false), mask(false) {} + bool annotations; + bool type; + bool packageSize; + bool infraName; + bool infraVersion; + bool kvAnnotations; + bool status; + bool mask; +} _ThriftSpan__isset; + +class ThriftSpan { + public: + + static const char* ascii_fingerprint; // = "B08D60902E6EF2A6DF2C5746A48261F4"; + static const uint8_t binary_fingerprint[16]; // = {0xB0,0x8D,0x60,0x90,0x2E,0x6E,0xF2,0xA6,0xDF,0x2C,0x57,0x46,0xA4,0x82,0x61,0xF4}; + + ThriftSpan() : traceId(0), spanId(""), spanName(""), start(0), duration(0), clientSide(0), type(""), packageSize(0), infraName(""), infraVersion(""), status((StatusCode::type)0), mask(0) { + } + + virtual ~ThriftSpan() throw() {} + + int64_t traceId; + std::string spanId; + std::string spanName; + Endpoint local; + Endpoint remote; + int64_t start; + int32_t duration; + bool clientSide; + std::vector annotations; + std::string type; + int32_t packageSize; + std::string infraName; + std::string infraVersion; + std::vector kvAnnotations; + StatusCode::type status; + int32_t mask; + + _ThriftSpan__isset __isset; + + void __set_traceId(const int64_t val) { + traceId = val; + } + + void __set_spanId(const std::string& val) { + spanId = val; + } + + void __set_spanName(const std::string& val) { + spanName = val; + } + + void __set_local(const Endpoint& val) { + local = val; + } + + void __set_remote(const Endpoint& val) { + remote = val; + } + + void __set_start(const int64_t val) { + start = val; + } + + void __set_duration(const int32_t val) { + duration = val; + } + + void __set_clientSide(const bool val) { + clientSide = val; + } + + void __set_annotations(const std::vector & val) { + annotations = val; + __isset.annotations = true; + } + + void __set_type(const std::string& val) { + type = val; + __isset.type = true; + } + + void __set_packageSize(const int32_t val) { + packageSize = val; + __isset.packageSize = true; + } + + void __set_infraName(const std::string& val) { + infraName = val; + __isset.infraName = true; + } + + void __set_infraVersion(const std::string& val) { + infraVersion = val; + __isset.infraVersion = true; + } + + void __set_kvAnnotations(const std::vector & val) { + kvAnnotations = val; + __isset.kvAnnotations = true; + } + + void __set_status(const StatusCode::type val) { + status = val; + __isset.status = true; + } + + void __set_mask(const int32_t val) { + mask = val; + __isset.mask = true; + } + + bool operator == (const ThriftSpan & rhs) const + { + if (!(traceId == rhs.traceId)) + return false; + if (!(spanId == rhs.spanId)) + return false; + if (!(spanName == rhs.spanName)) + return false; + if (!(local == rhs.local)) + return false; + if (!(remote == rhs.remote)) + return false; + if (!(start == rhs.start)) + return false; + if (!(duration == rhs.duration)) + return false; + if (!(clientSide == rhs.clientSide)) + return false; + if (__isset.annotations != rhs.__isset.annotations) + return false; + else if (__isset.annotations && !(annotations == rhs.annotations)) + return false; + if (__isset.type != rhs.__isset.type) + return false; + else if (__isset.type && !(type == rhs.type)) + return false; + if (__isset.packageSize != rhs.__isset.packageSize) + return false; + else if (__isset.packageSize && !(packageSize == rhs.packageSize)) + return false; + if (__isset.infraName != rhs.__isset.infraName) + return false; + else if (__isset.infraName && !(infraName == rhs.infraName)) + return false; + if (__isset.infraVersion != rhs.__isset.infraVersion) + return false; + else if (__isset.infraVersion && !(infraVersion == rhs.infraVersion)) + return false; + if (__isset.kvAnnotations != rhs.__isset.kvAnnotations) + return false; + else if (__isset.kvAnnotations && !(kvAnnotations == rhs.kvAnnotations)) + return false; + if (__isset.status != rhs.__isset.status) + return false; + else if (__isset.status && !(status == rhs.status)) + return false; + if (__isset.mask != rhs.__isset.mask) + return false; + else if (__isset.mask && !(mask == rhs.mask)) + return false; + return true; + } + bool operator != (const ThriftSpan &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ThriftSpan & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ThriftSpanList__isset { + _ThriftSpanList__isset() : var1(false), var2(false) {} + bool var1; + bool var2; +} _ThriftSpanList__isset; + +class ThriftSpanList { + public: + + static const char* ascii_fingerprint; // = "01BB7DF5DC125F694C08EE3ED02BB420"; + static const uint8_t binary_fingerprint[16]; // = {0x01,0xBB,0x7D,0xF5,0xDC,0x12,0x5F,0x69,0x4C,0x08,0xEE,0x3E,0xD0,0x2B,0xB4,0x20}; + + ThriftSpanList() : var1(0), var2("") { + } + + virtual ~ThriftSpanList() throw() {} + + std::vector spans; + int32_t var1; + std::string var2; + + _ThriftSpanList__isset __isset; + + void __set_spans(const std::vector & val) { + spans = val; + } + + void __set_var1(const int32_t val) { + var1 = val; + __isset.var1 = true; + } + + void __set_var2(const std::string& val) { + var2 = val; + __isset.var2 = true; + } + + bool operator == (const ThriftSpanList & rhs) const + { + if (!(spans == rhs.spans)) + return false; + if (__isset.var1 != rhs.__isset.var1) + return false; + else if (__isset.var1 && !(var1 == rhs.var1)) + return false; + if (__isset.var2 != rhs.__isset.var2) + return false; + else if (__isset.var2 && !(var2 == rhs.var2)) + return false; + return true; + } + bool operator != (const ThriftSpanList &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ThriftSpanList & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + + + +#endif diff --git a/sg_agent/thrid_party/thrid/include/octoidl/mnsc_data_constants.h b/sg_agent/thrid_party/thrid/include/octoidl/mnsc_data_constants.h new file mode 100644 index 0000000..77fc7ab --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/octoidl/mnsc_data_constants.h @@ -0,0 +1,33 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef mnsc_data_CONSTANTS_H +#define mnsc_data_CONSTANTS_H + +#include "mnsc_data_types.h" + +namespace meituan_mns { + +class mnsc_dataConstants { + public: + mnsc_dataConstants(); + + std::string PROD; + std::string STAGE; + std::string TEST; + int32_t SUCCESS; + int32_t MNSCache_UPDATE; + int32_t TIMEOUT_ERROR; + int32_t ILLEGAL_ARGUMENT; + int32_t NOT_FOUND; + int32_t NOT_MODIFIED; +}; + +extern const mnsc_dataConstants g_mnsc_data_constants; + +} // namespace + +#endif diff --git a/sg_agent/thrid_party/thrid/include/octoidl/mnsc_data_types.h b/sg_agent/thrid_party/thrid/include/octoidl/mnsc_data_types.h new file mode 100644 index 0000000..5835c20 --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/octoidl/mnsc_data_types.h @@ -0,0 +1,254 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef mnsc_data_TYPES_H +#define mnsc_data_TYPES_H + +#include +#include +#include +#include + +#include "naming_common_types.h" + + +namespace meituan_mns { + +struct Protocols { + enum type { + THRIFT = 0, + HTTP = 1 + }; +}; + +extern const std::map _Protocols_VALUES_TO_NAMES; + +typedef class ::meituan_mns::SGService SGService; + +typedef struct _MNSResponse__isset { + _MNSResponse__isset() : defaultMNSCache(false), version(false) {} + bool defaultMNSCache; + bool version; +} _MNSResponse__isset; + +class MNSResponse { + public: + + static const char* ascii_fingerprint; // = "262B7A6EE88301D8EA2B9CBECB4AF401"; + static const uint8_t binary_fingerprint[16]; // = {0x26,0x2B,0x7A,0x6E,0xE8,0x83,0x01,0xD8,0xEA,0x2B,0x9C,0xBE,0xCB,0x4A,0xF4,0x01}; + + MNSResponse() : code(200), version("") { + } + + virtual ~MNSResponse() throw() {} + + int32_t code; + std::vector defaultMNSCache; + std::string version; + + _MNSResponse__isset __isset; + + void __set_code(const int32_t val) { + code = val; + } + + void __set_defaultMNSCache(const std::vector & val) { + defaultMNSCache = val; + __isset.defaultMNSCache = true; + } + + void __set_version(const std::string& val) { + version = val; + __isset.version = true; + } + + bool operator == (const MNSResponse & rhs) const + { + if (!(code == rhs.code)) + return false; + if (__isset.defaultMNSCache != rhs.__isset.defaultMNSCache) + return false; + else if (__isset.defaultMNSCache && !(defaultMNSCache == rhs.defaultMNSCache)) + return false; + if (__isset.version != rhs.__isset.version) + return false; + else if (__isset.version && !(version == rhs.version)) + return false; + return true; + } + bool operator != (const MNSResponse &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSResponse & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MNSBatchResponse__isset { + _MNSBatchResponse__isset() : cache(false) {} + bool cache; +} _MNSBatchResponse__isset; + +class MNSBatchResponse { + public: + + static const char* ascii_fingerprint; // = "C0A3C40A83F3EC7069EF8B80B7669355"; + static const uint8_t binary_fingerprint[16]; // = {0xC0,0xA3,0xC4,0x0A,0x83,0xF3,0xEC,0x70,0x69,0xEF,0x8B,0x80,0xB7,0x66,0x93,0x55}; + + MNSBatchResponse() : code(200) { + } + + virtual ~MNSBatchResponse() throw() {} + + int32_t code; + std::map > > cache; + + _MNSBatchResponse__isset __isset; + + void __set_code(const int32_t val) { + code = val; + } + + void __set_cache(const std::map > > & val) { + cache = val; + __isset.cache = true; + } + + bool operator == (const MNSBatchResponse & rhs) const + { + if (!(code == rhs.code)) + return false; + if (__isset.cache != rhs.__isset.cache) + return false; + else if (__isset.cache && !(cache == rhs.cache)) + return false; + return true; + } + bool operator != (const MNSBatchResponse &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MNSBatchResponse & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _AppKeyListResponse__isset { + _AppKeyListResponse__isset() : appKeyList(false) {} + bool appKeyList; +} _AppKeyListResponse__isset; + +class AppKeyListResponse { + public: + + static const char* ascii_fingerprint; // = "93CC3D1E71866966C22792AABF4C3815"; + static const uint8_t binary_fingerprint[16]; // = {0x93,0xCC,0x3D,0x1E,0x71,0x86,0x69,0x66,0xC2,0x27,0x92,0xAA,0xBF,0x4C,0x38,0x15}; + + AppKeyListResponse() : code(200) { + } + + virtual ~AppKeyListResponse() throw() {} + + int32_t code; + std::vector appKeyList; + + _AppKeyListResponse__isset __isset; + + void __set_code(const int32_t val) { + code = val; + } + + void __set_appKeyList(const std::vector & val) { + appKeyList = val; + __isset.appKeyList = true; + } + + bool operator == (const AppKeyListResponse & rhs) const + { + if (!(code == rhs.code)) + return false; + if (__isset.appKeyList != rhs.__isset.appKeyList) + return false; + else if (__isset.appKeyList && !(appKeyList == rhs.appKeyList)) + return false; + return true; + } + bool operator != (const AppKeyListResponse &rhs) const { + return !(*this == rhs); + } + + bool operator < (const AppKeyListResponse & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _MnsRequest__isset { + _MnsRequest__isset() : protoctol(false), appkey(false), env(false) {} + bool protoctol; + bool appkey; + bool env; +} _MnsRequest__isset; + +class MnsRequest { + public: + + static const char* ascii_fingerprint; // = "38C252E94E93B69D04EB3A6EE2F9EDFB"; + static const uint8_t binary_fingerprint[16]; // = {0x38,0xC2,0x52,0xE9,0x4E,0x93,0xB6,0x9D,0x04,0xEB,0x3A,0x6E,0xE2,0xF9,0xED,0xFB}; + + MnsRequest() : protoctol((Protocols::type)0), appkey(""), env("") { + } + + virtual ~MnsRequest() throw() {} + + Protocols::type protoctol; + std::string appkey; + std::string env; + + _MnsRequest__isset __isset; + + void __set_protoctol(const Protocols::type val) { + protoctol = val; + } + + void __set_appkey(const std::string& val) { + appkey = val; + } + + void __set_env(const std::string& val) { + env = val; + } + + bool operator == (const MnsRequest & rhs) const + { + if (!(protoctol == rhs.protoctol)) + return false; + if (!(appkey == rhs.appkey)) + return false; + if (!(env == rhs.env)) + return false; + return true; + } + bool operator != (const MnsRequest &rhs) const { + return !(*this == rhs); + } + + bool operator < (const MnsRequest & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +} // namespace + +#endif diff --git a/sg_agent/thrid_party/thrid/include/octoidl/mnsc_service_constants.h b/sg_agent/thrid_party/thrid/include/octoidl/mnsc_service_constants.h new file mode 100644 index 0000000..7c99008 --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/octoidl/mnsc_service_constants.h @@ -0,0 +1,24 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef mnsc_service_CONSTANTS_H +#define mnsc_service_CONSTANTS_H + +#include "mnsc_service_types.h" + +namespace meituan_mns { + +class mnsc_serviceConstants { + public: + mnsc_serviceConstants(); + +}; + +extern const mnsc_serviceConstants g_mnsc_service_constants; + +} // namespace + +#endif diff --git a/sg_agent/thrid_party/thrid/include/octoidl/mnsc_service_types.h b/sg_agent/thrid_party/thrid/include/octoidl/mnsc_service_types.h new file mode 100644 index 0000000..6a0bbd0 --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/octoidl/mnsc_service_types.h @@ -0,0 +1,32 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef mnsc_service_TYPES_H +#define mnsc_service_TYPES_H + +#include +#include +#include +#include + +#include "mnsc_data_types.h" + + +namespace meituan_mns { + +typedef class ::meituan_mns::MNSResponse MNSResponse; + +typedef class ::meituan_mns::MNSBatchResponse MNSBatchResponse; + +typedef class ::meituan_mns::AppKeyListResponse AppKeyListResponse; + +typedef class ::meituan_mns::MnsRequest MnsRequest; + +typedef ::meituan_mns::SGService SGService; + +} // namespace + +#endif diff --git a/sg_agent/thrid_party/thrid/include/octoidl/naming_common_constants.h b/sg_agent/thrid_party/thrid/include/octoidl/naming_common_constants.h new file mode 100644 index 0000000..abc434b --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/octoidl/naming_common_constants.h @@ -0,0 +1,24 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef naming_common_CONSTANTS_H +#define naming_common_CONSTANTS_H + +#include "naming_common_types.h" + +namespace meituan_mns { + +class naming_commonConstants { + public: + naming_commonConstants(); + +}; + +extern const naming_commonConstants g_naming_common_constants; + +} // namespace + +#endif diff --git a/sg_agent/thrid_party/thrid/include/octoidl/naming_common_types.h b/sg_agent/thrid_party/thrid/include/octoidl/naming_common_types.h new file mode 100644 index 0000000..b15324b --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/octoidl/naming_common_types.h @@ -0,0 +1,744 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef naming_common_TYPES_H +#define naming_common_TYPES_H + +#include +#include +#include +#include + + + +namespace meituan_mns { + +struct UptCmd { + enum type { + RESET = 0, + ADD = 1, + DELETE = 2 + }; +}; + +extern const std::map _UptCmd_VALUES_TO_NAMES; + +struct fb_status { + enum type { + DEAD = 0, + STARTING = 1, + ALIVE = 2, + STOPPING = 3, + STOPPED = 4, + WARNING = 5 + }; +}; + +extern const std::map _fb_status_VALUES_TO_NAMES; + +struct HeartbeatSupportType { + enum type { + NoSupport = 0, + P2POnly = 1, + ScannerOnly = 2, + BothSupport = 3 + }; +}; + +extern const std::map _HeartbeatSupportType_VALUES_TO_NAMES; + +typedef struct _ServiceDetail__isset { + _ServiceDetail__isset() : unifiedProto(false) {} + bool unifiedProto; +} _ServiceDetail__isset; + +class ServiceDetail { + public: + + static const char* ascii_fingerprint; // = "5892306F7B861249AE8E27C8ED619593"; + static const uint8_t binary_fingerprint[16]; // = {0x58,0x92,0x30,0x6F,0x7B,0x86,0x12,0x49,0xAE,0x8E,0x27,0xC8,0xED,0x61,0x95,0x93}; + + ServiceDetail() : unifiedProto(0) { + } + + virtual ~ServiceDetail() throw() {} + + bool unifiedProto; + + _ServiceDetail__isset __isset; + + void __set_unifiedProto(const bool val) { + unifiedProto = val; + } + + bool operator == (const ServiceDetail & rhs) const + { + if (!(unifiedProto == rhs.unifiedProto)) + return false; + return true; + } + bool operator != (const ServiceDetail &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceDetail & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _SGService__isset { + _SGService__isset() : appkey(false), version(false), ip(false), port(false), weight(false), status(false), role(false), envir(false), lastUpdateTime(false), fweight(false), serverType(false), protocol(false), serviceInfo(false), heartbeatSupport(false), warmup(false) {} + bool appkey; + bool version; + bool ip; + bool port; + bool weight; + bool status; + bool role; + bool envir; + bool lastUpdateTime; + bool fweight; + bool serverType; + bool protocol; + bool serviceInfo; + bool heartbeatSupport; + bool warmup; +} _SGService__isset; + +class SGService { + public: + + static const char* ascii_fingerprint; // = "BE473A6FD5DE924200DDD8D539C779C1"; + static const uint8_t binary_fingerprint[16]; // = {0xBE,0x47,0x3A,0x6F,0xD5,0xDE,0x92,0x42,0x00,0xDD,0xD8,0xD5,0x39,0xC7,0x79,0xC1}; + + SGService() : appkey(""), version(""), ip(""), port(0), weight(0), status(0), role(0), envir(0), lastUpdateTime(0), fweight(0), serverType(0), protocol(""), heartbeatSupport(0), warmup(0) { + } + + virtual ~SGService() throw() {} + + std::string appkey; + std::string version; + std::string ip; + int32_t port; + int32_t weight; + int32_t status; + int32_t role; + int32_t envir; + int32_t lastUpdateTime; + double fweight; + int32_t serverType; + std::string protocol; + std::map serviceInfo; + int8_t heartbeatSupport; + int32_t warmup; + + _SGService__isset __isset; + + void __set_appkey(const std::string& val) { + appkey = val; + } + + void __set_version(const std::string& val) { + version = val; + } + + void __set_ip(const std::string& val) { + ip = val; + } + + void __set_port(const int32_t val) { + port = val; + } + + void __set_weight(const int32_t val) { + weight = val; + } + + void __set_status(const int32_t val) { + status = val; + } + + void __set_role(const int32_t val) { + role = val; + } + + void __set_envir(const int32_t val) { + envir = val; + } + + void __set_lastUpdateTime(const int32_t val) { + lastUpdateTime = val; + } + + void __set_fweight(const double val) { + fweight = val; + } + + void __set_serverType(const int32_t val) { + serverType = val; + } + + void __set_protocol(const std::string& val) { + protocol = val; + } + + void __set_serviceInfo(const std::map & val) { + serviceInfo = val; + } + + void __set_heartbeatSupport(const int8_t val) { + heartbeatSupport = val; + } + + void __set_warmup(const int32_t val) { + warmup = val; + } + + bool operator == (const SGService & rhs) const + { + if (!(appkey == rhs.appkey)) + return false; + if (!(version == rhs.version)) + return false; + if (!(ip == rhs.ip)) + return false; + if (!(port == rhs.port)) + return false; + if (!(weight == rhs.weight)) + return false; + if (!(status == rhs.status)) + return false; + if (!(role == rhs.role)) + return false; + if (!(envir == rhs.envir)) + return false; + if (!(lastUpdateTime == rhs.lastUpdateTime)) + return false; + if (!(fweight == rhs.fweight)) + return false; + if (!(serverType == rhs.serverType)) + return false; + if (!(protocol == rhs.protocol)) + return false; + if (!(serviceInfo == rhs.serviceInfo)) + return false; + if (!(heartbeatSupport == rhs.heartbeatSupport)) + return false; + if (!(warmup == rhs.warmup)) + return false; + return true; + } + bool operator != (const SGService &rhs) const { + return !(*this == rhs); + } + + bool operator < (const SGService & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ServiceNode__isset { + _ServiceNode__isset() : serviceName(false), appkeys(false), lastUpdateTime(false) {} + bool serviceName; + bool appkeys; + bool lastUpdateTime; +} _ServiceNode__isset; + +class ServiceNode { + public: + + static const char* ascii_fingerprint; // = "E6EB76A1BCBAF7124A43817D5BC322F7"; + static const uint8_t binary_fingerprint[16]; // = {0xE6,0xEB,0x76,0xA1,0xBC,0xBA,0xF7,0x12,0x4A,0x43,0x81,0x7D,0x5B,0xC3,0x22,0xF7}; + + ServiceNode() : serviceName(""), lastUpdateTime(0) { + } + + virtual ~ServiceNode() throw() {} + + std::string serviceName; + std::set appkeys; + int32_t lastUpdateTime; + + _ServiceNode__isset __isset; + + void __set_serviceName(const std::string& val) { + serviceName = val; + } + + void __set_appkeys(const std::set & val) { + appkeys = val; + } + + void __set_lastUpdateTime(const int32_t val) { + lastUpdateTime = val; + } + + bool operator == (const ServiceNode & rhs) const + { + if (!(serviceName == rhs.serviceName)) + return false; + if (!(appkeys == rhs.appkeys)) + return false; + if (!(lastUpdateTime == rhs.lastUpdateTime)) + return false; + return true; + } + bool operator != (const ServiceNode &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ServiceNode & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _Consumer__isset { + _Consumer__isset() : ips(false), appkeys(false) {} + bool ips; + bool appkeys; +} _Consumer__isset; + +class Consumer { + public: + + static const char* ascii_fingerprint; // = "AA819045335EAFAB5C2FE456B4B9CC1C"; + static const uint8_t binary_fingerprint[16]; // = {0xAA,0x81,0x90,0x45,0x33,0x5E,0xAF,0xAB,0x5C,0x2F,0xE4,0x56,0xB4,0xB9,0xCC,0x1C}; + + Consumer() { + } + + virtual ~Consumer() throw() {} + + std::vector ips; + std::vector appkeys; + + _Consumer__isset __isset; + + void __set_ips(const std::vector & val) { + ips = val; + } + + void __set_appkeys(const std::vector & val) { + appkeys = val; + } + + bool operator == (const Consumer & rhs) const + { + if (!(ips == rhs.ips)) + return false; + if (!(appkeys == rhs.appkeys)) + return false; + return true; + } + bool operator != (const Consumer &rhs) const { + return !(*this == rhs); + } + + bool operator < (const Consumer & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _CRouteData__isset { + _CRouteData__isset() : id(false), name(false), appkey(false), env(false), category(false), priority(false), status(false), consumer(false), provider(false), updateTime(false), createTime(false), reserved(false) {} + bool id; + bool name; + bool appkey; + bool env; + bool category; + bool priority; + bool status; + bool consumer; + bool provider; + bool updateTime; + bool createTime; + bool reserved; +} _CRouteData__isset; + +class CRouteData { + public: + + static const char* ascii_fingerprint; // = "BA097AEDC13A13D0EF25D33F4578FC59"; + static const uint8_t binary_fingerprint[16]; // = {0xBA,0x09,0x7A,0xED,0xC1,0x3A,0x13,0xD0,0xEF,0x25,0xD3,0x3F,0x45,0x78,0xFC,0x59}; + + CRouteData() : id(""), name(""), appkey(""), env(0), category(0), priority(0), status(0), updateTime(0), createTime(0), reserved("") { + } + + virtual ~CRouteData() throw() {} + + std::string id; + std::string name; + std::string appkey; + int32_t env; + int32_t category; + int32_t priority; + int32_t status; + Consumer consumer; + std::vector provider; + int32_t updateTime; + int32_t createTime; + std::string reserved; + + _CRouteData__isset __isset; + + void __set_id(const std::string& val) { + id = val; + } + + void __set_name(const std::string& val) { + name = val; + } + + void __set_appkey(const std::string& val) { + appkey = val; + } + + void __set_env(const int32_t val) { + env = val; + } + + void __set_category(const int32_t val) { + category = val; + } + + void __set_priority(const int32_t val) { + priority = val; + } + + void __set_status(const int32_t val) { + status = val; + } + + void __set_consumer(const Consumer& val) { + consumer = val; + } + + void __set_provider(const std::vector & val) { + provider = val; + } + + void __set_updateTime(const int32_t val) { + updateTime = val; + } + + void __set_createTime(const int32_t val) { + createTime = val; + } + + void __set_reserved(const std::string& val) { + reserved = val; + } + + bool operator == (const CRouteData & rhs) const + { + if (!(id == rhs.id)) + return false; + if (!(name == rhs.name)) + return false; + if (!(appkey == rhs.appkey)) + return false; + if (!(env == rhs.env)) + return false; + if (!(category == rhs.category)) + return false; + if (!(priority == rhs.priority)) + return false; + if (!(status == rhs.status)) + return false; + if (!(consumer == rhs.consumer)) + return false; + if (!(provider == rhs.provider)) + return false; + if (!(updateTime == rhs.updateTime)) + return false; + if (!(createTime == rhs.createTime)) + return false; + if (!(reserved == rhs.reserved)) + return false; + return true; + } + bool operator != (const CRouteData &rhs) const { + return !(*this == rhs); + } + + bool operator < (const CRouteData & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _CProviderNode__isset { + _CProviderNode__isset() : appkey(false), lastModifiedTime(false), mtime(false), cversion(false), version(false) {} + bool appkey; + bool lastModifiedTime; + bool mtime; + bool cversion; + bool version; +} _CProviderNode__isset; + +class CProviderNode { + public: + + static const char* ascii_fingerprint; // = "9118FDD77343DD231D97C424A53D2DCF"; + static const uint8_t binary_fingerprint[16]; // = {0x91,0x18,0xFD,0xD7,0x73,0x43,0xDD,0x23,0x1D,0x97,0xC4,0x24,0xA5,0x3D,0x2D,0xCF}; + + CProviderNode() : appkey(""), lastModifiedTime(0), mtime(0), cversion(0), version(0) { + } + + virtual ~CProviderNode() throw() {} + + std::string appkey; + int64_t lastModifiedTime; + int64_t mtime; + int64_t cversion; + int64_t version; + + _CProviderNode__isset __isset; + + void __set_appkey(const std::string& val) { + appkey = val; + } + + void __set_lastModifiedTime(const int64_t val) { + lastModifiedTime = val; + } + + void __set_mtime(const int64_t val) { + mtime = val; + } + + void __set_cversion(const int64_t val) { + cversion = val; + } + + void __set_version(const int64_t val) { + version = val; + } + + bool operator == (const CProviderNode & rhs) const + { + if (!(appkey == rhs.appkey)) + return false; + if (!(lastModifiedTime == rhs.lastModifiedTime)) + return false; + if (!(mtime == rhs.mtime)) + return false; + if (!(cversion == rhs.cversion)) + return false; + if (!(version == rhs.version)) + return false; + return true; + } + bool operator != (const CProviderNode &rhs) const { + return !(*this == rhs); + } + + bool operator < (const CProviderNode & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _CRouteNode__isset { + _CRouteNode__isset() : appkey(false), lastModifiedTime(false), mtime(false), cversion(false), version(false) {} + bool appkey; + bool lastModifiedTime; + bool mtime; + bool cversion; + bool version; +} _CRouteNode__isset; + +class CRouteNode { + public: + + static const char* ascii_fingerprint; // = "9118FDD77343DD231D97C424A53D2DCF"; + static const uint8_t binary_fingerprint[16]; // = {0x91,0x18,0xFD,0xD7,0x73,0x43,0xDD,0x23,0x1D,0x97,0xC4,0x24,0xA5,0x3D,0x2D,0xCF}; + + CRouteNode() : appkey(""), lastModifiedTime(0), mtime(0), cversion(0), version(0) { + } + + virtual ~CRouteNode() throw() {} + + std::string appkey; + int64_t lastModifiedTime; + int64_t mtime; + int64_t cversion; + int64_t version; + + _CRouteNode__isset __isset; + + void __set_appkey(const std::string& val) { + appkey = val; + } + + void __set_lastModifiedTime(const int64_t val) { + lastModifiedTime = val; + } + + void __set_mtime(const int64_t val) { + mtime = val; + } + + void __set_cversion(const int64_t val) { + cversion = val; + } + + void __set_version(const int64_t val) { + version = val; + } + + bool operator == (const CRouteNode & rhs) const + { + if (!(appkey == rhs.appkey)) + return false; + if (!(lastModifiedTime == rhs.lastModifiedTime)) + return false; + if (!(mtime == rhs.mtime)) + return false; + if (!(cversion == rhs.cversion)) + return false; + if (!(version == rhs.version)) + return false; + return true; + } + bool operator != (const CRouteNode &rhs) const { + return !(*this == rhs); + } + + bool operator < (const CRouteNode & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ProtocolRequest__isset { + _ProtocolRequest__isset() : localAppkey(false), remoteAppkey(false), protocol(false), serviceName(false) {} + bool localAppkey; + bool remoteAppkey; + bool protocol; + bool serviceName; +} _ProtocolRequest__isset; + +class ProtocolRequest { + public: + + static const char* ascii_fingerprint; // = "C93D890311F28844166CF6E571EB3AC2"; + static const uint8_t binary_fingerprint[16]; // = {0xC9,0x3D,0x89,0x03,0x11,0xF2,0x88,0x44,0x16,0x6C,0xF6,0xE5,0x71,0xEB,0x3A,0xC2}; + + ProtocolRequest() : localAppkey(""), remoteAppkey(""), protocol(""), serviceName("") { + } + + virtual ~ProtocolRequest() throw() {} + + std::string localAppkey; + std::string remoteAppkey; + std::string protocol; + std::string serviceName; + + _ProtocolRequest__isset __isset; + + void __set_localAppkey(const std::string& val) { + localAppkey = val; + } + + void __set_remoteAppkey(const std::string& val) { + remoteAppkey = val; + } + + void __set_protocol(const std::string& val) { + protocol = val; + } + + void __set_serviceName(const std::string& val) { + serviceName = val; + } + + bool operator == (const ProtocolRequest & rhs) const + { + if (!(localAppkey == rhs.localAppkey)) + return false; + if (!(remoteAppkey == rhs.remoteAppkey)) + return false; + if (!(protocol == rhs.protocol)) + return false; + if (!(serviceName == rhs.serviceName)) + return false; + return true; + } + bool operator != (const ProtocolRequest &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ProtocolRequest & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ProtocolResponse__isset { + _ProtocolResponse__isset() : errcode(false), servicelist(false) {} + bool errcode; + bool servicelist; +} _ProtocolResponse__isset; + +class ProtocolResponse { + public: + + static const char* ascii_fingerprint; // = "F56E7FEC73C75A28B4691E35627DB92D"; + static const uint8_t binary_fingerprint[16]; // = {0xF5,0x6E,0x7F,0xEC,0x73,0xC7,0x5A,0x28,0xB4,0x69,0x1E,0x35,0x62,0x7D,0xB9,0x2D}; + + ProtocolResponse() : errcode(0) { + } + + virtual ~ProtocolResponse() throw() {} + + int32_t errcode; + std::vector servicelist; + + _ProtocolResponse__isset __isset; + + void __set_errcode(const int32_t val) { + errcode = val; + } + + void __set_servicelist(const std::vector & val) { + servicelist = val; + } + + bool operator == (const ProtocolResponse & rhs) const + { + if (!(errcode == rhs.errcode)) + return false; + if (!(servicelist == rhs.servicelist)) + return false; + return true; + } + bool operator != (const ProtocolResponse &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ProtocolResponse & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +} // namespace + +#endif diff --git a/sg_agent/thrid_party/thrid/include/octoidl/naming_data_constants.h b/sg_agent/thrid_party/thrid/include/octoidl/naming_data_constants.h new file mode 100644 index 0000000..7ef8442 --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/octoidl/naming_data_constants.h @@ -0,0 +1,24 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef naming_data_CONSTANTS_H +#define naming_data_CONSTANTS_H + +#include "naming_data_types.h" + +namespace meituan_mns { + +class naming_dataConstants { + public: + naming_dataConstants(); + +}; + +extern const naming_dataConstants g_naming_data_constants; + +} // namespace + +#endif diff --git a/sg_agent/thrid_party/thrid/include/octoidl/naming_data_types.h b/sg_agent/thrid_party/thrid/include/octoidl/naming_data_types.h new file mode 100644 index 0000000..9272deb --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/octoidl/naming_data_types.h @@ -0,0 +1,514 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef naming_data_TYPES_H +#define naming_data_TYPES_H + +#include +#include +#include +#include + +#include "naming_common_types.h" + + +namespace meituan_mns { + +struct RegistCmd { + enum type { + REGIST = 0, + UNREGIST = 1 + }; +}; + +extern const std::map _RegistCmd_VALUES_TO_NAMES; + +typedef class ::meituan_mns::SGService SGService; + +typedef class ::meituan_mns::CRouteData CRouteData; + +typedef struct _getservice_req_param_t__isset { + _getservice_req_param_t__isset() : localAppkey(false), remoteAppkey(false), version(false), protocol(false) {} + bool localAppkey; + bool remoteAppkey; + bool version; + bool protocol; +} _getservice_req_param_t__isset; + +class getservice_req_param_t { + public: + + static const char* ascii_fingerprint; // = "C93D890311F28844166CF6E571EB3AC2"; + static const uint8_t binary_fingerprint[16]; // = {0xC9,0x3D,0x89,0x03,0x11,0xF2,0x88,0x44,0x16,0x6C,0xF6,0xE5,0x71,0xEB,0x3A,0xC2}; + + getservice_req_param_t() : localAppkey(""), remoteAppkey(""), version(""), protocol("") { + } + + virtual ~getservice_req_param_t() throw() {} + + std::string localAppkey; + std::string remoteAppkey; + std::string version; + std::string protocol; + + _getservice_req_param_t__isset __isset; + + void __set_localAppkey(const std::string& val) { + localAppkey = val; + } + + void __set_remoteAppkey(const std::string& val) { + remoteAppkey = val; + } + + void __set_version(const std::string& val) { + version = val; + } + + void __set_protocol(const std::string& val) { + protocol = val; + } + + bool operator == (const getservice_req_param_t & rhs) const + { + if (!(localAppkey == rhs.localAppkey)) + return false; + if (!(remoteAppkey == rhs.remoteAppkey)) + return false; + if (!(version == rhs.version)) + return false; + if (!(protocol == rhs.protocol)) + return false; + return true; + } + bool operator != (const getservice_req_param_t &rhs) const { + return !(*this == rhs); + } + + bool operator < (const getservice_req_param_t & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _getservice_res_param_t__isset { + _getservice_res_param_t__isset() : localAppkey(false), remoteAppkey(false), version(false), serviceList(false), protocol(false) {} + bool localAppkey; + bool remoteAppkey; + bool version; + bool serviceList; + bool protocol; +} _getservice_res_param_t__isset; + +class getservice_res_param_t { + public: + + static const char* ascii_fingerprint; // = "BEE4DB4CE7FE0806BC8C2B45BA6E4742"; + static const uint8_t binary_fingerprint[16]; // = {0xBE,0xE4,0xDB,0x4C,0xE7,0xFE,0x08,0x06,0xBC,0x8C,0x2B,0x45,0xBA,0x6E,0x47,0x42}; + + getservice_res_param_t() : localAppkey(""), remoteAppkey(""), version(""), protocol("") { + } + + virtual ~getservice_res_param_t() throw() {} + + std::string localAppkey; + std::string remoteAppkey; + std::string version; + std::vector serviceList; + std::string protocol; + + _getservice_res_param_t__isset __isset; + + void __set_localAppkey(const std::string& val) { + localAppkey = val; + } + + void __set_remoteAppkey(const std::string& val) { + remoteAppkey = val; + } + + void __set_version(const std::string& val) { + version = val; + } + + void __set_serviceList(const std::vector & val) { + serviceList = val; + } + + void __set_protocol(const std::string& val) { + protocol = val; + } + + bool operator == (const getservice_res_param_t & rhs) const + { + if (!(localAppkey == rhs.localAppkey)) + return false; + if (!(remoteAppkey == rhs.remoteAppkey)) + return false; + if (!(version == rhs.version)) + return false; + if (!(serviceList == rhs.serviceList)) + return false; + if (!(protocol == rhs.protocol)) + return false; + return true; + } + bool operator != (const getservice_res_param_t &rhs) const { + return !(*this == rhs); + } + + bool operator < (const getservice_res_param_t & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _getservicename_req_param_t__isset { + _getservicename_req_param_t__isset() : localAppkey(false), servicename(false), version(false), protocol(false) {} + bool localAppkey; + bool servicename; + bool version; + bool protocol; +} _getservicename_req_param_t__isset; + +class getservicename_req_param_t { + public: + + static const char* ascii_fingerprint; // = "C93D890311F28844166CF6E571EB3AC2"; + static const uint8_t binary_fingerprint[16]; // = {0xC9,0x3D,0x89,0x03,0x11,0xF2,0x88,0x44,0x16,0x6C,0xF6,0xE5,0x71,0xEB,0x3A,0xC2}; + + getservicename_req_param_t() : localAppkey(""), servicename(""), version(""), protocol("") { + } + + virtual ~getservicename_req_param_t() throw() {} + + std::string localAppkey; + std::string servicename; + std::string version; + std::string protocol; + + _getservicename_req_param_t__isset __isset; + + void __set_localAppkey(const std::string& val) { + localAppkey = val; + } + + void __set_servicename(const std::string& val) { + servicename = val; + } + + void __set_version(const std::string& val) { + version = val; + } + + void __set_protocol(const std::string& val) { + protocol = val; + } + + bool operator == (const getservicename_req_param_t & rhs) const + { + if (!(localAppkey == rhs.localAppkey)) + return false; + if (!(servicename == rhs.servicename)) + return false; + if (!(version == rhs.version)) + return false; + if (!(protocol == rhs.protocol)) + return false; + return true; + } + bool operator != (const getservicename_req_param_t &rhs) const { + return !(*this == rhs); + } + + bool operator < (const getservicename_req_param_t & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _getservicename_res_param_t__isset { + _getservicename_res_param_t__isset() : localAppkey(false), servicename(false), version(false), appkeys(false), protocol(false) {} + bool localAppkey; + bool servicename; + bool version; + bool appkeys; + bool protocol; +} _getservicename_res_param_t__isset; + +class getservicename_res_param_t { + public: + + static const char* ascii_fingerprint; // = "029F9D059094419E5A20EF21917997A5"; + static const uint8_t binary_fingerprint[16]; // = {0x02,0x9F,0x9D,0x05,0x90,0x94,0x41,0x9E,0x5A,0x20,0xEF,0x21,0x91,0x79,0x97,0xA5}; + + getservicename_res_param_t() : localAppkey(""), servicename(""), version(""), protocol("") { + } + + virtual ~getservicename_res_param_t() throw() {} + + std::string localAppkey; + std::string servicename; + std::string version; + std::set appkeys; + std::string protocol; + + _getservicename_res_param_t__isset __isset; + + void __set_localAppkey(const std::string& val) { + localAppkey = val; + } + + void __set_servicename(const std::string& val) { + servicename = val; + } + + void __set_version(const std::string& val) { + version = val; + } + + void __set_appkeys(const std::set & val) { + appkeys = val; + } + + void __set_protocol(const std::string& val) { + protocol = val; + } + + bool operator == (const getservicename_res_param_t & rhs) const + { + if (!(localAppkey == rhs.localAppkey)) + return false; + if (!(servicename == rhs.servicename)) + return false; + if (!(version == rhs.version)) + return false; + if (!(appkeys == rhs.appkeys)) + return false; + if (!(protocol == rhs.protocol)) + return false; + return true; + } + bool operator != (const getservicename_res_param_t &rhs) const { + return !(*this == rhs); + } + + bool operator < (const getservicename_res_param_t & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _getroute_req_param_t__isset { + _getroute_req_param_t__isset() : localAppkey(false), remoteAppkey(false), version(false), protocol(false) {} + bool localAppkey; + bool remoteAppkey; + bool version; + bool protocol; +} _getroute_req_param_t__isset; + +class getroute_req_param_t { + public: + + static const char* ascii_fingerprint; // = "C93D890311F28844166CF6E571EB3AC2"; + static const uint8_t binary_fingerprint[16]; // = {0xC9,0x3D,0x89,0x03,0x11,0xF2,0x88,0x44,0x16,0x6C,0xF6,0xE5,0x71,0xEB,0x3A,0xC2}; + + getroute_req_param_t() : localAppkey(""), remoteAppkey(""), version(""), protocol("") { + } + + virtual ~getroute_req_param_t() throw() {} + + std::string localAppkey; + std::string remoteAppkey; + std::string version; + std::string protocol; + + _getroute_req_param_t__isset __isset; + + void __set_localAppkey(const std::string& val) { + localAppkey = val; + } + + void __set_remoteAppkey(const std::string& val) { + remoteAppkey = val; + } + + void __set_version(const std::string& val) { + version = val; + } + + void __set_protocol(const std::string& val) { + protocol = val; + } + + bool operator == (const getroute_req_param_t & rhs) const + { + if (!(localAppkey == rhs.localAppkey)) + return false; + if (!(remoteAppkey == rhs.remoteAppkey)) + return false; + if (!(version == rhs.version)) + return false; + if (!(protocol == rhs.protocol)) + return false; + return true; + } + bool operator != (const getroute_req_param_t &rhs) const { + return !(*this == rhs); + } + + bool operator < (const getroute_req_param_t & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _getroute_res_param_t__isset { + _getroute_res_param_t__isset() : localAppkey(false), remoteAppkey(false), version(false), routeList(false), protocol(false) {} + bool localAppkey; + bool remoteAppkey; + bool version; + bool routeList; + bool protocol; +} _getroute_res_param_t__isset; + +class getroute_res_param_t { + public: + + static const char* ascii_fingerprint; // = "61123EDDD00927E85F89381EEBDBC37F"; + static const uint8_t binary_fingerprint[16]; // = {0x61,0x12,0x3E,0xDD,0xD0,0x09,0x27,0xE8,0x5F,0x89,0x38,0x1E,0xEB,0xDB,0xC3,0x7F}; + + getroute_res_param_t() : localAppkey(""), remoteAppkey(""), version(""), protocol("") { + } + + virtual ~getroute_res_param_t() throw() {} + + std::string localAppkey; + std::string remoteAppkey; + std::string version; + std::vector routeList; + std::string protocol; + + _getroute_res_param_t__isset __isset; + + void __set_localAppkey(const std::string& val) { + localAppkey = val; + } + + void __set_remoteAppkey(const std::string& val) { + remoteAppkey = val; + } + + void __set_version(const std::string& val) { + version = val; + } + + void __set_routeList(const std::vector & val) { + routeList = val; + } + + void __set_protocol(const std::string& val) { + protocol = val; + } + + bool operator == (const getroute_res_param_t & rhs) const + { + if (!(localAppkey == rhs.localAppkey)) + return false; + if (!(remoteAppkey == rhs.remoteAppkey)) + return false; + if (!(version == rhs.version)) + return false; + if (!(routeList == rhs.routeList)) + return false; + if (!(protocol == rhs.protocol)) + return false; + return true; + } + bool operator != (const getroute_res_param_t &rhs) const { + return !(*this == rhs); + } + + bool operator < (const getroute_res_param_t & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _regist_req_param_t__isset { + _regist_req_param_t__isset() : retry_times(false), sgservice(false), uptCmd(false), regCmd(false) {} + bool retry_times; + bool sgservice; + bool uptCmd; + bool regCmd; +} _regist_req_param_t__isset; + +class regist_req_param_t { + public: + + static const char* ascii_fingerprint; // = "0E9168D7B65EE33C82EF267B678FCB69"; + static const uint8_t binary_fingerprint[16]; // = {0x0E,0x91,0x68,0xD7,0xB6,0x5E,0xE3,0x3C,0x82,0xEF,0x26,0x7B,0x67,0x8F,0xCB,0x69}; + + regist_req_param_t() : retry_times(0), uptCmd(0), regCmd((RegistCmd::type)0) { + } + + virtual ~regist_req_param_t() throw() {} + + int32_t retry_times; + SGService sgservice; + int32_t uptCmd; + RegistCmd::type regCmd; + + _regist_req_param_t__isset __isset; + + void __set_retry_times(const int32_t val) { + retry_times = val; + } + + void __set_sgservice(const SGService& val) { + sgservice = val; + } + + void __set_uptCmd(const int32_t val) { + uptCmd = val; + } + + void __set_regCmd(const RegistCmd::type val) { + regCmd = val; + } + + bool operator == (const regist_req_param_t & rhs) const + { + if (!(retry_times == rhs.retry_times)) + return false; + if (!(sgservice == rhs.sgservice)) + return false; + if (!(uptCmd == rhs.uptCmd)) + return false; + if (!(regCmd == rhs.regCmd)) + return false; + return true; + } + bool operator != (const regist_req_param_t &rhs) const { + return !(*this == rhs); + } + + bool operator < (const regist_req_param_t & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +} // namespace + +#endif diff --git a/sg_agent/thrid_party/thrid/include/octoidl/naming_service_constants.h b/sg_agent/thrid_party/thrid/include/octoidl/naming_service_constants.h new file mode 100644 index 0000000..54a6a0c --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/octoidl/naming_service_constants.h @@ -0,0 +1,24 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef naming_service_CONSTANTS_H +#define naming_service_CONSTANTS_H + +#include "naming_service_types.h" + +namespace meituan_mns { + +class naming_serviceConstants { + public: + naming_serviceConstants(); + +}; + +extern const naming_serviceConstants g_naming_service_constants; + +} // namespace + +#endif diff --git a/sg_agent/thrid_party/thrid/include/octoidl/naming_service_types.h b/sg_agent/thrid_party/thrid/include/octoidl/naming_service_types.h new file mode 100644 index 0000000..62b923e --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/octoidl/naming_service_types.h @@ -0,0 +1,28 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef naming_service_TYPES_H +#define naming_service_TYPES_H + +#include +#include +#include +#include + +#include "naming_common_types.h" + + +namespace meituan_mns { + +typedef class ::meituan_mns::SGService SGService; + +typedef class ::meituan_mns::ProtocolRequest ProtocolRequest; + +typedef class ::meituan_mns::ProtocolResponse ProtocolResponse; + +} // namespace + +#endif diff --git a/sg_agent/thrid_party/thrid/include/octoidl/unified_protocol_constants.h b/sg_agent/thrid_party/thrid/include/octoidl/unified_protocol_constants.h new file mode 100644 index 0000000..760de8a --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/octoidl/unified_protocol_constants.h @@ -0,0 +1,24 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef unified_protocol_CONSTANTS_H +#define unified_protocol_CONSTANTS_H + +#include "unified_protocol_types.h" + +namespace meituan_mns { + +class unified_protocolConstants { + public: + unified_protocolConstants(); + +}; + +extern const unified_protocolConstants g_unified_protocol_constants; + +} // namespace + +#endif diff --git a/sg_agent/thrid_party/thrid/include/octoidl/unified_protocol_types.h b/sg_agent/thrid_party/thrid/include/octoidl/unified_protocol_types.h new file mode 100644 index 0000000..df6a0cf --- /dev/null +++ b/sg_agent/thrid_party/thrid/include/octoidl/unified_protocol_types.h @@ -0,0 +1,582 @@ +/** + * Autogenerated by Thrift Compiler (0.8.0) + * + * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING + * @generated + */ +#ifndef unified_protocol_TYPES_H +#define unified_protocol_TYPES_H + +#include +#include +#include +#include + + + +namespace meituan_mns { + +struct MessageType { + enum type { + Normal = 0, + NormalHeartbeat = 1, + ScannerHeartbeat = 2 + }; +}; + +extern const std::map _MessageType_VALUES_TO_NAMES; + +struct CompressType { + enum type { + None = 0, + Snappy = 1, + Gzip = 2 + }; +}; + +extern const std::map _CompressType_VALUES_TO_NAMES; + +struct CallType { + enum type { + Reply = 0, + NoReply = 1 + }; +}; + +extern const std::map _CallType_VALUES_TO_NAMES; + +struct StatusCodes { + enum type { + Success = 0, + ApplicationException = 1, + RuntimeException = 2, + RpcException = 3, + TransportException = 4, + ProtocolException = 5, + DegradeException = 6, + SecurityException = 7, + ServiceException = 8, + RemoteException = 9 + }; +}; + +extern const std::map _StatusCodes_VALUES_TO_NAMES; + +typedef std::map Context; + + +class RequestInfo { + public: + + static const char* ascii_fingerprint; // = "59AD75927B39FBAC91B35C663FDB29CD"; + static const uint8_t binary_fingerprint[16]; // = {0x59,0xAD,0x75,0x92,0x7B,0x39,0xFB,0xAC,0x91,0xB3,0x5C,0x66,0x3F,0xDB,0x29,0xCD}; + + RequestInfo() : serviceName(""), sequenceId(0), callType(0), timeout(0) { + } + + virtual ~RequestInfo() throw() {} + + std::string serviceName; + int64_t sequenceId; + int8_t callType; + int32_t timeout; + + void __set_serviceName(const std::string& val) { + serviceName = val; + } + + void __set_sequenceId(const int64_t val) { + sequenceId = val; + } + + void __set_callType(const int8_t val) { + callType = val; + } + + void __set_timeout(const int32_t val) { + timeout = val; + } + + bool operator == (const RequestInfo & rhs) const + { + if (!(serviceName == rhs.serviceName)) + return false; + if (!(sequenceId == rhs.sequenceId)) + return false; + if (!(callType == rhs.callType)) + return false; + if (!(timeout == rhs.timeout)) + return false; + return true; + } + bool operator != (const RequestInfo &rhs) const { + return !(*this == rhs); + } + + bool operator < (const RequestInfo & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _ResponseInfo__isset { + _ResponseInfo__isset() : message(false) {} + bool message; +} _ResponseInfo__isset; + +class ResponseInfo { + public: + + static const char* ascii_fingerprint; // = "C6D3CA4A6A1EB8E865A6A00B60176AA8"; + static const uint8_t binary_fingerprint[16]; // = {0xC6,0xD3,0xCA,0x4A,0x6A,0x1E,0xB8,0xE8,0x65,0xA6,0xA0,0x0B,0x60,0x17,0x6A,0xA8}; + + ResponseInfo() : sequenceId(0), status(0), message("") { + } + + virtual ~ResponseInfo() throw() {} + + int64_t sequenceId; + int8_t status; + std::string message; + + _ResponseInfo__isset __isset; + + void __set_sequenceId(const int64_t val) { + sequenceId = val; + } + + void __set_status(const int8_t val) { + status = val; + } + + void __set_message(const std::string& val) { + message = val; + __isset.message = true; + } + + bool operator == (const ResponseInfo & rhs) const + { + if (!(sequenceId == rhs.sequenceId)) + return false; + if (!(status == rhs.status)) + return false; + if (__isset.message != rhs.__isset.message) + return false; + else if (__isset.message && !(message == rhs.message)) + return false; + return true; + } + bool operator != (const ResponseInfo &rhs) const { + return !(*this == rhs); + } + + bool operator < (const ResponseInfo & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _TraceInfo__isset { + _TraceInfo__isset() : traceId(false), spanId(false), rootMessageId(false), currentMessageId(false), serverMessageId(false), debug(false), sample(false), clientIp(false) {} + bool traceId; + bool spanId; + bool rootMessageId; + bool currentMessageId; + bool serverMessageId; + bool debug; + bool sample; + bool clientIp; +} _TraceInfo__isset; + +class TraceInfo { + public: + + static const char* ascii_fingerprint; // = "ABB2B5AA298E9052ED1A5DE871EF9527"; + static const uint8_t binary_fingerprint[16]; // = {0xAB,0xB2,0xB5,0xAA,0x29,0x8E,0x90,0x52,0xED,0x1A,0x5D,0xE8,0x71,0xEF,0x95,0x27}; + + TraceInfo() : clientAppkey(""), traceId(""), spanId(""), rootMessageId(""), currentMessageId(""), serverMessageId(""), debug(0), sample(0), clientIp("") { + } + + virtual ~TraceInfo() throw() {} + + std::string clientAppkey; + std::string traceId; + std::string spanId; + std::string rootMessageId; + std::string currentMessageId; + std::string serverMessageId; + bool debug; + bool sample; + std::string clientIp; + + _TraceInfo__isset __isset; + + void __set_clientAppkey(const std::string& val) { + clientAppkey = val; + } + + void __set_traceId(const std::string& val) { + traceId = val; + __isset.traceId = true; + } + + void __set_spanId(const std::string& val) { + spanId = val; + __isset.spanId = true; + } + + void __set_rootMessageId(const std::string& val) { + rootMessageId = val; + __isset.rootMessageId = true; + } + + void __set_currentMessageId(const std::string& val) { + currentMessageId = val; + __isset.currentMessageId = true; + } + + void __set_serverMessageId(const std::string& val) { + serverMessageId = val; + __isset.serverMessageId = true; + } + + void __set_debug(const bool val) { + debug = val; + __isset.debug = true; + } + + void __set_sample(const bool val) { + sample = val; + __isset.sample = true; + } + + void __set_clientIp(const std::string& val) { + clientIp = val; + __isset.clientIp = true; + } + + bool operator == (const TraceInfo & rhs) const + { + if (!(clientAppkey == rhs.clientAppkey)) + return false; + if (__isset.traceId != rhs.__isset.traceId) + return false; + else if (__isset.traceId && !(traceId == rhs.traceId)) + return false; + if (__isset.spanId != rhs.__isset.spanId) + return false; + else if (__isset.spanId && !(spanId == rhs.spanId)) + return false; + if (__isset.rootMessageId != rhs.__isset.rootMessageId) + return false; + else if (__isset.rootMessageId && !(rootMessageId == rhs.rootMessageId)) + return false; + if (__isset.currentMessageId != rhs.__isset.currentMessageId) + return false; + else if (__isset.currentMessageId && !(currentMessageId == rhs.currentMessageId)) + return false; + if (__isset.serverMessageId != rhs.__isset.serverMessageId) + return false; + else if (__isset.serverMessageId && !(serverMessageId == rhs.serverMessageId)) + return false; + if (__isset.debug != rhs.__isset.debug) + return false; + else if (__isset.debug && !(debug == rhs.debug)) + return false; + if (__isset.sample != rhs.__isset.sample) + return false; + else if (__isset.sample && !(sample == rhs.sample)) + return false; + if (__isset.clientIp != rhs.__isset.clientIp) + return false; + else if (__isset.clientIp && !(clientIp == rhs.clientIp)) + return false; + return true; + } + bool operator != (const TraceInfo &rhs) const { + return !(*this == rhs); + } + + bool operator < (const TraceInfo & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _LoadInfo__isset { + _LoadInfo__isset() : averageLoad(false), oldGC(false), threadNum(false), queueSize(false), methodQpsMap(false) {} + bool averageLoad; + bool oldGC; + bool threadNum; + bool queueSize; + bool methodQpsMap; +} _LoadInfo__isset; + +class LoadInfo { + public: + + static const char* ascii_fingerprint; // = "F424555CA1CEF935A4729C49DC664047"; + static const uint8_t binary_fingerprint[16]; // = {0xF4,0x24,0x55,0x5C,0xA1,0xCE,0xF9,0x35,0xA4,0x72,0x9C,0x49,0xDC,0x66,0x40,0x47}; + + LoadInfo() : averageLoad(0), oldGC(0), threadNum(0), queueSize(0) { + } + + virtual ~LoadInfo() throw() {} + + double averageLoad; + int32_t oldGC; + int32_t threadNum; + int32_t queueSize; + std::map methodQpsMap; + + _LoadInfo__isset __isset; + + void __set_averageLoad(const double val) { + averageLoad = val; + __isset.averageLoad = true; + } + + void __set_oldGC(const int32_t val) { + oldGC = val; + __isset.oldGC = true; + } + + void __set_threadNum(const int32_t val) { + threadNum = val; + __isset.threadNum = true; + } + + void __set_queueSize(const int32_t val) { + queueSize = val; + __isset.queueSize = true; + } + + void __set_methodQpsMap(const std::map & val) { + methodQpsMap = val; + __isset.methodQpsMap = true; + } + + bool operator == (const LoadInfo & rhs) const + { + if (__isset.averageLoad != rhs.__isset.averageLoad) + return false; + else if (__isset.averageLoad && !(averageLoad == rhs.averageLoad)) + return false; + if (__isset.oldGC != rhs.__isset.oldGC) + return false; + else if (__isset.oldGC && !(oldGC == rhs.oldGC)) + return false; + if (__isset.threadNum != rhs.__isset.threadNum) + return false; + else if (__isset.threadNum && !(threadNum == rhs.threadNum)) + return false; + if (__isset.queueSize != rhs.__isset.queueSize) + return false; + else if (__isset.queueSize && !(queueSize == rhs.queueSize)) + return false; + if (__isset.methodQpsMap != rhs.__isset.methodQpsMap) + return false; + else if (__isset.methodQpsMap && !(methodQpsMap == rhs.methodQpsMap)) + return false; + return true; + } + bool operator != (const LoadInfo &rhs) const { + return !(*this == rhs); + } + + bool operator < (const LoadInfo & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _HeartbeatInfo__isset { + _HeartbeatInfo__isset() : appkey(false), sendTime(false), loadInfo(false) {} + bool appkey; + bool sendTime; + bool loadInfo; +} _HeartbeatInfo__isset; + +class HeartbeatInfo { + public: + + static const char* ascii_fingerprint; // = "EF43E82D9230E1225E24787F74163831"; + static const uint8_t binary_fingerprint[16]; // = {0xEF,0x43,0xE8,0x2D,0x92,0x30,0xE1,0x22,0x5E,0x24,0x78,0x7F,0x74,0x16,0x38,0x31}; + + HeartbeatInfo() : appkey(""), sendTime(0), status(0) { + } + + virtual ~HeartbeatInfo() throw() {} + + std::string appkey; + int64_t sendTime; + LoadInfo loadInfo; + int32_t status; + + _HeartbeatInfo__isset __isset; + + void __set_appkey(const std::string& val) { + appkey = val; + __isset.appkey = true; + } + + void __set_sendTime(const int64_t val) { + sendTime = val; + __isset.sendTime = true; + } + + void __set_loadInfo(const LoadInfo& val) { + loadInfo = val; + __isset.loadInfo = true; + } + + void __set_status(const int32_t val) { + status = val; + } + + bool operator == (const HeartbeatInfo & rhs) const + { + if (__isset.appkey != rhs.__isset.appkey) + return false; + else if (__isset.appkey && !(appkey == rhs.appkey)) + return false; + if (__isset.sendTime != rhs.__isset.sendTime) + return false; + else if (__isset.sendTime && !(sendTime == rhs.sendTime)) + return false; + if (__isset.loadInfo != rhs.__isset.loadInfo) + return false; + else if (__isset.loadInfo && !(loadInfo == rhs.loadInfo)) + return false; + if (!(status == rhs.status)) + return false; + return true; + } + bool operator != (const HeartbeatInfo &rhs) const { + return !(*this == rhs); + } + + bool operator < (const HeartbeatInfo & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +typedef struct _Header__isset { + _Header__isset() : messageType(false), requestInfo(false), responseInfo(false), traceInfo(false), globalContext(false), localContext(false), heartbeatInfo(false) {} + bool messageType; + bool requestInfo; + bool responseInfo; + bool traceInfo; + bool globalContext; + bool localContext; + bool heartbeatInfo; +} _Header__isset; + +class Header { + public: + + static const char* ascii_fingerprint; // = "449EC0AD8F982561B4D899B14FB0084B"; + static const uint8_t binary_fingerprint[16]; // = {0x44,0x9E,0xC0,0xAD,0x8F,0x98,0x25,0x61,0xB4,0xD8,0x99,0xB1,0x4F,0xB0,0x08,0x4B}; + + Header() : messageType(0) { + } + + virtual ~Header() throw() {} + + int8_t messageType; + RequestInfo requestInfo; + ResponseInfo responseInfo; + TraceInfo traceInfo; + Context globalContext; + Context localContext; + HeartbeatInfo heartbeatInfo; + + _Header__isset __isset; + + void __set_messageType(const int8_t val) { + messageType = val; + __isset.messageType = true; + } + + void __set_requestInfo(const RequestInfo& val) { + requestInfo = val; + __isset.requestInfo = true; + } + + void __set_responseInfo(const ResponseInfo& val) { + responseInfo = val; + __isset.responseInfo = true; + } + + void __set_traceInfo(const TraceInfo& val) { + traceInfo = val; + __isset.traceInfo = true; + } + + void __set_globalContext(const Context& val) { + globalContext = val; + __isset.globalContext = true; + } + + void __set_localContext(const Context& val) { + localContext = val; + __isset.localContext = true; + } + + void __set_heartbeatInfo(const HeartbeatInfo& val) { + heartbeatInfo = val; + __isset.heartbeatInfo = true; + } + + bool operator == (const Header & rhs) const + { + if (__isset.messageType != rhs.__isset.messageType) + return false; + else if (__isset.messageType && !(messageType == rhs.messageType)) + return false; + if (__isset.requestInfo != rhs.__isset.requestInfo) + return false; + else if (__isset.requestInfo && !(requestInfo == rhs.requestInfo)) + return false; + if (__isset.responseInfo != rhs.__isset.responseInfo) + return false; + else if (__isset.responseInfo && !(responseInfo == rhs.responseInfo)) + return false; + if (__isset.traceInfo != rhs.__isset.traceInfo) + return false; + else if (__isset.traceInfo && !(traceInfo == rhs.traceInfo)) + return false; + if (__isset.globalContext != rhs.__isset.globalContext) + return false; + else if (__isset.globalContext && !(globalContext == rhs.globalContext)) + return false; + if (__isset.localContext != rhs.__isset.localContext) + return false; + else if (__isset.localContext && !(localContext == rhs.localContext)) + return false; + if (__isset.heartbeatInfo != rhs.__isset.heartbeatInfo) + return false; + else if (__isset.heartbeatInfo && !(heartbeatInfo == rhs.heartbeatInfo)) + return false; + return true; + } + bool operator != (const Header &rhs) const { + return !(*this == rhs); + } + + bool operator < (const Header & ) const; + + uint32_t read(::apache::thrift::protocol::TProtocol* iprot); + uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; + +}; + +} // namespace + +#endif diff --git a/sg_agent/thrid_party/thrid/lib/libmns_sdk.a b/sg_agent/thrid_party/thrid/lib/libmns_sdk.a new file mode 100644 index 0000000..36174f8 Binary files /dev/null and b/sg_agent/thrid_party/thrid/lib/libmns_sdk.a differ diff --git a/sg_agent/thrid_party/thrid/lib/libmns_sdk.so b/sg_agent/thrid_party/thrid/lib/libmns_sdk.so new file mode 100755 index 0000000..0cd23e9 Binary files /dev/null and b/sg_agent/thrid_party/thrid/lib/libmns_sdk.so differ diff --git a/sg_agent/thrid_party/thrid/lib/liboctoidl.a b/sg_agent/thrid_party/thrid/lib/liboctoidl.a new file mode 100644 index 0000000..064a391 Binary files /dev/null and b/sg_agent/thrid_party/thrid/lib/liboctoidl.a differ diff --git a/sg_agent/thrid_party/thrid/lib/liboctoidl.so b/sg_agent/thrid_party/thrid/lib/liboctoidl.so new file mode 100755 index 0000000..ed94972 Binary files /dev/null and b/sg_agent/thrid_party/thrid/lib/liboctoidl.so differ diff --git a/sg_agent/thrid_party/thrift/include/TApplicationException.cpp b/sg_agent/thrid_party/thrift/include/TApplicationException.cpp new file mode 100644 index 0000000..32238fb --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/TApplicationException.cpp @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include + +namespace apache { namespace thrift { + +uint32_t TApplicationException::read(apache::thrift::protocol::TProtocol* iprot) { + uint32_t xfer = 0; + std::string fname; + apache::thrift::protocol::TType ftype; + int16_t fid; + + xfer += iprot->readStructBegin(fname); + + while (true) { + xfer += iprot->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + switch (fid) { + case 1: + if (ftype == apache::thrift::protocol::T_STRING) { + xfer += iprot->readString(message_); + } else { + xfer += iprot->skip(ftype); + } + break; + case 2: + if (ftype == apache::thrift::protocol::T_I32) { + int32_t type; + xfer += iprot->readI32(type); + type_ = (TApplicationExceptionType)type; + } else { + xfer += iprot->skip(ftype); + } + break; + default: + xfer += iprot->skip(ftype); + break; + } + xfer += iprot->readFieldEnd(); + } + + xfer += iprot->readStructEnd(); + return xfer; +} + +uint32_t TApplicationException::write(apache::thrift::protocol::TProtocol* oprot) const { + uint32_t xfer = 0; + xfer += oprot->writeStructBegin("TApplicationException"); + xfer += oprot->writeFieldBegin("message", apache::thrift::protocol::T_STRING, 1); + xfer += oprot->writeString(message_); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldBegin("type", apache::thrift::protocol::T_I32, 2); + xfer += oprot->writeI32(type_); + xfer += oprot->writeFieldEnd(); + xfer += oprot->writeFieldStop(); + xfer += oprot->writeStructEnd(); + return xfer; +} + +}} // apache::thrift diff --git a/sg_agent/thrid_party/thrift/include/TApplicationException.h b/sg_agent/thrid_party/thrift/include/TApplicationException.h new file mode 100644 index 0000000..61e6864 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/TApplicationException.h @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TAPPLICATIONEXCEPTION_H_ +#define _THRIFT_TAPPLICATIONEXCEPTION_H_ 1 + +#include + + +namespace apache { namespace thrift { + +namespace protocol { + class TProtocol; +} + +class TApplicationException : public TException { + public: + + /** + * Error codes for the various types of exceptions. + */ + enum TApplicationExceptionType { + UNKNOWN = 0, + UNKNOWN_METHOD = 1, + INVALID_MESSAGE_TYPE = 2, + WRONG_METHOD_NAME = 3, + BAD_SEQUENCE_ID = 4, + MISSING_RESULT = 5, + INTERNAL_ERROR = 6, + PROTOCOL_ERROR = 7 + }; + + TApplicationException() : + TException(), + type_(UNKNOWN) {} + + TApplicationException(TApplicationExceptionType type) : + TException(), + type_(type) {} + + TApplicationException(const std::string& message) : + TException(message), + type_(UNKNOWN) {} + + TApplicationException(TApplicationExceptionType type, + const std::string& message) : + TException(message), + type_(type) {} + + virtual ~TApplicationException() throw() {} + + /** + * Returns an error code that provides information about the type of error + * that has occurred. + * + * @return Error code + */ + TApplicationExceptionType getType() { + return type_; + } + + virtual const char* what() const throw() { + if (message_.empty()) { + switch (type_) { + case UNKNOWN : return "TApplicationException: Unknown application exception"; + case UNKNOWN_METHOD : return "TApplicationException: Unknown method"; + case INVALID_MESSAGE_TYPE : return "TApplicationException: Invalid message type"; + case WRONG_METHOD_NAME : return "TApplicationException: Wrong method name"; + case BAD_SEQUENCE_ID : return "TApplicationException: Bad sequence identifier"; + case MISSING_RESULT : return "TApplicationException: Missing result"; + default : return "TApplicationException: (Invalid exception type)"; + }; + } else { + return message_.c_str(); + } + } + + uint32_t read(protocol::TProtocol* iprot); + uint32_t write(protocol::TProtocol* oprot) const; + + protected: + /** + * Error code + */ + TApplicationExceptionType type_; + +}; + +}} // apache::thrift + +#endif // #ifndef _THRIFT_TAPPLICATIONEXCEPTION_H_ diff --git a/sg_agent/thrid_party/thrift/include/TLogging.h b/sg_agent/thrid_party/thrift/include/TLogging.h new file mode 100644 index 0000000..934e8fc --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/TLogging.h @@ -0,0 +1,199 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TLOGGING_H_ +#define _THRIFT_TLOGGING_H_ 1 + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/** + * Contains utility macros for debugging and logging. + * + */ + +#ifndef HAVE_CLOCK_GETTIME +#include +#else +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +/** + * T_GLOBAL_DEBUGGING_LEVEL = 0: all debugging turned off, debug macros undefined + * T_GLOBAL_DEBUGGING_LEVEL = 1: all debugging turned on + */ +#define T_GLOBAL_DEBUGGING_LEVEL 0 + + +/** + * T_GLOBAL_LOGGING_LEVEL = 0: all logging turned off, logging macros undefined + * T_GLOBAL_LOGGING_LEVEL = 1: all logging turned on + */ +#define T_GLOBAL_LOGGING_LEVEL 1 + + +/** + * Standard wrapper around fprintf what will prefix the file name and line + * number to the line. Uses T_GLOBAL_DEBUGGING_LEVEL to control whether it is + * turned on or off. + * + * @param format_string + */ +#if T_GLOBAL_DEBUGGING_LEVEL > 0 + #define T_DEBUG(format_string,...) \ + if (T_GLOBAL_DEBUGGING_LEVEL > 0) { \ + fprintf(stderr,"[%s,%d] " format_string " \n", __FILE__, __LINE__,##__VA_ARGS__); \ + } +#else + #define T_DEBUG(format_string,...) +#endif + + +/** + * analagous to T_DEBUG but also prints the time + * + * @param string format_string input: printf style format string + */ +#if T_GLOBAL_DEBUGGING_LEVEL > 0 + #define T_DEBUG_T(format_string,...) \ + { \ + if (T_GLOBAL_DEBUGGING_LEVEL > 0) { \ + time_t now; \ + char dbgtime[26] ; \ + time(&now); \ + ctime_r(&now, dbgtime); \ + dbgtime[24] = '\0'; \ + fprintf(stderr,"[%s,%d] [%s] " format_string " \n", __FILE__, __LINE__,dbgtime,##__VA_ARGS__); \ + } \ + } +#else + #define T_DEBUG_T(format_string,...) +#endif + + +/** + * analagous to T_DEBUG but uses input level to determine whether or not the string + * should be logged. + * + * @param int level: specified debug level + * @param string format_string input: format string + */ +#define T_DEBUG_L(level, format_string,...) \ + if ((level) > 0) { \ + fprintf(stderr,"[%s,%d] " format_string " \n", __FILE__, __LINE__,##__VA_ARGS__); \ + } + + +/** + * Explicit error logging. Prints time, file name and line number + * + * @param string format_string input: printf style format string + */ +#define T_ERROR(format_string,...) \ + { \ + time_t now; \ + char dbgtime[26] ; \ + time(&now); \ + ctime_r(&now, dbgtime); \ + dbgtime[24] = '\0'; \ + fprintf(stderr,"[%s,%d] [%s] ERROR: " format_string " \n", __FILE__, __LINE__,dbgtime,##__VA_ARGS__); \ + } + + +/** + * Analagous to T_ERROR, additionally aborting the process. + * WARNING: macro calls abort(), ending program execution + * + * @param string format_string input: printf style format string + */ +#define T_ERROR_ABORT(format_string,...) \ + { \ + time_t now; \ + char dbgtime[26] ; \ + time(&now); \ + ctime_r(&now, dbgtime); \ + dbgtime[24] = '\0'; \ + fprintf(stderr,"[%s,%d] [%s] ERROR: Going to abort " format_string " \n", __FILE__, __LINE__,dbgtime,##__VA_ARGS__); \ + exit(1); \ + } + + +/** + * Log input message + * + * @param string format_string input: printf style format string + */ +#if T_GLOBAL_LOGGING_LEVEL > 0 + #define T_LOG_OPER(format_string,...) \ + { \ + if (T_GLOBAL_LOGGING_LEVEL > 0) { \ + time_t now; \ + char dbgtime[26] ; \ + time(&now); \ + ctime_r(&now, dbgtime); \ + dbgtime[24] = '\0'; \ + fprintf(stderr,"[%s] " format_string " \n", dbgtime,##__VA_ARGS__); \ + } \ + } +#else + #define T_LOG_OPER(format_string,...) +#endif + + +/** + * T_GLOBAL_DEBUG_VIRTUAL = 0 or unset: normal operation, + * virtual call debug messages disabled + * T_GLOBAL_DEBUG_VIRTUAL = 1: log a debug messages whenever an + * avoidable virtual call is made + * T_GLOBAL_DEBUG_VIRTUAL = 2: record detailed info that can be + * printed by calling + * apache::thrift::profile_print_info() + */ +#if T_GLOBAL_DEBUG_VIRTUAL > 1 + #define T_VIRTUAL_CALL() \ + ::apache::thrift::profile_virtual_call(typeid(*this)) + #define T_GENERIC_PROTOCOL(template_class, generic_prot, specific_prot) \ + do { \ + if (!(specific_prot)) { \ + ::apache::thrift::profile_generic_protocol( \ + typeid(*template_class), typeid(*generic_prot)); \ + } \ + } while (0) +#elif T_GLOBAL_DEBUG_VIRTUAL == 1 + #define T_VIRTUAL_CALL() \ + fprintf(stderr,"[%s,%d] virtual call\n", __FILE__, __LINE__) + #define T_GENERIC_PROTOCOL(template_class, generic_prot, specific_prot) \ + do { \ + if (!(specific_prot)) { \ + fprintf(stderr, \ + "[%s,%d] failed to cast to specific protocol type\n", \ + __FILE__, __LINE__); \ + } \ + } while (0) +#else + #define T_VIRTUAL_CALL() + #define T_GENERIC_PROTOCOL(template_class, generic_prot, specific_prot) +#endif + +#endif // #ifndef _THRIFT_TLOGGING_H_ diff --git a/sg_agent/thrid_party/thrift/include/TProcessor.h b/sg_agent/thrid_party/thrift/include/TProcessor.h new file mode 100644 index 0000000..26c3ee4 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/TProcessor.h @@ -0,0 +1,233 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TPROCESSOR_H_ +#define _THRIFT_TPROCESSOR_H_ 1 + +#include +#include +#include + +namespace apache { namespace thrift { + +/** + * Virtual interface class that can handle events from the processor. To + * use this you should subclass it and implement the methods that you care + * about. Your subclass can also store local data that you may care about, + * such as additional "arguments" to these methods (stored in the object + * instance's state). + */ +class TProcessorEventHandler { + public: + + virtual ~TProcessorEventHandler() {} + + /** + * Called before calling other callback methods. + * Expected to return some sort of context object. + * The return value is passed to all other callbacks + * for that function invocation. + */ + virtual void* getContext(const char* fn_name, void* serverContext) { + (void) fn_name; + (void) serverContext; + return NULL; + } + + /** + * Expected to free resources associated with a context. + */ + virtual void freeContext(void* ctx, const char* fn_name) { + (void) ctx; + (void) fn_name; + } + + /** + * Called before reading arguments. + */ + virtual void preRead(void* ctx, const char* fn_name) { + (void) ctx; + (void) fn_name; + } + + /** + * Called between reading arguments and calling the handler. + */ + virtual void postRead(void* ctx, const char* fn_name, uint32_t bytes) { + (void) ctx; + (void) fn_name; + (void) bytes; + } + + /** + * Called between calling the handler and writing the response. + */ + virtual void preWrite(void* ctx, const char* fn_name) { + (void) ctx; + (void) fn_name; + } + + /** + * Called after writing the response. + */ + virtual void postWrite(void* ctx, const char* fn_name, uint32_t bytes) { + (void) ctx; + (void) fn_name; + (void) bytes; + } + + /** + * Called when an async function call completes successfully. + */ + virtual void asyncComplete(void* ctx, const char* fn_name) { + (void) ctx; + (void) fn_name; + } + + /** + * Called if the handler throws an undeclared exception. + */ + virtual void handlerError(void* ctx, const char* fn_name) { + (void) ctx; + (void) fn_name; + } + + protected: + TProcessorEventHandler() {} +}; + +/** + * A helper class used by the generated code to free each context. + */ +class TProcessorContextFreer { + public: + TProcessorContextFreer(TProcessorEventHandler* handler, void* context, const char* method) : + handler_(handler), context_(context), method_(method) {} + ~TProcessorContextFreer() { if (handler_ != NULL) handler_->freeContext(context_, method_); } + void unregister() { handler_ = NULL; } + private: + apache::thrift::TProcessorEventHandler* handler_; + void* context_; + const char* method_; +}; + +/** + * A processor is a generic object that acts upon two streams of data, one + * an input and the other an output. The definition of this object is loose, + * though the typical case is for some sort of server that either generates + * responses to an input stream or forwards data from one pipe onto another. + * + */ +class TProcessor { + public: + virtual ~TProcessor() {} + + virtual bool process(boost::shared_ptr in, + boost::shared_ptr out, + void* connectionContext) = 0; + + bool process(boost::shared_ptr io, + void* connectionContext) { + return process(io, io, connectionContext); + } + + boost::shared_ptr getEventHandler() { + return eventHandler_; + } + + void setEventHandler(boost::shared_ptr eventHandler) { + eventHandler_ = eventHandler; + } + + protected: + TProcessor() {} + + boost::shared_ptr eventHandler_; +}; + +/** + * This is a helper class to allow boost::shared_ptr to be used with handler + * pointers returned by the generated handler factories. + * + * The handler factory classes generated by the thrift compiler return raw + * pointers, and factory->releaseHandler() must be called when the handler is + * no longer needed. + * + * A ReleaseHandler object can be instantiated and passed as the second + * parameter to a shared_ptr, so that factory->releaseHandler() will be called + * when the object is no longer needed, instead of deleting the pointer. + */ +template +class ReleaseHandler { + public: + ReleaseHandler(const boost::shared_ptr& handlerFactory) : + handlerFactory_(handlerFactory) {} + + void operator()(typename HandlerFactory_::Handler* handler) { + if (handler) { + handlerFactory_->releaseHandler(handler); + } + } + + private: + boost::shared_ptr handlerFactory_; +}; + +struct TConnectionInfo { + // The input and output protocols + boost::shared_ptr input; + boost::shared_ptr output; + // The underlying transport used for the connection + // This is the transport that was returned by TServerTransport::accept(), + // and it may be different than the transport pointed to by the input and + // output protocols. + boost::shared_ptr transport; +}; + +class TProcessorFactory { + public: + virtual ~TProcessorFactory() {} + + /** + * Get the TProcessor to use for a particular connection. + * + * This method is always invoked in the same thread that the connection was + * accepted on. This generally means that this call does not need to be + * thread safe, as it will always be invoked from a single thread. + */ + virtual boost::shared_ptr getProcessor( + const TConnectionInfo& connInfo) = 0; +}; + +class TSingletonProcessorFactory : public TProcessorFactory { + public: + TSingletonProcessorFactory(boost::shared_ptr processor) : + processor_(processor) {} + + boost::shared_ptr getProcessor(const TConnectionInfo&) { + return processor_; + } + + private: + boost::shared_ptr processor_; +}; + +}} // apache::thrift + +#endif // #ifndef _THRIFT_TPROCESSOR_H_ diff --git a/sg_agent/thrid_party/thrift/include/TReflectionLocal.h b/sg_agent/thrid_party/thrift/include/TReflectionLocal.h new file mode 100644 index 0000000..e83e475 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/TReflectionLocal.h @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TREFLECTIONLOCAL_H_ +#define _THRIFT_TREFLECTIONLOCAL_H_ 1 + +#include +#include +#include + +/** + * Local Reflection is a blanket term referring to the the structure + * and generation of this particular representation of Thrift types. + * (It is called local because it cannot be serialized by Thrift). + * + */ + +namespace apache { namespace thrift { namespace reflection { namespace local { + +using apache::thrift::protocol::TType; + +// We include this many bytes of the structure's fingerprint when serializing +// a top-level structure. Long enough to make collisions unlikely, short +// enough to not significantly affect the amount of memory used. +const int FP_PREFIX_LEN = 4; + +struct FieldMeta { + int16_t tag; + bool is_optional; +}; + +struct TypeSpec { + TType ttype; + uint8_t fp_prefix[FP_PREFIX_LEN]; + + // Use an anonymous union here so we can fit two TypeSpecs in one cache line. + union { + struct { + // Use parallel arrays here for denser packing (of the arrays). + FieldMeta* metas; + TypeSpec** specs; + } tstruct; + struct { + TypeSpec *subtype1; + TypeSpec *subtype2; + } tcontainer; + }; + + // Static initialization of unions isn't really possible, + // so take the plunge and use constructors. + // Hopefully they'll be evaluated at compile time. + + TypeSpec(TType ttype) : ttype(ttype) { + std::memset(fp_prefix, 0, FP_PREFIX_LEN); + } + + TypeSpec(TType ttype, + const uint8_t* fingerprint, + FieldMeta* metas, + TypeSpec** specs) : + ttype(ttype) + { + std::memcpy(fp_prefix, fingerprint, FP_PREFIX_LEN); + tstruct.metas = metas; + tstruct.specs = specs; + } + + TypeSpec(TType ttype, TypeSpec* subtype1, TypeSpec* subtype2) : + ttype(ttype) + { + std::memset(fp_prefix, 0, FP_PREFIX_LEN); + tcontainer.subtype1 = subtype1; + tcontainer.subtype2 = subtype2; + } + +}; + +}}}} // apache::thrift::reflection::local + +#endif // #ifndef _THRIFT_TREFLECTIONLOCAL_H_ diff --git a/sg_agent/thrid_party/thrift/include/Thrift.cpp b/sg_agent/thrid_party/thrift/include/Thrift.cpp new file mode 100644 index 0000000..114947f --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/Thrift.cpp @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include +#include + +namespace apache { namespace thrift { + +TOutput GlobalOutput; + +void TOutput::printf(const char *message, ...) { + // Try to reduce heap usage, even if printf is called rarely. + static const int STACK_BUF_SIZE = 256; + char stack_buf[STACK_BUF_SIZE]; + va_list ap; + + va_start(ap, message); + int need = vsnprintf(stack_buf, STACK_BUF_SIZE, message, ap); + va_end(ap); + + if (need < STACK_BUF_SIZE) { + f_(stack_buf); + return; + } + + char *heap_buf = (char*)malloc((need+1) * sizeof(char)); + if (heap_buf == NULL) { + // Malloc failed. We might as well print the stack buffer. + f_(stack_buf); + return; + } + + va_start(ap, message); + int rval = vsnprintf(heap_buf, need+1, message, ap); + va_end(ap); + // TODO(shigin): inform user + if (rval != -1) { + f_(heap_buf); + } + free(heap_buf); +} + +void TOutput::perror(const char *message, int errno_copy) { + std::string out = message + strerror_s(errno_copy); + f_(out.c_str()); +} + +std::string TOutput::strerror_s(int errno_copy) { +#ifndef HAVE_STRERROR_R + return "errno = " + boost::lexical_cast(errno_copy); +#else // HAVE_STRERROR_R + + char b_errbuf[1024] = { '\0' }; +#ifdef STRERROR_R_CHAR_P + char *b_error = strerror_r(errno_copy, b_errbuf, sizeof(b_errbuf)); +#else + char *b_error = b_errbuf; + int rv = strerror_r(errno_copy, b_errbuf, sizeof(b_errbuf)); + if (rv == -1) { + // strerror_r failed. omgwtfbbq. + return "XSI-compliant strerror_r() failed with errno = " + + boost::lexical_cast(errno_copy); + } +#endif + // Can anyone prove that explicit cast is probably not necessary + // to ensure that the string object is constructed before + // b_error becomes invalid? + return std::string(b_error); + +#endif // HAVE_STRERROR_R +} + +}} // apache::thrift diff --git a/sg_agent/thrid_party/thrift/include/Thrift.h b/sg_agent/thrid_party/thrift/include/Thrift.h new file mode 100644 index 0000000..60a66f4 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/Thrift.h @@ -0,0 +1,210 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_THRIFT_H_ +#define _THRIFT_THRIFT_H_ 1 + +#ifdef _WIN32 +#include "windows/config.h" +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_INTTYPES_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "TLogging.h" + +/** + * Helper macros to allow function overloading even when using + * boost::shared_ptr. + * + * shared_ptr makes overloading really annoying, since shared_ptr defines + * constructor methods to allow one shared_ptr type to be constructed from any + * other shared_ptr type. (Even if it would be a compile error to actually try + * to instantiate the constructor.) These macros add an extra argument to the + * function to cause it to only be instantiated if a pointer of type T is + * convertible to a pointer of type U. + * + * THRIFT_OVERLOAD_IF should be used in function declarations. + * THRIFT_OVERLOAD_IF_DEFN should be used in the function definition, if it is + * defined separately from where it is declared. + */ +#define THRIFT_OVERLOAD_IF_DEFN(T, Y) \ + typename ::boost::enable_if::type, \ + void*>::type + +#define THRIFT_OVERLOAD_IF(T, Y) \ + THRIFT_OVERLOAD_IF_DEFN(T, Y) = NULL + +namespace apache { namespace thrift { + +class TEnumIterator : public std::iterator > { + public: + TEnumIterator(int n, + int* enums, + const char** names) : + ii_(0), n_(n), enums_(enums), names_(names) { + } + + int operator ++() { + return ++ii_; + } + + bool operator !=(const TEnumIterator& end) { + assert(end.n_ == -1); + return (ii_ != n_); + } + + std::pair operator*() const { + return std::make_pair(enums_[ii_], names_[ii_]); + } + + private: + int ii_; + const int n_; + int* enums_; + const char** names_; +}; + +class TOutput { + public: + TOutput() : f_(&errorTimeWrapper) {} + + inline void setOutputFunction(void (*function)(const char *)){ + f_ = function; + } + + inline void operator()(const char *message){ + f_(message); + } + + // It is important to have a const char* overload here instead of + // just the string version, otherwise errno could be corrupted + // if there is some problem allocating memory when constructing + // the string. + void perror(const char *message, int errno_copy); + inline void perror(const std::string &message, int errno_copy) { + perror(message.c_str(), errno_copy); + } + + void printf(const char *message, ...); + + inline static void errorTimeWrapper(const char* msg) { + time_t now; + char dbgtime[26]; + time(&now); + ctime_r(&now, dbgtime); + dbgtime[24] = 0; + fprintf(stderr, "Thrift: %s %s\n", dbgtime, msg); + } + + /** Just like strerror_r but returns a C++ string object. */ + static std::string strerror_s(int errno_copy); + + private: + void (*f_)(const char *); +}; + +extern TOutput GlobalOutput; + +class TException : public std::exception { + public: + TException(): + message_() {} + + TException(const std::string& message) : + message_(message) {} + + virtual ~TException() throw() {} + + virtual const char* what() const throw() { + if (message_.empty()) { + return "Default TException."; + } else { + return message_.c_str(); + } + } + + protected: + std::string message_; + +}; + + +// Forward declare this structure used by TDenseProtocol +namespace reflection { namespace local { +struct TypeSpec; +}} + +class TDelayedException { + public: + template static TDelayedException* delayException(const E& e); + virtual void throw_it() = 0; + virtual ~TDelayedException() {}; +}; + +template class TExceptionWrapper : public TDelayedException { + public: + TExceptionWrapper(const E& e) : e_(e) {} + virtual void throw_it() { + E temp(e_); + delete this; + throw temp; + } + private: + E e_; +}; + +template +TDelayedException* TDelayedException::delayException(const E& e) { + return new TExceptionWrapper(e); +} + +#if T_GLOBAL_DEBUG_VIRTUAL > 1 +void profile_virtual_call(const std::type_info& info); +void profile_generic_protocol(const std::type_info& template_type, + const std::type_info& prot_type); +void profile_print_info(FILE *f); +void profile_print_info(); +void profile_write_pprof(FILE* gen_calls_f, FILE* virtual_calls_f); +#endif + +}} // apache::thrift + +#endif // #ifndef _THRIFT_THRIFT_H_ diff --git a/sg_agent/thrid_party/thrift/include/VirtualProfiling.cpp b/sg_agent/thrid_party/thrift/include/VirtualProfiling.cpp new file mode 100644 index 0000000..0b023af --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/VirtualProfiling.cpp @@ -0,0 +1,455 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include + +// Do nothing if virtual call profiling is not enabled +#if T_GLOBAL_DEBUG_VIRTUAL > 1 + +// TODO: This code only works with g++ (since we rely on the fact +// that all std::type_info instances referring to a particular type +// always return the exact same pointer value from name().) +#ifndef __GNUG__ +#error "Thrift virtual function profiling currently only works with gcc" +#endif // !__GNUG__ + +// TODO: We also require glibc for the backtrace() and backtrace_symbols() +// functions. +#ifndef __GLIBC__ +#error "Thrift virtual function profiling currently requires glibc" +#endif // !__GLIBC__ + + +#include + +#include +#include +#include + +namespace apache { namespace thrift { + +using ::apache::thrift::concurrency::Mutex; +using ::apache::thrift::concurrency::Guard; + +static const unsigned int MAX_STACK_DEPTH = 15; + +/** + * A stack trace + */ +class Backtrace { + public: + Backtrace(int skip = 0); + Backtrace(Backtrace const &bt); + + void operator=(Backtrace const &bt) { + numCallers_ = bt.numCallers_; + if (numCallers_ >= 0) { + memcpy(callers_, bt.callers_, numCallers_ * sizeof(void*)); + } + } + + bool operator==(Backtrace const &bt) const { + return (cmp(bt) == 0); + } + + size_t hash() const { + intptr_t ret = 0; + for (int n = 0; n < numCallers_; ++n) { + ret ^= reinterpret_cast(callers_[n]); + } + return static_cast(ret); + } + + int cmp(Backtrace const& bt) const { + int depth_diff = (numCallers_ - bt.numCallers_); + if (depth_diff != 0) { + return depth_diff; + } + + for (int n = 0; n < numCallers_; ++n) { + int diff = reinterpret_cast(callers_[n]) - + reinterpret_cast(bt.callers_[n]); + if (diff != 0) { + return diff; + } + } + + return 0; + } + + void print(FILE *f, int indent=0, int start=0) const { + char **strings = backtrace_symbols(callers_, numCallers_); + if (strings) { + start += skip_; + if (start < 0) { + start = 0; + } + for (int n = start; n < numCallers_; ++n) { + fprintf(f, "%*s#%-2d %s\n", indent, "", n, strings[n]); + } + free(strings); + } else { + fprintf(f, "%*s\n", indent, ""); + } + } + + int getDepth() const { + return numCallers_ - skip_; + } + + void *getFrame(int index) const { + int adjusted_index = index + skip_; + if (adjusted_index < 0 || adjusted_index >= numCallers_) { + return NULL; + } + return callers_[adjusted_index]; + } + + private: + void *callers_[MAX_STACK_DEPTH]; + int numCallers_; + int skip_; +}; + +// Define the constructors non-inline, so they consistently add a single +// frame to the stack trace, regardless of whether optimization is enabled +Backtrace::Backtrace(int skip) + : skip_(skip + 1) // ignore the constructor itself +{ + numCallers_ = backtrace(callers_, MAX_STACK_DEPTH); + if (skip_ > numCallers_) { + skip_ = numCallers_; + } +} + +Backtrace::Backtrace(Backtrace const &bt) + : numCallers_(bt.numCallers_) + , skip_(bt.skip_) { + if (numCallers_ >= 0) { + memcpy(callers_, bt.callers_, numCallers_ * sizeof(void*)); + } +} + +/** + * A backtrace, plus one or two type names + */ +class Key { + public: + class Hash { + public: + size_t operator()(Key const& k) const { + return k.hash(); + } + }; + + Key(const Backtrace* bt, const std::type_info& type_info) + : backtrace_(bt) + , typeName1_(type_info.name()) + , typeName2_(NULL) { + } + + Key(const Backtrace* bt, const std::type_info& type_info1, + const std::type_info& type_info2) + : backtrace_(bt) + , typeName1_(type_info1.name()) + , typeName2_(type_info2.name()) { + } + + Key(const Key& k) + : backtrace_(k.backtrace_) + , typeName1_(k.typeName1_) + , typeName2_(k.typeName2_) { + } + + void operator=(const Key& k) { + backtrace_ = k.backtrace_; + typeName1_ = k.typeName1_; + typeName2_ = k.typeName2_; + } + + const Backtrace* getBacktrace() const { + return backtrace_; + } + + const char* getTypeName() const { + return typeName1_; + } + + const char* getTypeName2() const { + return typeName2_; + } + + void makePersistent() { + // Copy the Backtrace object + backtrace_ = new Backtrace(*backtrace_); + + // NOTE: We don't copy the type name. + // The GNU libstdc++ implementation of type_info::name() returns a value + // that will be valid for the lifetime of the program. (Although the C++ + // standard doesn't guarantee this will be true on all implementations.) + } + + /** + * Clean up memory allocated by makePersistent() + * + * Should only be invoked if makePersistent() has previously been called. + * The Key should no longer be used after cleanup() is called. + */ + void cleanup() { + delete backtrace_; + backtrace_ = NULL; + } + + int cmp(const Key& k) const { + int ret = backtrace_->cmp(*k.backtrace_); + if (ret != 0) { + return ret; + } + + // NOTE: We compare just the name pointers. + // With GNU libstdc++, every type_info object for the same type points to + // exactly the same name string. (Although this isn't guaranteed by the + // C++ standard.) + ret = k.typeName1_ - typeName1_; + if (ret != 0) { + return ret; + } + return k.typeName2_ - typeName2_; + } + + bool operator==(const Key& k) const { + return cmp(k) == 0; + } + + size_t hash() const { + // NOTE: As above, we just use the name pointer value. + // Works with GNU libstdc++, but not guaranteed to be correct on all + // implementations. + return backtrace_->hash() ^ + reinterpret_cast(typeName1_) ^ + reinterpret_cast(typeName2_); + } + + private: + const Backtrace* backtrace_; + const char* typeName1_; + const char* typeName2_; +}; + +/** + * A functor that determines which of two BacktraceMap entries + * has a higher count. + */ +class CountGreater { + public: + bool operator()(std::pair bt1, + std::pair bt2) const { + return bt1.second > bt2.second; + } +}; + +typedef __gnu_cxx::hash_map BacktraceMap; + +/** + * A map describing how many times T_VIRTUAL_CALL() has been invoked. + */ +BacktraceMap virtual_calls; +Mutex virtual_calls_mutex; + +/** + * A map describing how many times T_GENERIC_PROTOCOL() has been invoked. + */ +BacktraceMap generic_calls; +Mutex generic_calls_mutex; + + +void _record_backtrace(BacktraceMap* map, const Mutex& mutex, Key *k) { + Guard guard(mutex); + + BacktraceMap::iterator it = map->find(*k); + if (it == map->end()) { + k->makePersistent(); + map->insert(std::make_pair(*k, 1)); + } else { + // increment the count + // NOTE: we could assert if it->second is 0 afterwards, since that would + // mean we've wrapped. + ++(it->second); + } +} + +/** + * Record an unnecessary virtual function call. + * + * This method is invoked by the T_VIRTUAL_CALL() macro. + */ +void profile_virtual_call(const std::type_info& type) { + int const skip = 1; // ignore this frame + Backtrace bt(skip); + Key k(&bt, type); + _record_backtrace(&virtual_calls, virtual_calls_mutex, &k); +} + +/** + * Record a call to a template processor with a protocol that is not the one + * specified in the template parameter. + * + * This method is invoked by the T_GENERIC_PROTOCOL() macro. + */ +void profile_generic_protocol(const std::type_info& template_type, + const std::type_info& prot_type) { + int const skip = 1; // ignore this frame + Backtrace bt(skip); + Key k(&bt, template_type, prot_type); + _record_backtrace(&generic_calls, generic_calls_mutex, &k); +} + +/** + * Print the recorded profiling information to the specified file. + */ +void profile_print_info(FILE* f) { + typedef std::vector< std::pair > BacktraceVector; + + CountGreater is_greater; + + // Grab both locks for the duration of the print operation, + // to ensure the output is a consistent snapshot of a single point in time + Guard generic_calls_guard(generic_calls_mutex); + Guard virtual_calls_guard(virtual_calls_mutex); + + // print the info from generic_calls, sorted by frequency + // + // We print the generic_calls info ahead of virtual_calls, since it is more + // useful in some cases. All T_GENERIC_PROTOCOL calls can be eliminated + // from most programs. Not all T_VIRTUAL_CALLs will be eliminated by + // converting to templates. + BacktraceVector gp_sorted(generic_calls.begin(), generic_calls.end()); + std::sort(gp_sorted.begin(), gp_sorted.end(), is_greater); + + for (BacktraceVector::const_iterator it = gp_sorted.begin(); + it != gp_sorted.end(); + ++it) { + Key const &key = it->first; + size_t const count = it->second; + fprintf(f, "T_GENERIC_PROTOCOL: %zu calls to %s with a %s:\n", + count, key.getTypeName(), key.getTypeName2()); + key.getBacktrace()->print(f, 2); + fprintf(f, "\n"); + } + + // print the info from virtual_calls, sorted by frequency + BacktraceVector vc_sorted(virtual_calls.begin(), virtual_calls.end()); + std::sort(vc_sorted.begin(), vc_sorted.end(), is_greater); + + for (BacktraceVector::const_iterator it = vc_sorted.begin(); + it != vc_sorted.end(); + ++it) { + Key const &key = it->first; + size_t const count = it->second; + fprintf(f, "T_VIRTUAL_CALL: %zu calls on %s:\n", count, key.getTypeName()); + key.getBacktrace()->print(f, 2); + fprintf(f, "\n"); + } +} + +/** + * Print the recorded profiling information to stdout. + */ +void profile_print_info() { + profile_print_info(stdout); +} + +/** + * Write a BacktraceMap as Google CPU profiler binary data. + */ +static void profile_write_pprof_file(FILE* f, BacktraceMap const& map) { + // Write the header + uintptr_t header[5] = { 0, 3, 0, 0, 0 }; + fwrite(&header, sizeof(header), 1, f); + + // Write the profile records + for (BacktraceMap::const_iterator it = map.begin(); it != map.end(); ++it) { + uintptr_t count = it->second; + fwrite(&count, sizeof(count), 1, f); + + Backtrace const* bt = it->first.getBacktrace(); + uintptr_t num_pcs = bt->getDepth(); + fwrite(&num_pcs, sizeof(num_pcs), 1, f); + + for (uintptr_t n = 0; n < num_pcs; ++n) { + void* pc = bt->getFrame(n); + fwrite(&pc, sizeof(pc), 1, f); + } + } + + // Write the trailer + uintptr_t trailer[3] = { 0, 1, 0 }; + fwrite(&trailer, sizeof(trailer), 1, f); + + // Write /proc/self/maps + // TODO(simpkins): This only works on linux + FILE *proc_maps = fopen("/proc/self/maps", "r"); + if (proc_maps) { + uint8_t buf[4096]; + while (true) { + size_t bytes_read = fread(buf, 1, sizeof(buf), proc_maps); + if (bytes_read == 0) { + break; + } + fwrite(buf, 1, bytes_read, f); + } + fclose(proc_maps); + } +} + +/** + * Write the recorded profiling information as pprof files. + * + * This writes the information using the Google CPU profiler binary data + * format, so it can be analyzed with pprof. Note that information about the + * protocol/transport data types cannot be stored in this file format. + * + * See http://code.google.com/p/google-perftools/ for more details. + * + * @param gen_calls_f The information about calls to + * profile_generic_protocol() will be written to this + * file. + * @param virtual_calls_f The information about calls to + * profile_virtual_call() will be written to this file. + */ +void profile_write_pprof(FILE* gen_calls_f, FILE* virtual_calls_f) { + typedef std::vector< std::pair > BacktraceVector; + + CountGreater is_greater; + + // Grab both locks for the duration of the print operation, + // to ensure the output is a consistent snapshot of a single point in time + Guard generic_calls_guard(generic_calls_mutex); + Guard virtual_calls_guard(virtual_calls_mutex); + + // write the info from generic_calls + profile_write_pprof_file(gen_calls_f, generic_calls); + + // write the info from virtual_calls + profile_write_pprof_file(virtual_calls_f, virtual_calls); +} + +}} // apache::thrift + +#endif // T_GLOBAL_PROFILE_VIRTUAL > 0 diff --git a/sg_agent/thrid_party/thrift/include/async/TAsyncBufferProcessor.h b/sg_agent/thrid_party/thrift/include/async/TAsyncBufferProcessor.h new file mode 100644 index 0000000..bfaf323 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/async/TAsyncBufferProcessor.h @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TASYNC_BUFFER_PROCESSOR_H_ +#define _THRIFT_TASYNC_BUFFER_PROCESSOR_H_ 1 + +#include +#include + +#include "transport/TBufferTransports.h" + +namespace apache { namespace thrift { namespace async { + +class TAsyncBufferProcessor { + public: + // Process data in "in", putting the result in "out". + // Call _return(true) when done, or _return(false) to + // forcefully close the connection (if applicable). + // "in" and "out" should be TMemoryBuffer or similar, + // not a wrapper around a socket. + virtual void process( + std::tr1::function _return, + boost::shared_ptr ibuf, + boost::shared_ptr obuf) = 0; + virtual ~TAsyncBufferProcessor() {} +}; + +}}} // apache::thrift::async + +#endif // #ifndef _THRIFT_TASYNC_BUFFER_PROCESSOR_H_ diff --git a/sg_agent/thrid_party/thrift/include/async/TAsyncChannel.cpp b/sg_agent/thrid_party/thrift/include/async/TAsyncChannel.cpp new file mode 100644 index 0000000..9397017 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/async/TAsyncChannel.cpp @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include + +namespace apache { namespace thrift { namespace async { + +void TAsyncChannel::sendAndRecvMessage(const VoidCallback& cob, + TMemoryBuffer* sendBuf, + TMemoryBuffer* recvBuf) { + std::tr1::function send_done = + std::tr1::bind(&TAsyncChannel::recvMessage, this, cob, recvBuf); + + sendMessage(send_done, sendBuf); +} + +}}} // apache::thrift::async diff --git a/sg_agent/thrid_party/thrift/include/async/TAsyncChannel.h b/sg_agent/thrid_party/thrift/include/async/TAsyncChannel.h new file mode 100644 index 0000000..856ab31 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/async/TAsyncChannel.h @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_ASYNC_TASYNCCHANNEL_H_ +#define _THRIFT_ASYNC_TASYNCCHANNEL_H_ 1 + +#include +#include + +namespace apache { namespace thrift { namespace transport { +class TMemoryBuffer; +}}} + +namespace apache { namespace thrift { namespace async { +using apache::thrift::transport::TMemoryBuffer; + +class TAsyncChannel { + public: + typedef std::tr1::function VoidCallback; + + virtual ~TAsyncChannel() {} + + // is the channel in a good state? + virtual bool good() const = 0; + virtual bool error() const = 0; + virtual bool timedOut() const = 0; + + /** + * Send a message over the channel. + */ + virtual void sendMessage(const VoidCallback& cob, + apache::thrift::transport::TMemoryBuffer* message) = 0; + + /** + * Receive a message from the channel. + */ + virtual void recvMessage(const VoidCallback& cob, + apache::thrift::transport::TMemoryBuffer* message) = 0; + + /** + * Send a message over the channel and receive a response. + */ + virtual void sendAndRecvMessage(const VoidCallback& cob, + apache::thrift::transport::TMemoryBuffer* sendBuf, + apache::thrift::transport::TMemoryBuffer* recvBuf); +}; + +}}} // apache::thrift::async + +#endif // #ifndef _THRIFT_ASYNC_TASYNCCHANNEL_H_ diff --git a/sg_agent/thrid_party/thrift/include/async/TAsyncProcessor.h b/sg_agent/thrid_party/thrift/include/async/TAsyncProcessor.h new file mode 100644 index 0000000..c62f8b7 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/async/TAsyncProcessor.h @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TASYNCPROCESSOR_H_ +#define _THRIFT_TASYNCPROCESSOR_H_ 1 + +#include +#include +#include +#include + +namespace apache { namespace thrift { namespace async { + +/** + * Async version of a TProcessor. It is not expected to complete by the time + * the call to process returns. Instead, it calls a cob to signal completion. + */ + +class TEventServer; // forward declaration + +class TAsyncProcessor { + public: + virtual ~TAsyncProcessor() {} + + virtual void process(std::tr1::function _return, + boost::shared_ptr in, + boost::shared_ptr out) = 0; + + void process(std::tr1::function _return, + boost::shared_ptr io) { + return process(_return, io, io); + } + + boost::shared_ptr getEventHandler() { + return eventHandler_; + } + + void setEventHandler(boost::shared_ptr eventHandler) { + eventHandler_ = eventHandler; + } + + const TEventServer* getAsyncServer() { + return asyncServer_; + } + protected: + TAsyncProcessor() {} + + boost::shared_ptr eventHandler_; + const TEventServer* asyncServer_; + private: + friend class TEventServer; + void setAsyncServer(const TEventServer* server) { + asyncServer_ = server; + } +}; + +class TAsyncProcessorFactory { + public: + virtual ~TAsyncProcessorFactory() {} + + /** + * Get the TAsyncProcessor to use for a particular connection. + * + * This method is always invoked in the same thread that the connection was + * accepted on. This generally means that this call does not need to be + * thread safe, as it will always be invoked from a single thread. + */ + virtual boost::shared_ptr getProcessor( + const TConnectionInfo& connInfo) = 0; +}; + + + +}}} // apache::thrift::async + +// XXX I'm lazy for now +namespace apache { namespace thrift { +using apache::thrift::async::TAsyncProcessor; +}} + +#endif // #ifndef _THRIFT_TASYNCPROCESSOR_H_ diff --git a/sg_agent/thrid_party/thrift/include/async/TAsyncProtocolProcessor.cpp b/sg_agent/thrid_party/thrift/include/async/TAsyncProtocolProcessor.cpp new file mode 100644 index 0000000..eaa86e0 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/async/TAsyncProtocolProcessor.cpp @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "TAsyncProtocolProcessor.h" + +using apache::thrift::transport::TBufferBase; +using apache::thrift::protocol::TProtocol; + +namespace apache { namespace thrift { namespace async { + +void TAsyncProtocolProcessor::process( + std::tr1::function _return, + boost::shared_ptr ibuf, + boost::shared_ptr obuf) { + boost::shared_ptr iprot(pfact_->getProtocol(ibuf)); + boost::shared_ptr oprot(pfact_->getProtocol(obuf)); + return underlying_->process( + std::tr1::bind( + &TAsyncProtocolProcessor::finish, + _return, + oprot, + std::tr1::placeholders::_1), + iprot, oprot); +} + +/* static */ void TAsyncProtocolProcessor::finish( + std::tr1::function _return, + boost::shared_ptr oprot, + bool healthy) { + (void) oprot; + // This is a stub function to hold a reference to oprot. + return _return(healthy); +} + +}}} // apache::thrift::async diff --git a/sg_agent/thrid_party/thrift/include/async/TAsyncProtocolProcessor.h b/sg_agent/thrid_party/thrift/include/async/TAsyncProtocolProcessor.h new file mode 100644 index 0000000..647bbb6 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/async/TAsyncProtocolProcessor.h @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TNAME_ME_H_ +#define _THRIFT_TNAME_ME_H_ 1 + +#include "TAsyncProcessor.h" +#include "TAsyncBufferProcessor.h" +#include "protocol/TProtocol.h" + +namespace apache { namespace thrift { namespace async { + +class TAsyncProtocolProcessor : public TAsyncBufferProcessor { + public: + TAsyncProtocolProcessor( + boost::shared_ptr underlying, + boost::shared_ptr pfact) + : underlying_(underlying) + , pfact_(pfact) + {} + + virtual void process( + std::tr1::function _return, + boost::shared_ptr ibuf, + boost::shared_ptr obuf); + + virtual ~TAsyncProtocolProcessor() {} + + private: + static void finish( + std::tr1::function _return, + boost::shared_ptr oprot, + bool healthy); + + boost::shared_ptr underlying_; + boost::shared_ptr pfact_; +}; + +}}} // apache::thrift::async + +#endif // #ifndef _THRIFT_TNAME_ME_H_ diff --git a/sg_agent/thrid_party/thrift/include/async/TEvhttpClientChannel.cpp b/sg_agent/thrid_party/thrift/include/async/TEvhttpClientChannel.cpp new file mode 100755 index 0000000..c0363fc --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/async/TEvhttpClientChannel.cpp @@ -0,0 +1,162 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "TEvhttpClientChannel.h" +#include +#include "transport/TBufferTransports.h" +#include + +#include +#include + +using namespace apache::thrift::protocol; +using apache::thrift::transport::TTransportException; + +namespace apache { namespace thrift { namespace async { + + +TEvhttpClientChannel::TEvhttpClientChannel( + const std::string& host, + const std::string& path, + const char* address, + int port, + struct event_base* eb) + : host_(host) + , path_(path) + , recvBuf_(NULL) + , conn_(NULL) +{ + conn_ = evhttp_connection_new(address, port); + if (conn_ == NULL) { + throw TException("evhttp_connection_new failed"); + } + evhttp_connection_set_base(conn_, eb); +} + + +TEvhttpClientChannel::~TEvhttpClientChannel() { + if (conn_ != NULL) { + evhttp_connection_free(conn_); + } +} + + +void TEvhttpClientChannel::sendAndRecvMessage( + const VoidCallback& cob, + apache::thrift::transport::TMemoryBuffer* sendBuf, + apache::thrift::transport::TMemoryBuffer* recvBuf) { + cob_ = cob; + recvBuf_ = recvBuf; + + struct evhttp_request* req = evhttp_request_new(response, this); + if (req == NULL) { + throw TException("evhttp_request_new failed"); + } + + int rv; + + rv = evhttp_add_header(req->output_headers, "Host", host_.c_str()); + if (rv != 0) { + throw TException("evhttp_add_header failed"); + } + + rv = evhttp_add_header(req->output_headers, "Content-Type", "application/x-thrift"); + if (rv != 0) { + throw TException("evhttp_add_header failed"); + } + + uint8_t* obuf; + uint32_t sz; + sendBuf->getBuffer(&obuf, &sz); + rv = evbuffer_add(req->output_buffer, obuf, sz); + if (rv != 0) { + throw TException("evbuffer_add failed"); + } + + rv = evhttp_make_request(conn_, req, EVHTTP_REQ_POST, path_.c_str()); + if (rv != 0) { + throw TException("evhttp_make_request failed"); + } +} + + +void TEvhttpClientChannel::sendMessage( + const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* message) { + (void) cob; + (void) message; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "Unexpected call to TEvhttpClientChannel::sendMessage"); +} + + +void TEvhttpClientChannel::recvMessage( + const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* message) { + (void) cob; + (void) message; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "Unexpected call to TEvhttpClientChannel::recvMessage"); +} + + +void TEvhttpClientChannel::finish(struct evhttp_request* req) { + if (req == NULL) { + try { + cob_(); + } catch(const TTransportException& e) { + if(e.getType() == TTransportException::END_OF_FILE) + throw TException("connect failed"); + else + throw; + } + return; + } else if (req->response_code != 200) { + try { + cob_(); + } catch(const TTransportException& e) { + std::stringstream ss; + ss << "server returned code " << req->response_code; + if(req->response_code_line) + ss << ": " << req->response_code_line; + if(e.getType() == TTransportException::END_OF_FILE) + throw TException(ss.str()); + else + throw; + } + return; + } + recvBuf_->resetBuffer( + EVBUFFER_DATA(req->input_buffer), + EVBUFFER_LENGTH(req->input_buffer)); + cob_(); + return; +} + + +/* static */ void TEvhttpClientChannel::response(struct evhttp_request* req, void* arg) { + TEvhttpClientChannel* self = (TEvhttpClientChannel*)arg; + try { + self->finish(req); + } catch(std::exception& e) { + // don't propagate a C++ exception in C code (e.g. libevent) + std::cerr << "TEvhttpClientChannel::response exception thrown (ignored): " << e.what() << std::endl; + } +} + + +}}} // apache::thrift::async diff --git a/sg_agent/thrid_party/thrift/include/async/TEvhttpClientChannel.h b/sg_agent/thrid_party/thrift/include/async/TEvhttpClientChannel.h new file mode 100644 index 0000000..d497edb --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/async/TEvhttpClientChannel.h @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TEVHTTP_CLIENT_CHANNEL_H_ +#define _THRIFT_TEVHTTP_CLIENT_CHANNEL_H_ 1 + +#include +#include +#include "TAsyncChannel.h" + +struct event_base; +struct evhttp_connection; +struct evhttp_request; + +namespace apache { namespace thrift { namespace transport { +class TMemoryBuffer; +}}} + +namespace apache { namespace thrift { namespace async { + +class TEvhttpClientChannel : public TAsyncChannel { + public: + using TAsyncChannel::VoidCallback; + + TEvhttpClientChannel( + const std::string& host, + const std::string& path, + const char* address, + int port, + struct event_base* eb); + ~TEvhttpClientChannel(); + + virtual void sendAndRecvMessage(const VoidCallback& cob, + apache::thrift::transport::TMemoryBuffer* sendBuf, + apache::thrift::transport::TMemoryBuffer* recvBuf); + + virtual void sendMessage(const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* message); + virtual void recvMessage(const VoidCallback& cob, apache::thrift::transport::TMemoryBuffer* message); + + void finish(struct evhttp_request* req); + + //XXX + virtual bool good() const { return true; } + virtual bool error() const { return false; } + virtual bool timedOut() const { return false; } + + private: + static void response(struct evhttp_request* req, void* arg); + + std::string host_; + std::string path_; + VoidCallback cob_; + apache::thrift::transport::TMemoryBuffer* recvBuf_; + struct evhttp_connection* conn_; + +}; + +}}} // apache::thrift::async + +#endif // #ifndef _THRIFT_TEVHTTP_CLIENT_CHANNEL_H_ diff --git a/sg_agent/thrid_party/thrift/include/async/TEvhttpServer.cpp b/sg_agent/thrid_party/thrift/include/async/TEvhttpServer.cpp new file mode 100755 index 0000000..b92422c --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/async/TEvhttpServer.cpp @@ -0,0 +1,169 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "TEvhttpServer.h" +#include "TAsyncBufferProcessor.h" +#include "transport/TBufferTransports.h" +#include + +#include + +#ifndef HTTP_INTERNAL // libevent < 2 +#define HTTP_INTERNAL 500 +#endif + +using apache::thrift::transport::TMemoryBuffer; + +namespace apache { namespace thrift { namespace async { + + +struct TEvhttpServer::RequestContext { + struct evhttp_request* req; + boost::shared_ptr ibuf; + boost::shared_ptr obuf; + + RequestContext(struct evhttp_request* req); +}; + + +TEvhttpServer::TEvhttpServer(boost::shared_ptr processor) + : processor_(processor) + , eb_(NULL) + , eh_(NULL) +{} + + +TEvhttpServer::TEvhttpServer(boost::shared_ptr processor, int port) + : processor_(processor) + , eb_(NULL) + , eh_(NULL) +{ + // Create event_base and evhttp. + eb_ = event_base_new(); + if (eb_ == NULL) { + throw TException("event_base_new failed"); + } + eh_ = evhttp_new(eb_); + if (eh_ == NULL) { + event_base_free(eb_); + throw TException("evhttp_new failed"); + } + + // Bind to port. + int ret = evhttp_bind_socket(eh_, NULL, port); + if (ret < 0) { + evhttp_free(eh_); + event_base_free(eb_); + throw TException("evhttp_bind_socket failed"); + } + + // Register a handler. If you use the other constructor, + // you will want to do this yourself. + // Don't forget to unregister before destorying this TEvhttpServer. + evhttp_set_cb(eh_, "/", request, (void*)this); +} + + +TEvhttpServer::~TEvhttpServer() { + if (eh_ != NULL) { + evhttp_free(eh_); + } + if (eb_ != NULL) { + event_base_free(eb_); + } +} + + +int TEvhttpServer::serve() { + if (eb_ == NULL) { + throw TException("Unexpected call to TEvhttpServer::serve"); + } + return event_base_dispatch(eb_); +} + + +TEvhttpServer::RequestContext::RequestContext(struct evhttp_request* req) : req(req) + , ibuf(new TMemoryBuffer(EVBUFFER_DATA(req->input_buffer), EVBUFFER_LENGTH(req->input_buffer))) + , obuf(new TMemoryBuffer()) +{} + + +void TEvhttpServer::request(struct evhttp_request* req, void* self) { + try { + static_cast(self)->process(req); + } catch(std::exception& e) { + evhttp_send_reply(req, HTTP_INTERNAL, e.what(), 0); + } +} + + +void TEvhttpServer::process(struct evhttp_request* req) { + RequestContext* ctx = new RequestContext(req); + return processor_->process( + std::tr1::bind( + &TEvhttpServer::complete, + this, + ctx, + std::tr1::placeholders::_1), + ctx->ibuf, + ctx->obuf); +} + + +void TEvhttpServer::complete(RequestContext* ctx, bool success) { + (void) success; + std::auto_ptr ptr(ctx); + + int code = success ? 200 : 400; + const char* reason = success ? "OK" : "Bad Request"; + + int rv = evhttp_add_header(ctx->req->output_headers, "Content-Type", "application/x-thrift"); + if (rv != 0) { + // TODO: Log an error. + std::cerr << "evhttp_add_header failed " << __FILE__ << ":" << __LINE__ << std::endl; + } + + struct evbuffer* buf = evbuffer_new(); + if (buf == NULL) { + // TODO: Log an error. + std::cerr << "evbuffer_new failed " << __FILE__ << ":" << __LINE__ << std::endl; + } else { + uint8_t* obuf; + uint32_t sz; + ctx->obuf->getBuffer(&obuf, &sz); + int ret = evbuffer_add(buf, obuf, sz); + if (ret != 0) { + // TODO: Log an error. + std::cerr << "evhttp_add failed with " << ret << " " << __FILE__ << ":" << __LINE__ << std::endl; + } + } + + evhttp_send_reply(ctx->req, code, reason, buf); + if (buf != NULL) { + evbuffer_free(buf); + } +} + + +struct event_base* TEvhttpServer::getEventBase() { + return eb_; +} + + +}}} // apache::thrift::async diff --git a/sg_agent/thrid_party/thrift/include/async/TEvhttpServer.h b/sg_agent/thrid_party/thrift/include/async/TEvhttpServer.h new file mode 100644 index 0000000..edc6ffb --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/async/TEvhttpServer.h @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TEVHTTP_SERVER_H_ +#define _THRIFT_TEVHTTP_SERVER_H_ 1 + +#include + +struct event_base; +struct evhttp; +struct evhttp_request; + +namespace apache { namespace thrift { namespace async { + +class TAsyncBufferProcessor; + +class TEvhttpServer { + public: + /** + * Create a TEvhttpServer for use with an external evhttp instance. + * Must be manually installed with evhttp_set_cb, using + * TEvhttpServer::request as the callback and the + * address of the server as the extra arg. + * Do not call "serve" on this server. + */ + TEvhttpServer(boost::shared_ptr processor); + + /** + * Create a TEvhttpServer with an embedded event_base and evhttp, + * listening on port and responding on the endpoint "/". + * Call "serve" on this server to serve forever. + */ + TEvhttpServer(boost::shared_ptr processor, int port); + + ~TEvhttpServer(); + + static void request(struct evhttp_request* req, void* self); + int serve(); + + struct event_base* getEventBase(); + + private: + struct RequestContext; + + void process(struct evhttp_request* req); + void complete(RequestContext* ctx, bool success); + + boost::shared_ptr processor_; + struct event_base* eb_; + struct evhttp* eh_; +}; + +}}} // apache::thrift::async + +#endif // #ifndef _THRIFT_TEVHTTP_SERVER_H_ diff --git a/sg_agent/thrid_party/thrift/include/concurrency/BoostMonitor.cpp b/sg_agent/thrid_party/thrift/include/concurrency/BoostMonitor.cpp new file mode 100644 index 0000000..2adf7d7 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/BoostMonitor.cpp @@ -0,0 +1,198 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "Monitor.h" +#include "Exception.h" +#include "Util.h" + +#include +#include + +#include +#include +#include + +namespace apache { namespace thrift { namespace concurrency { + +/** + * Monitor implementation using the boost thread library + * + * @version $Id:$ + */ +class Monitor::Impl : public boost::condition_variable_any { + + public: + + Impl() + : ownedMutex_(new Mutex()), + mutex_(NULL) { + init(ownedMutex_.get()); + } + + Impl(Mutex* mutex) + : mutex_(NULL) { + init(mutex); + } + + Impl(Monitor* monitor) + : mutex_(NULL) { + init(&(monitor->mutex())); + } + + Mutex& mutex() { return *mutex_; } + void lock() { mutex().lock(); } + void unlock() { mutex().unlock(); } + + /** + * Exception-throwing version of waitForTimeRelative(), called simply + * wait(int64) for historical reasons. Timeout is in milliseconds. + * + * If the condition occurs, this function returns cleanly; on timeout or + * error an exception is thrown. + */ + void wait(int64_t timeout_ms) { + int result = waitForTimeRelative(timeout_ms); + if (result == ETIMEDOUT) { + throw TimedOutException(); + } else if (result != 0) { + throw TException( + "Monitor::wait() failed"); + } + } + + /** + * Waits until the specified timeout in milliseconds for the condition to + * occur, or waits forever if timeout_ms == 0. + * + * Returns 0 if condition occurs, ETIMEDOUT on timeout, or an error code. + */ + int waitForTimeRelative(int64_t timeout_ms) { + if (timeout_ms == 0LL) { + return waitForever(); + } + + assert(mutex_); + boost::timed_mutex* mutexImpl = + reinterpret_cast(mutex_->getUnderlyingImpl()); + assert(mutexImpl); + + boost::timed_mutex::scoped_lock lock(*mutexImpl, boost::adopt_lock); + int res = timed_wait(lock, boost::get_system_time()+boost::posix_time::milliseconds(timeout_ms)) ? 0 : ETIMEDOUT; + lock.release(); + return res; + } + + /** + * Waits until the absolute time specified using struct timespec. + * Returns 0 if condition occurs, ETIMEDOUT on timeout, or an error code. + */ + int waitForTime(const timespec* abstime) { + assert(mutex_); + boost::timed_mutex* mutexImpl = + reinterpret_cast(mutex_->getUnderlyingImpl()); + assert(mutexImpl); + + struct timespec currenttime; + Util::toTimespec(currenttime, Util::currentTime()); + + long tv_sec = abstime->tv_sec - currenttime.tv_sec; + long tv_nsec = abstime->tv_nsec - currenttime.tv_nsec; + if(tv_sec < 0) + tv_sec = 0; + if(tv_nsec < 0) + tv_nsec = 0; + + boost::timed_mutex::scoped_lock lock(*mutexImpl, boost::adopt_lock); + int res = timed_wait(lock, boost::get_system_time() + + boost::posix_time::seconds(tv_sec) + + boost::posix_time::microseconds(tv_nsec / 1000) + ) ? 0 : ETIMEDOUT; + lock.release(); + return res; + } + + /** + * Waits forever until the condition occurs. + * Returns 0 if condition occurs, or an error code otherwise. + */ + int waitForever() { + assert(mutex_); + boost::timed_mutex* mutexImpl = + reinterpret_cast(mutex_->getUnderlyingImpl()); + assert(mutexImpl); + + boost::timed_mutex::scoped_lock lock(*mutexImpl, boost::adopt_lock); + ((boost::condition_variable_any*)this)->wait(lock); + lock.release(); + return 0; + } + + + void notify() { + notify_one(); + } + + void notifyAll() { + notify_all(); + } + + private: + + void init(Mutex* mutex) { + mutex_ = mutex; + } + + boost::scoped_ptr ownedMutex_; + Mutex* mutex_; +}; + +Monitor::Monitor() : impl_(new Monitor::Impl()) {} +Monitor::Monitor(Mutex* mutex) : impl_(new Monitor::Impl(mutex)) {} +Monitor::Monitor(Monitor* monitor) : impl_(new Monitor::Impl(monitor)) {} + +Monitor::~Monitor() { delete impl_; } + +Mutex& Monitor::mutex() const { return const_cast(impl_)->mutex(); } + +void Monitor::lock() const { const_cast(impl_)->lock(); } + +void Monitor::unlock() const { const_cast(impl_)->unlock(); } + +void Monitor::wait(int64_t timeout) const { const_cast(impl_)->wait(timeout); } + +int Monitor::waitForTime(const timespec* abstime) const { + return const_cast(impl_)->waitForTime(abstime); +} + +int Monitor::waitForTimeRelative(int64_t timeout_ms) const { + return const_cast(impl_)->waitForTimeRelative(timeout_ms); +} + +int Monitor::waitForever() const { + return const_cast(impl_)->waitForever(); +} + +void Monitor::notify() const { const_cast(impl_)->notify(); } + +void Monitor::notifyAll() const { const_cast(impl_)->notifyAll(); } + +}}} // apache::thrift::concurrency diff --git a/sg_agent/thrid_party/thrift/include/concurrency/BoostMutex.cpp b/sg_agent/thrid_party/thrift/include/concurrency/BoostMutex.cpp new file mode 100644 index 0000000..a7b5c37 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/BoostMutex.cpp @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "Mutex.h" +#include "Util.h" + +#include +#include +#include +#include + +namespace apache { namespace thrift { namespace concurrency { + +/** + * Implementation of Mutex class using boost interprocess mutex + * + * @version $Id:$ + */ +class Mutex::impl : public boost::timed_mutex { +}; + +Mutex::Mutex(Initializer init) : impl_(new Mutex::impl()) {} + +void* Mutex::getUnderlyingImpl() const { return impl_.get(); } + +void Mutex::lock() const { impl_->lock(); } + +bool Mutex::trylock() const { return impl_->try_lock(); } + +bool Mutex::timedlock(int64_t ms) const { return impl_->timed_lock(boost::get_system_time()+boost::posix_time::milliseconds(ms)); } + +void Mutex::unlock() const { impl_->unlock(); } + +void Mutex::DEFAULT_INITIALIZER(void* arg) { +} + +}}} // apache::thrift::concurrency + diff --git a/sg_agent/thrid_party/thrift/include/concurrency/BoostThreadFactory.cpp b/sg_agent/thrid_party/thrift/include/concurrency/BoostThreadFactory.cpp new file mode 100644 index 0000000..5551528 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/BoostThreadFactory.cpp @@ -0,0 +1,182 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "BoostThreadFactory.h" +#include "Exception.h" + +#include + +#include +#include + +namespace apache { namespace thrift { namespace concurrency { + +using boost::shared_ptr; +using boost::weak_ptr; + +/** + * The boost thread class. + * + * @version $Id:$ + */ +class BoostThread: public Thread { + public: + + enum STATE { + uninitialized, + starting, + started, + stopping, + stopped + }; + + static void* threadMain(void* arg); + + private: + std::auto_ptr thread_; + STATE state_; + weak_ptr self_; + bool detached_; + + public: + + BoostThread(bool detached, shared_ptr runnable) : + state_(uninitialized), + detached_(detached) { + this->Thread::runnable(runnable); + } + + ~BoostThread() { + if(!detached_) { + try { + join(); + } catch(...) { + // We're really hosed. + } + } + } + + void start() { + if (state_ != uninitialized) { + return; + } + + // Create reference + shared_ptr* selfRef = new shared_ptr(); + *selfRef = self_.lock(); + + thread_ = std::auto_ptr(new boost::thread(boost::bind(threadMain, (void*)selfRef))); + + if(detached_) + thread_->detach(); + + state_ = starting; + } + + void join() { + if (!detached_ && state_ != uninitialized) { + thread_->join(); + } + } + + Thread::id_t getId() { + return thread_.get() ? thread_->get_id() : boost::thread::id(); + } + + shared_ptr runnable() const { return Thread::runnable(); } + + void runnable(shared_ptr value) { Thread::runnable(value); } + + void weakRef(shared_ptr self) { + assert(self.get() == this); + self_ = weak_ptr(self); + } +}; + +void* BoostThread::threadMain(void* arg) { + shared_ptr thread = *(shared_ptr*)arg; + delete reinterpret_cast*>(arg); + + if (thread == NULL) { + return (void*)0; + } + + if (thread->state_ != starting) { + return (void*)0; + } + + thread->state_ = started; + thread->runnable()->run(); + + if (thread->state_ != stopping && thread->state_ != stopped) { + thread->state_ = stopping; + } + return (void*)0; +} + +/** + * POSIX Thread factory implementation + */ +class BoostThreadFactory::Impl { + + private: + bool detached_; + + public: + + Impl(bool detached) : + detached_(detached) {} + + /** + * Creates a new POSIX thread to run the runnable object + * + * @param runnable A runnable object + */ + shared_ptr newThread(shared_ptr runnable) const { + shared_ptr result = shared_ptr(new BoostThread(detached_, runnable)); + result->weakRef(result); + runnable->thread(result); + return result; + } + + bool isDetached() const { return detached_; } + + void setDetached(bool value) { detached_ = value; } + + Thread::id_t getCurrentThreadId() const { + return boost::this_thread::get_id(); + } + +}; + +BoostThreadFactory::BoostThreadFactory(bool detached) : + impl_(new BoostThreadFactory::Impl(detached)) {} + +shared_ptr BoostThreadFactory::newThread(shared_ptr runnable) const { return impl_->newThread(runnable); } + +bool BoostThreadFactory::isDetached() const { return impl_->isDetached(); } + +void BoostThreadFactory::setDetached(bool value) { impl_->setDetached(value); } + +Thread::id_t BoostThreadFactory::getCurrentThreadId() const { return impl_->getCurrentThreadId(); } + +}}} // apache::thrift::concurrency diff --git a/sg_agent/thrid_party/thrift/include/concurrency/BoostThreadFactory.h b/sg_agent/thrid_party/thrift/include/concurrency/BoostThreadFactory.h new file mode 100644 index 0000000..a466705 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/BoostThreadFactory.h @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_CONCURRENCY_BOOSTTHREADFACTORY_H_ +#define _THRIFT_CONCURRENCY_BOOSTTHREADFACTORY_H_ 1 + +#include "Thread.h" + +#include + +namespace apache { namespace thrift { namespace concurrency { + +/** + * A thread factory to create posix threads + * + * @version $Id:$ + */ +class BoostThreadFactory : public ThreadFactory { + + public: + + /** + * Boost thread factory. All threads created by a factory are reference-counted + * via boost::shared_ptr and boost::weak_ptr. The factory guarantees that threads and + * the Runnable tasks they host will be properly cleaned up once the last strong reference + * to both is given up. + * + * Threads are created with the specified boost policy, priority, stack-size. A detachable thread is not + * joinable. + * + * By default threads are not joinable. + */ + + BoostThreadFactory(bool detached=true); + + // From ThreadFactory; + boost::shared_ptr newThread(boost::shared_ptr runnable) const; + + // From ThreadFactory; + Thread::id_t getCurrentThreadId() const; + + /** + * Sets detached mode of threads + */ + virtual void setDetached(bool detached); + + /** + * Gets current detached mode + */ + virtual bool isDetached() const; + +private: + class Impl; + boost::shared_ptr impl_; +}; + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_BOOSTTHREADFACTORY_H_ diff --git a/sg_agent/thrid_party/thrift/include/concurrency/Exception.h b/sg_agent/thrid_party/thrift/include/concurrency/Exception.h new file mode 100644 index 0000000..06ba0d3 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/Exception.h @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_CONCURRENCY_EXCEPTION_H_ +#define _THRIFT_CONCURRENCY_EXCEPTION_H_ 1 + +#include +#include + +namespace apache { namespace thrift { namespace concurrency { + +class NoSuchTaskException : public apache::thrift::TException {}; + +class UncancellableTaskException : public apache::thrift::TException {}; + +class InvalidArgumentException : public apache::thrift::TException {}; + +class IllegalStateException : public apache::thrift::TException { +public: + IllegalStateException() {} + IllegalStateException(const std::string& message) : TException(message) {} +}; + +class TimedOutException : public apache::thrift::TException { +public: + TimedOutException():TException("TimedOutException"){}; + TimedOutException(const std::string& message ) : + TException(message) {} +}; + +class TooManyPendingTasksException : public apache::thrift::TException { +public: + TooManyPendingTasksException():TException("TooManyPendingTasksException"){}; + TooManyPendingTasksException(const std::string& message ) : + TException(message) {} +}; + +class SystemResourceException : public apache::thrift::TException { +public: + SystemResourceException() {} + + SystemResourceException(const std::string& message) : + TException(message) {} +}; + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_EXCEPTION_H_ diff --git a/sg_agent/thrid_party/thrift/include/concurrency/FunctionRunner.h b/sg_agent/thrid_party/thrift/include/concurrency/FunctionRunner.h new file mode 100644 index 0000000..5a8cd3d --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/FunctionRunner.h @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H +#define _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H 1 + +#include +#include "thrift/lib/cpp/concurrency/Thread.h" + +namespace apache { namespace thrift { namespace concurrency { + +/** + * Convenient implementation of Runnable that will execute arbitrary callbacks. + * Interfaces are provided to accept both a generic 'void(void)' callback, and + * a 'void* (void*)' pthread_create-style callback. + * + * Example use: + * void* my_thread_main(void* arg); + * shared_ptr factory = ...; + * // To create a thread that executes my_thread_main once: + * shared_ptr thread = + * factory->newThread(shared_ptr( + * new FunctionRunner(my_thread_main, some_argument))); + * thread->start(); + * + * bool A::foo(); + * A* a = new A(); + * // To create a thread that executes a.foo() every 100 milliseconds: + * factory->newThread(shared_ptr( + * new FunctionRunner(std::tr1::bind(&A::foo, a), 100)))->start(); + * + */ + +class FunctionRunner : public Runnable { + public: + // This is the type of callback 'pthread_create()' expects. + typedef void* (*PthreadFuncPtr)(void *arg); + // This a fully-generic void(void) callback for custom bindings. + typedef std::tr1::function VoidFunc; + + typedef std::tr1::function BoolFunc; + + /** + * Given a 'pthread_create' style callback, this FunctionRunner will + * execute the given callback. Note that the 'void*' return value is ignored. + */ + FunctionRunner(PthreadFuncPtr func, void* arg) + : func_(std::tr1::bind(func, arg)), repFunc_(0) + { } + + /** + * Given a generic callback, this FunctionRunner will execute it. + */ + FunctionRunner(const VoidFunc& cob) + : func_(cob), repFunc_(0) + { } + + /** + * Given a bool foo(...) type callback, FunctionRunner will execute + * the callback repeatedly with 'intervalMs' milliseconds between the calls, + * until it returns false. Note that the actual interval between calls will + * be intervalMs plus execution time of the callback. + */ + FunctionRunner(const BoolFunc& cob, int intervalMs) + : func_(0), repFunc_(cob), intervalMs_(intervalMs) + { } + + void run() { + if (repFunc_) { + while(repFunc_()) { + usleep(intervalMs_*1000); + } + } else { + func_(); + } + } + + private: + VoidFunc func_; + BoolFunc repFunc_; + int intervalMs_; +}; + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_FUNCTION_RUNNER_H diff --git a/sg_agent/thrid_party/thrift/include/concurrency/Monitor.cpp b/sg_agent/thrid_party/thrift/include/concurrency/Monitor.cpp new file mode 100644 index 0000000..3d6440c --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/Monitor.cpp @@ -0,0 +1,208 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "Monitor.h" +#include "Exception.h" +#include "Util.h" + +#include + +#include +#include + +#include + +#include + +namespace apache { namespace thrift { namespace concurrency { + +using boost::scoped_ptr; + +/** + * Monitor implementation using the POSIX pthread library + * + * @version $Id:$ + */ +class Monitor::Impl { + + public: + + Impl() + : ownedMutex_(new Mutex()), + mutex_(NULL), + condInitialized_(false) { + init(ownedMutex_.get()); + } + + Impl(Mutex* mutex) + : mutex_(NULL), + condInitialized_(false) { + init(mutex); + } + + Impl(Monitor* monitor) + : mutex_(NULL), + condInitialized_(false) { + init(&(monitor->mutex())); + } + + ~Impl() { cleanup(); } + + Mutex& mutex() { return *mutex_; } + void lock() { mutex().lock(); } + void unlock() { mutex().unlock(); } + + /** + * Exception-throwing version of waitForTimeRelative(), called simply + * wait(int64) for historical reasons. Timeout is in milliseconds. + * + * If the condition occurs, this function returns cleanly; on timeout or + * error an exception is thrown. + */ + void wait(int64_t timeout_ms) const { + int result = waitForTimeRelative(timeout_ms); + if (result == ETIMEDOUT) { + // pthread_cond_timedwait has been observed to return early on + // various platforms, so comment out this assert. + //assert(Util::currentTime() >= (now + timeout)); + throw TimedOutException(); + } else if (result != 0) { + throw TException( + "pthread_cond_wait() or pthread_cond_timedwait() failed"); + } + } + + /** + * Waits until the specified timeout in milliseconds for the condition to + * occur, or waits forever if timeout_ms == 0. + * + * Returns 0 if condition occurs, ETIMEDOUT on timeout, or an error code. + */ + int waitForTimeRelative(int64_t timeout_ms) const { + if (timeout_ms == 0LL) { + return waitForever(); + } + + struct timespec abstime; + Util::toTimespec(abstime, Util::currentTime() + timeout_ms); + return waitForTime(&abstime); + } + + /** + * Waits until the absolute time specified using struct timespec. + * Returns 0 if condition occurs, ETIMEDOUT on timeout, or an error code. + */ + int waitForTime(const timespec* abstime) const { + assert(mutex_); + pthread_mutex_t* mutexImpl = + reinterpret_cast(mutex_->getUnderlyingImpl()); + assert(mutexImpl); + + // XXX Need to assert that caller owns mutex + return pthread_cond_timedwait(&pthread_cond_, + mutexImpl, + abstime); + } + + /** + * Waits forever until the condition occurs. + * Returns 0 if condition occurs, or an error code otherwise. + */ + int waitForever() const { + assert(mutex_); + pthread_mutex_t* mutexImpl = + reinterpret_cast(mutex_->getUnderlyingImpl()); + assert(mutexImpl); + return pthread_cond_wait(&pthread_cond_, mutexImpl); + } + + + void notify() { + // XXX Need to assert that caller owns mutex + int iret = pthread_cond_signal(&pthread_cond_); + assert(iret == 0); + } + + void notifyAll() { + // XXX Need to assert that caller owns mutex + int iret = pthread_cond_broadcast(&pthread_cond_); + assert(iret == 0); + } + + private: + + void init(Mutex* mutex) { + mutex_ = mutex; + + if (pthread_cond_init(&pthread_cond_, NULL) == 0) { + condInitialized_ = true; + } + + if (!condInitialized_) { + cleanup(); + throw SystemResourceException(); + } + } + + void cleanup() { + if (condInitialized_) { + condInitialized_ = false; + int iret = pthread_cond_destroy(&pthread_cond_); + assert(iret == 0); + } + } + + scoped_ptr ownedMutex_; + Mutex* mutex_; + + mutable pthread_cond_t pthread_cond_; + mutable bool condInitialized_; +}; + +Monitor::Monitor() : impl_(new Monitor::Impl()) {} +Monitor::Monitor(Mutex* mutex) : impl_(new Monitor::Impl(mutex)) {} +Monitor::Monitor(Monitor* monitor) : impl_(new Monitor::Impl(monitor)) {} + +Monitor::~Monitor() { delete impl_; } + +Mutex& Monitor::mutex() const { return impl_->mutex(); } + +void Monitor::lock() const { impl_->lock(); } + +void Monitor::unlock() const { impl_->unlock(); } + +void Monitor::wait(int64_t timeout) const { impl_->wait(timeout); } + +int Monitor::waitForTime(const timespec* abstime) const { + return impl_->waitForTime(abstime); +} + +int Monitor::waitForTimeRelative(int64_t timeout_ms) const { + return impl_->waitForTimeRelative(timeout_ms); +} + +int Monitor::waitForever() const { + return impl_->waitForever(); +} + +void Monitor::notify() const { impl_->notify(); } + +void Monitor::notifyAll() const { impl_->notifyAll(); } + +}}} // apache::thrift::concurrency diff --git a/sg_agent/thrid_party/thrift/include/concurrency/Monitor.h b/sg_agent/thrid_party/thrift/include/concurrency/Monitor.h new file mode 100644 index 0000000..aa6fe93 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/Monitor.h @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_CONCURRENCY_MONITOR_H_ +#define _THRIFT_CONCURRENCY_MONITOR_H_ 1 + +#include "Exception.h" +#include "Mutex.h" + +#include + + +namespace apache { namespace thrift { namespace concurrency { + +/** + * A monitor is a combination mutex and condition-event. Waiting and + * notifying condition events requires that the caller own the mutex. Mutex + * lock and unlock operations can be performed independently of condition + * events. This is more or less analogous to java.lang.Object multi-thread + * operations. + * + * Note the Monitor can create a new, internal mutex; alternatively, a + * separate Mutex can be passed in and the Monitor will re-use it without + * taking ownership. It's the user's responsibility to make sure that the + * Mutex is not deallocated before the Monitor. + * + * Note that all methods are const. Monitors implement logical constness, not + * bit constness. This allows const methods to call monitor methods without + * needing to cast away constness or change to non-const signatures. + * + * @version $Id:$ + */ +class Monitor : boost::noncopyable { + public: + /** Creates a new mutex, and takes ownership of it. */ + Monitor(); + + /** Uses the provided mutex without taking ownership. */ + explicit Monitor(Mutex* mutex); + + /** Uses the mutex inside the provided Monitor without taking ownership. */ + explicit Monitor(Monitor* monitor); + + /** Deallocates the mutex only if we own it. */ + virtual ~Monitor(); + + Mutex& mutex() const; + + virtual void lock() const; + + virtual void unlock() const; + + /** + * Waits a maximum of the specified timeout in milliseconds for the condition + * to occur, or waits forever if timeout_ms == 0. + * + * Returns 0 if condition occurs, ETIMEDOUT on timeout, or an error code. + */ + int waitForTimeRelative(int64_t timeout_ms) const; + + /** + * Waits until the absolute time specified using struct timespec. + * Returns 0 if condition occurs, ETIMEDOUT on timeout, or an error code. + */ + int waitForTime(const timespec* abstime) const; + + /** + * Waits forever until the condition occurs. + * Returns 0 if condition occurs, or an error code otherwise. + */ + int waitForever() const; + + /** + * Exception-throwing version of waitForTimeRelative(), called simply + * wait(int64) for historical reasons. Timeout is in milliseconds. + * + * If the condition occurs, this function returns cleanly; on timeout or + * error an exception is thrown. + */ + void wait(int64_t timeout_ms = 0LL) const; + + + /** Wakes up one thread waiting on this monitor. */ + virtual void notify() const; + + /** Wakes up all waiting threads on this monitor. */ + virtual void notifyAll() const; + + private: + + class Impl; + + Impl* impl_; +}; + +class Synchronized { + public: + Synchronized(const Monitor* monitor) : g(monitor->mutex()) { } + Synchronized(const Monitor& monitor) : g(monitor.mutex()) { } + + private: + Guard g; +}; + + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_MONITOR_H_ diff --git a/sg_agent/thrid_party/thrift/include/concurrency/Mutex.cpp b/sg_agent/thrid_party/thrift/include/concurrency/Mutex.cpp new file mode 100644 index 0000000..0cfa0ad --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/Mutex.cpp @@ -0,0 +1,303 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "Mutex.h" +#include "Util.h" + +#include +#ifdef HAVE_PTHREAD_H +#include +#endif +#include + +using boost::shared_ptr; + +namespace apache { namespace thrift { namespace concurrency { + +#ifndef THRIFT_NO_CONTENTION_PROFILING + +static sig_atomic_t mutexProfilingSampleRate = 0; +static MutexWaitCallback mutexProfilingCallback = 0; + +volatile static sig_atomic_t mutexProfilingCounter = 0; + +void enableMutexProfiling(int32_t profilingSampleRate, + MutexWaitCallback callback) { + mutexProfilingSampleRate = profilingSampleRate; + mutexProfilingCallback = callback; +} + +#define PROFILE_MUTEX_START_LOCK() \ + int64_t _lock_startTime = maybeGetProfilingStartTime(); + +#define PROFILE_MUTEX_NOT_LOCKED() \ + do { \ + if (_lock_startTime > 0) { \ + int64_t endTime = Util::currentTimeUsec(); \ + (*mutexProfilingCallback)(this, endTime - _lock_startTime); \ + } \ + } while (0) + +#define PROFILE_MUTEX_LOCKED() \ + do { \ + profileTime_ = _lock_startTime; \ + if (profileTime_ > 0) { \ + profileTime_ = Util::currentTimeUsec() - profileTime_; \ + } \ + } while (0) + +#define PROFILE_MUTEX_START_UNLOCK() \ + int64_t _temp_profileTime = profileTime_; \ + profileTime_ = 0; + +#define PROFILE_MUTEX_UNLOCKED() \ + do { \ + if (_temp_profileTime > 0) { \ + (*mutexProfilingCallback)(this, _temp_profileTime); \ + } \ + } while (0) + +static inline int64_t maybeGetProfilingStartTime() { + if (mutexProfilingSampleRate && mutexProfilingCallback) { + // This block is unsynchronized, but should produce a reasonable sampling + // rate on most architectures. The main race conditions are the gap + // between the decrement and the test, the non-atomicity of decrement, and + // potential caching of different values at different CPUs. + // + // - if two decrements race, the likeliest result is that the counter + // decrements slowly (perhaps much more slowly) than intended. + // + // - many threads could potentially decrement before resetting the counter + // to its large value, causing each additional incoming thread to + // profile every call. This situation is unlikely to persist for long + // as the critical gap is quite short, but profiling could be bursty. + sig_atomic_t localValue = --mutexProfilingCounter; + if (localValue <= 0) { + mutexProfilingCounter = mutexProfilingSampleRate; + return Util::currentTimeUsec(); + } + } + + return 0; +} + +#else +# define PROFILE_MUTEX_START_LOCK() +# define PROFILE_MUTEX_NOT_LOCKED() +# define PROFILE_MUTEX_LOCKED() +# define PROFILE_MUTEX_START_UNLOCK() +# define PROFILE_MUTEX_UNLOCKED() +#endif // THRIFT_NO_CONTENTION_PROFILING + +/** + * Implementation of Mutex class using POSIX mutex + * + * @version $Id:$ + */ +class Mutex::impl { + public: + impl(Initializer init) : initialized_(false) { +#ifndef THRIFT_NO_CONTENTION_PROFILING + profileTime_ = 0; +#endif + init(&pthread_mutex_); + initialized_ = true; + } + + ~impl() { + if (initialized_) { + initialized_ = false; + int ret = pthread_mutex_destroy(&pthread_mutex_); + assert(ret == 0); + } + } + + void lock() const { + PROFILE_MUTEX_START_LOCK(); + pthread_mutex_lock(&pthread_mutex_); + PROFILE_MUTEX_LOCKED(); + } + + bool trylock() const { return (0 == pthread_mutex_trylock(&pthread_mutex_)); } + + bool timedlock(int64_t milliseconds) const { +#if defined(_POSIX_TIMEOUTS) && _POSIX_TIMEOUTS >= 200112L + PROFILE_MUTEX_START_LOCK(); + + struct timespec ts; + Util::toTimespec(ts, milliseconds); + int ret = pthread_mutex_timedlock(&pthread_mutex_, &ts); + if (ret == 0) { + PROFILE_MUTEX_LOCKED(); + return true; + } + + PROFILE_MUTEX_NOT_LOCKED(); + return false; +#else + // If pthread_mutex_timedlock isn't supported, the safest thing to do + // is just do a nonblocking trylock. + return trylock(); +#endif + } + + void unlock() const { + PROFILE_MUTEX_START_UNLOCK(); + pthread_mutex_unlock(&pthread_mutex_); + PROFILE_MUTEX_UNLOCKED(); + } + + void* getUnderlyingImpl() const { return (void*) &pthread_mutex_; } + + private: + mutable pthread_mutex_t pthread_mutex_; + mutable bool initialized_; +#ifndef THRIFT_NO_CONTENTION_PROFILING + mutable int64_t profileTime_; +#endif +}; + +Mutex::Mutex(Initializer init) : impl_(new Mutex::impl(init)) {} + +void* Mutex::getUnderlyingImpl() const { return impl_->getUnderlyingImpl(); } + +void Mutex::lock() const { impl_->lock(); } + +bool Mutex::trylock() const { return impl_->trylock(); } + +bool Mutex::timedlock(int64_t ms) const { return impl_->timedlock(ms); } + +void Mutex::unlock() const { impl_->unlock(); } + +void Mutex::DEFAULT_INITIALIZER(void* arg) { + pthread_mutex_t* pthread_mutex = (pthread_mutex_t*)arg; + int ret = pthread_mutex_init(pthread_mutex, NULL); + assert(ret == 0); +} + +#if defined(PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP) || defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) +static void init_with_kind(pthread_mutex_t* mutex, int kind) { + pthread_mutexattr_t mutexattr; + int ret = pthread_mutexattr_init(&mutexattr); + assert(ret == 0); + + // Apparently, this can fail. Should we really be aborting? + ret = pthread_mutexattr_settype(&mutexattr, kind); + assert(ret == 0); + + ret = pthread_mutex_init(mutex, &mutexattr); + assert(ret == 0); + + ret = pthread_mutexattr_destroy(&mutexattr); + assert(ret == 0); +} +#endif + +#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP +void Mutex::ADAPTIVE_INITIALIZER(void* arg) { + // From mysql source: mysys/my_thr_init.c + // Set mutex type to "fast" a.k.a "adaptive" + // + // In this case the thread may steal the mutex from some other thread + // that is waiting for the same mutex. This will save us some + // context switches but may cause a thread to 'starve forever' while + // waiting for the mutex (not likely if the code within the mutex is + // short). + init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_ADAPTIVE_NP); +} +#endif + +#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP +void Mutex::RECURSIVE_INITIALIZER(void* arg) { + init_with_kind((pthread_mutex_t*)arg, PTHREAD_MUTEX_RECURSIVE_NP); +} +#endif + + +/** + * Implementation of ReadWriteMutex class using POSIX rw lock + * + * @version $Id:$ + */ +class ReadWriteMutex::impl { +public: + impl() : initialized_(false) { +#ifndef THRIFT_NO_CONTENTION_PROFILING + profileTime_ = 0; +#endif + int ret = pthread_rwlock_init(&rw_lock_, NULL); + assert(ret == 0); + initialized_ = true; + } + + ~impl() { + if(initialized_) { + initialized_ = false; + int ret = pthread_rwlock_destroy(&rw_lock_); + assert(ret == 0); + } + } + + void acquireRead() const { + PROFILE_MUTEX_START_LOCK(); + pthread_rwlock_rdlock(&rw_lock_); + PROFILE_MUTEX_NOT_LOCKED(); // not exclusive, so use not-locked path + } + + void acquireWrite() const { + PROFILE_MUTEX_START_LOCK(); + pthread_rwlock_wrlock(&rw_lock_); + PROFILE_MUTEX_LOCKED(); + } + + bool attemptRead() const { return pthread_rwlock_tryrdlock(&rw_lock_); } + + bool attemptWrite() const { return pthread_rwlock_trywrlock(&rw_lock_); } + + void release() const { + PROFILE_MUTEX_START_UNLOCK(); + pthread_rwlock_unlock(&rw_lock_); + PROFILE_MUTEX_UNLOCKED(); + } + +private: + mutable pthread_rwlock_t rw_lock_; + mutable bool initialized_; +#ifndef THRIFT_NO_CONTENTION_PROFILING + mutable int64_t profileTime_; +#endif +}; + +ReadWriteMutex::ReadWriteMutex() : impl_(new ReadWriteMutex::impl()) {} + +void ReadWriteMutex::acquireRead() const { impl_->acquireRead(); } + +void ReadWriteMutex::acquireWrite() const { impl_->acquireWrite(); } + +bool ReadWriteMutex::attemptRead() const { return impl_->attemptRead(); } + +bool ReadWriteMutex::attemptWrite() const { return impl_->attemptWrite(); } + +void ReadWriteMutex::release() const { impl_->release(); } + +}}} // apache::thrift::concurrency + diff --git a/sg_agent/thrid_party/thrift/include/concurrency/Mutex.h b/sg_agent/thrid_party/thrift/include/concurrency/Mutex.h new file mode 100644 index 0000000..847aaf6 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/Mutex.h @@ -0,0 +1,178 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_CONCURRENCY_MUTEX_H_ +#define _THRIFT_CONCURRENCY_MUTEX_H_ 1 + +#include +#include + +namespace apache { namespace thrift { namespace concurrency { + +#ifndef THRIFT_NO_CONTENTION_PROFILING + +/** + * Determines if the Thrift Mutex and ReadWriteMutex classes will attempt to + * profile their blocking acquire methods. If this value is set to non-zero, + * Thrift will attempt to invoke the callback once every profilingSampleRate + * times. However, as the sampling is not synchronized the rate is not + * guranateed, and could be subject to big bursts and swings. Please ensure + * your sampling callback is as performant as your application requires. + * + * The callback will get called with the wait time taken to lock the mutex in + * usec and a (void*) that uniquely identifies the Mutex (or ReadWriteMutex) + * being locked. + * + * The enableMutexProfiling() function is unsynchronized; calling this function + * while profiling is already enabled may result in race conditions. On + * architectures where a pointer assignment is atomic, this is safe but there + * is no guarantee threads will agree on a single callback within any + * particular time period. + */ +typedef void (*MutexWaitCallback)(const void* id, int64_t waitTimeMicros); +void enableMutexProfiling(int32_t profilingSampleRate, + MutexWaitCallback callback); + +#endif + +/** + * A simple mutex class + * + * @version $Id:$ + */ +class Mutex { + public: + typedef void (*Initializer)(void*); + + Mutex(Initializer init = DEFAULT_INITIALIZER); + virtual ~Mutex() {} + virtual void lock() const; + virtual bool trylock() const; + virtual bool timedlock(int64_t milliseconds) const; + virtual void unlock() const; + + void* getUnderlyingImpl() const; + + static void DEFAULT_INITIALIZER(void*); + static void ADAPTIVE_INITIALIZER(void*); + static void RECURSIVE_INITIALIZER(void*); + + private: + + class impl; + boost::shared_ptr impl_; +}; + +class ReadWriteMutex { +public: + ReadWriteMutex(); + virtual ~ReadWriteMutex() {} + + // these get the lock and block until it is done successfully + virtual void acquireRead() const; + virtual void acquireWrite() const; + + // these attempt to get the lock, returning false immediately if they fail + virtual bool attemptRead() const; + virtual bool attemptWrite() const; + + // this releases both read and write locks + virtual void release() const; + +private: + + class impl; + boost::shared_ptr impl_; +}; + +class Guard : boost::noncopyable { + public: + Guard(const Mutex& value, int64_t timeout = 0) : mutex_(&value) { + if (timeout == 0) { + value.lock(); + } else if (timeout < 0) { + if (!value.trylock()) { + mutex_ = NULL; + } + } else { + if (!value.timedlock(timeout)) { + mutex_ = NULL; + } + } + } + ~Guard() { + if (mutex_) { + mutex_->unlock(); + } + } + + operator bool() const { + return (mutex_ != NULL); + } + + private: + const Mutex* mutex_; +}; + +// Can be used as second argument to RWGuard to make code more readable +// as to whether we're doing acquireRead() or acquireWrite(). +enum RWGuardType { + RW_READ = 0, + RW_WRITE = 1 +}; + + +class RWGuard : boost::noncopyable { + public: + RWGuard(const ReadWriteMutex& value, bool write = false) + : rw_mutex_(value) { + if (write) { + rw_mutex_.acquireWrite(); + } else { + rw_mutex_.acquireRead(); + } + } + + RWGuard(const ReadWriteMutex& value, RWGuardType type) + : rw_mutex_(value) { + if (type == RW_WRITE) { + rw_mutex_.acquireWrite(); + } else { + rw_mutex_.acquireRead(); + } + } + ~RWGuard() { + rw_mutex_.release(); + } + private: + const ReadWriteMutex& rw_mutex_; +}; + + +// A little hack to prevent someone from trying to do "Guard(m);" +// Such a use is invalid because the temporary Guard object is +// destroyed at the end of the line, releasing the lock. +// Sorry for polluting the global namespace, but I think it's worth it. +#define Guard(m) incorrect_use_of_Guard(m) +#define RWGuard(m) incorrect_use_of_RWGuard(m) + + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_MUTEX_H_ diff --git a/sg_agent/thrid_party/thrift/include/concurrency/PlatformThreadFactory.h b/sg_agent/thrid_party/thrift/include/concurrency/PlatformThreadFactory.h new file mode 100644 index 0000000..9f053a0 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/PlatformThreadFactory.h @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_CONCURRENCY_PLATFORMTHREADFACTORY_H_ +#define _THRIFT_CONCURRENCY_PLATFORMTHREADFACTORY_H_ 1 + +#ifndef USE_BOOST_THREAD +# include +#else +# include +#endif + +namespace apache { namespace thrift { namespace concurrency { + +#ifndef USE_BOOST_THREAD + typedef PosixThreadFactory PlatformThreadFactory; +#include +#else + typedef BoostThreadFactory PlatformThreadFactory; +#endif + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_PLATFORMTHREADFACTORY_H_ diff --git a/sg_agent/thrid_party/thrift/include/concurrency/PosixThreadFactory.cpp b/sg_agent/thrid_party/thrift/include/concurrency/PosixThreadFactory.cpp new file mode 100644 index 0000000..70204f1 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/PosixThreadFactory.cpp @@ -0,0 +1,333 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "PosixThreadFactory.h" +#include "Exception.h" + +#if GOOGLE_PERFTOOLS_REGISTER_THREAD +# include +#endif + +#include +#include + +#include + +#include + +namespace apache { namespace thrift { namespace concurrency { + +using boost::shared_ptr; +using boost::weak_ptr; + +/** + * The POSIX thread class. + * + * @version $Id:$ + */ +class PthreadThread: public Thread { + public: + + enum STATE { + uninitialized, + starting, + started, + stopping, + stopped + }; + + static const int MB = 1024 * 1024; + + static void* threadMain(void* arg); + + private: + pthread_t pthread_; + STATE state_; + int policy_; + int priority_; + int stackSize_; + weak_ptr self_; + bool detached_; + + public: + + PthreadThread(int policy, int priority, int stackSize, bool detached, shared_ptr runnable) : + +#ifndef _WIN32 + pthread_(0), +#endif // _WIN32 + + state_(uninitialized), + policy_(policy), + priority_(priority), + stackSize_(stackSize), + detached_(detached) { + + this->Thread::runnable(runnable); + } + + ~PthreadThread() { + /* Nothing references this thread, if is is not detached, do a join + now, otherwise the thread-id and, possibly, other resources will + be leaked. */ + if(!detached_) { + try { + join(); + } catch(...) { + // We're really hosed. + } + } + } + + void start() { + if (state_ != uninitialized) { + return; + } + + pthread_attr_t thread_attr; + if (pthread_attr_init(&thread_attr) != 0) { + throw SystemResourceException("pthread_attr_init failed"); + } + + if(pthread_attr_setdetachstate(&thread_attr, + detached_ ? + PTHREAD_CREATE_DETACHED : + PTHREAD_CREATE_JOINABLE) != 0) { + throw SystemResourceException("pthread_attr_setdetachstate failed"); + } + + // Set thread stack size + if (pthread_attr_setstacksize(&thread_attr, MB * stackSize_) != 0) { + throw SystemResourceException("pthread_attr_setstacksize failed"); + } + + // Set thread policy + #ifdef _WIN32 + //WIN32 Pthread implementation doesn't seem to support sheduling policies other then PosixThreadFactory::OTHER - runtime error + policy_ = PosixThreadFactory::OTHER; + #endif + + if (pthread_attr_setschedpolicy(&thread_attr, policy_) != 0) { + throw SystemResourceException("pthread_attr_setschedpolicy failed"); + } + + struct sched_param sched_param; + sched_param.sched_priority = priority_; + + // Set thread priority + if (pthread_attr_setschedparam(&thread_attr, &sched_param) != 0) { + throw SystemResourceException("pthread_attr_setschedparam failed"); + } + + // Create reference + shared_ptr* selfRef = new shared_ptr(); + *selfRef = self_.lock(); + + state_ = starting; + + if (pthread_create(&pthread_, &thread_attr, threadMain, (void*)selfRef) != 0) { + throw SystemResourceException("pthread_create failed"); + } + } + + void join() { + if (!detached_ && state_ != uninitialized) { + void* ignore; + /* XXX + If join fails it is most likely due to the fact + that the last reference was the thread itself and cannot + join. This results in leaked threads and will eventually + cause the process to run out of thread resources. + We're beyond the point of throwing an exception. Not clear how + best to handle this. */ + detached_ = pthread_join(pthread_, &ignore) == 0; + } + } + + Thread::id_t getId() { + +#ifndef _WIN32 + return (Thread::id_t)pthread_; +#else + return (Thread::id_t)pthread_.p; +#endif // _WIN32 + } + + shared_ptr runnable() const { return Thread::runnable(); } + + void runnable(shared_ptr value) { Thread::runnable(value); } + + void weakRef(shared_ptr self) { + assert(self.get() == this); + self_ = weak_ptr(self); + } +}; + +void* PthreadThread::threadMain(void* arg) { + shared_ptr thread = *(shared_ptr*)arg; + delete reinterpret_cast*>(arg); + + if (thread == NULL) { + return (void*)0; + } + + if (thread->state_ != starting) { + return (void*)0; + } + +#if GOOGLE_PERFTOOLS_REGISTER_THREAD + ProfilerRegisterThread(); +#endif + + thread->state_ = started; + thread->runnable()->run(); + if (thread->state_ != stopping && thread->state_ != stopped) { + thread->state_ = stopping; + } + + return (void*)0; +} + +/** + * POSIX Thread factory implementation + */ +class PosixThreadFactory::Impl { + + private: + POLICY policy_; + PRIORITY priority_; + int stackSize_; + bool detached_; + + /** + * Converts generic posix thread schedule policy enums into pthread + * API values. + */ + static int toPthreadPolicy(POLICY policy) { + switch (policy) { + case OTHER: + return SCHED_OTHER; + case FIFO: + return SCHED_FIFO; + case ROUND_ROBIN: + return SCHED_RR; + } + return SCHED_OTHER; + } + + /** + * Converts relative thread priorities to absolute value based on posix + * thread scheduler policy + * + * The idea is simply to divide up the priority range for the given policy + * into the correpsonding relative priority level (lowest..highest) and + * then pro-rate accordingly. + */ + static int toPthreadPriority(POLICY policy, PRIORITY priority) { + int pthread_policy = toPthreadPolicy(policy); + int min_priority = 0; + int max_priority = 0; +#ifdef HAVE_SCHED_GET_PRIORITY_MIN + min_priority = sched_get_priority_min(pthread_policy); +#endif +#ifdef HAVE_SCHED_GET_PRIORITY_MAX + max_priority = sched_get_priority_max(pthread_policy); +#endif + int quanta = (HIGHEST - LOWEST) + 1; + float stepsperquanta = (float)(max_priority - min_priority) / quanta; + + if (priority <= HIGHEST) { + return (int)(min_priority + stepsperquanta * priority); + } else { + // should never get here for priority increments. + assert(false); + return (int)(min_priority + stepsperquanta * NORMAL); + } + } + + public: + + Impl(POLICY policy, PRIORITY priority, int stackSize, bool detached) : + policy_(policy), + priority_(priority), + stackSize_(stackSize), + detached_(detached) {} + + /** + * Creates a new POSIX thread to run the runnable object + * + * @param runnable A runnable object + */ + shared_ptr newThread(shared_ptr runnable) const { + shared_ptr result = shared_ptr(new PthreadThread(toPthreadPolicy(policy_), toPthreadPriority(policy_, priority_), stackSize_, detached_, runnable)); + result->weakRef(result); + runnable->thread(result); + return result; + } + + int getStackSize() const { return stackSize_; } + + void setStackSize(int value) { stackSize_ = value; } + + PRIORITY getPriority() const { return priority_; } + + /** + * Sets priority. + * + * XXX + * Need to handle incremental priorities properly. + */ + void setPriority(PRIORITY value) { priority_ = value; } + + bool isDetached() const { return detached_; } + + void setDetached(bool value) { detached_ = value; } + + Thread::id_t getCurrentThreadId() const { + +#ifndef _WIN32 + return (Thread::id_t)pthread_self(); +#else + return (Thread::id_t)pthread_self().p; +#endif // _WIN32 + + } + +}; + +PosixThreadFactory::PosixThreadFactory(POLICY policy, PRIORITY priority, int stackSize, bool detached) : + impl_(new PosixThreadFactory::Impl(policy, priority, stackSize, detached)) {} + +shared_ptr PosixThreadFactory::newThread(shared_ptr runnable) const { return impl_->newThread(runnable); } + +int PosixThreadFactory::getStackSize() const { return impl_->getStackSize(); } + +void PosixThreadFactory::setStackSize(int value) { impl_->setStackSize(value); } + +PosixThreadFactory::PRIORITY PosixThreadFactory::getPriority() const { return impl_->getPriority(); } + +void PosixThreadFactory::setPriority(PosixThreadFactory::PRIORITY value) { impl_->setPriority(value); } + +bool PosixThreadFactory::isDetached() const { return impl_->isDetached(); } + +void PosixThreadFactory::setDetached(bool value) { impl_->setDetached(value); } + +Thread::id_t PosixThreadFactory::getCurrentThreadId() const { return impl_->getCurrentThreadId(); } + +}}} // apache::thrift::concurrency diff --git a/sg_agent/thrid_party/thrift/include/concurrency/PosixThreadFactory.h b/sg_agent/thrid_party/thrift/include/concurrency/PosixThreadFactory.h new file mode 100644 index 0000000..d6d83a3 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/PosixThreadFactory.h @@ -0,0 +1,130 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_CONCURRENCY_POSIXTHREADFACTORY_H_ +#define _THRIFT_CONCURRENCY_POSIXTHREADFACTORY_H_ 1 + +#include "Thread.h" + +#include + +namespace apache { namespace thrift { namespace concurrency { + +/** + * A thread factory to create posix threads + * + * @version $Id:$ + */ +class PosixThreadFactory : public ThreadFactory { + + public: + + /** + * POSIX Thread scheduler policies + */ + enum POLICY { + OTHER, + FIFO, + ROUND_ROBIN + }; + + /** + * POSIX Thread scheduler relative priorities, + * + * Absolute priority is determined by scheduler policy and OS. This + * enumeration specifies relative priorities such that one can specify a + * priority withing a giving scheduler policy without knowing the absolute + * value of the priority. + */ + enum PRIORITY { + LOWEST = 0, + LOWER = 1, + LOW = 2, + NORMAL = 3, + HIGH = 4, + HIGHER = 5, + HIGHEST = 6, + INCREMENT = 7, + DECREMENT = 8 + }; + + /** + * Posix thread (pthread) factory. All threads created by a factory are reference-counted + * via boost::shared_ptr and boost::weak_ptr. The factory guarantees that threads and + * the Runnable tasks they host will be properly cleaned up once the last strong reference + * to both is given up. + * + * Threads are created with the specified policy, priority, stack-size and detachable-mode + * detached means the thread is free-running and will release all system resources the + * when it completes. A detachable thread is not joinable. The join method + * of a detachable thread will return immediately with no error. + * + * By default threads are not joinable. + */ + + PosixThreadFactory(POLICY policy=ROUND_ROBIN, PRIORITY priority=NORMAL, int stackSize=1, bool detached=true); + + // From ThreadFactory; + boost::shared_ptr newThread(boost::shared_ptr runnable) const; + + // From ThreadFactory; + Thread::id_t getCurrentThreadId() const; + + /** + * Gets stack size for created threads + * + * @return int size in megabytes + */ + virtual int getStackSize() const; + + /** + * Sets stack size for created threads + * + * @param value size in megabytes + */ + virtual void setStackSize(int value); + + /** + * Gets priority relative to current policy + */ + virtual PRIORITY getPriority() const; + + /** + * Sets priority relative to current policy + */ + virtual void setPriority(PRIORITY priority); + + /** + * Sets detached mode of threads + */ + virtual void setDetached(bool detached); + + /** + * Gets current detached mode + */ + virtual bool isDetached() const; + + private: + class Impl; + boost::shared_ptr impl_; +}; + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_POSIXTHREADFACTORY_H_ diff --git a/sg_agent/thrid_party/thrift/include/concurrency/Thread.h b/sg_agent/thrid_party/thrift/include/concurrency/Thread.h new file mode 100644 index 0000000..a9e15af --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/Thread.h @@ -0,0 +1,133 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_CONCURRENCY_THREAD_H_ +#define _THRIFT_CONCURRENCY_THREAD_H_ 1 + +#include +#include +#include + +#ifdef USE_BOOST_THREAD +#include +#endif + +namespace apache { namespace thrift { namespace concurrency { + +class Thread; + +/** + * Minimal runnable class. More or less analogous to java.lang.Runnable. + * + * @version $Id:$ + */ +class Runnable { + + public: + virtual ~Runnable() {}; + virtual void run() = 0; + + /** + * Gets the thread object that is hosting this runnable object - can return + * an empty boost::shared pointer if no references remain on thet thread object + */ + virtual boost::shared_ptr thread() { return thread_.lock(); } + + /** + * Sets the thread that is executing this object. This is only meant for + * use by concrete implementations of Thread. + */ + virtual void thread(boost::shared_ptr value) { thread_ = value; } + + private: + boost::weak_ptr thread_; +}; + +/** + * Minimal thread class. Returned by thread factory bound to a Runnable object + * and ready to start execution. More or less analogous to java.lang.Thread + * (minus all the thread group, priority, mode and other baggage, since that + * is difficult to abstract across platforms and is left for platform-specific + * ThreadFactory implemtations to deal with + * + * @see apache::thrift::concurrency::ThreadFactory) + */ +class Thread { + + public: + +#ifdef USE_BOOST_THREAD + typedef boost::thread::id id_t; +#else + typedef uint64_t id_t; +#endif + + virtual ~Thread() {}; + + /** + * Starts the thread. Does platform specific thread creation and + * configuration then invokes the run method of the Runnable object bound + * to this thread. + */ + virtual void start() = 0; + + /** + * Join this thread. Current thread blocks until this target thread + * completes. + */ + virtual void join() = 0; + + /** + * Gets the thread's platform-specific ID + */ + virtual id_t getId() = 0; + + /** + * Gets the runnable object this thread is hosting + */ + virtual boost::shared_ptr runnable() const { return _runnable; } + + protected: + virtual void runnable(boost::shared_ptr value) { _runnable = value; } + + private: + boost::shared_ptr _runnable; + +}; + +/** + * Factory to create platform-specific thread object and bind them to Runnable + * object for execution + */ +class ThreadFactory { + + public: + virtual ~ThreadFactory() {} + virtual boost::shared_ptr newThread(boost::shared_ptr runnable) const = 0; + + /** Gets the current thread id or unknown_thread_id if the current thread is not a thrift thread */ + + static const Thread::id_t unknown_thread_id; + + virtual Thread::id_t getCurrentThreadId() const = 0; +}; + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_THREAD_H_ diff --git a/sg_agent/thrid_party/thrift/include/concurrency/ThreadManager.cpp b/sg_agent/thrid_party/thrift/include/concurrency/ThreadManager.cpp new file mode 100644 index 0000000..e56a9b5 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/ThreadManager.cpp @@ -0,0 +1,581 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "ThreadManager.h" +#include "Exception.h" +#include "Monitor.h" +#include "Util.h" + +#include + +#include +#include +#include + +#if defined(DEBUG) +#include +#endif //defined(DEBUG) + +namespace apache { namespace thrift { namespace concurrency { + +using boost::shared_ptr; +using boost::dynamic_pointer_cast; + +/** + * ThreadManager class + * + * This class manages a pool of threads. It uses a ThreadFactory to create + * threads. It never actually creates or destroys worker threads, rather + * it maintains statistics on number of idle threads, number of active threads, + * task backlog, and average wait and service times. + * + * @version $Id:$ + */ +class ThreadManager::Impl : public ThreadManager { + + public: + Impl() : + workerCount_(0), + workerMaxCount_(0), + idleCount_(0), + pendingTaskCountMax_(0), + expiredCount_(0), + state_(ThreadManager::UNINITIALIZED), + monitor_(&mutex_), + maxMonitor_(&mutex_) {} + + ~Impl() { stop(); } + + void start(); + + void stop() { stopImpl(false); } + + void join() { stopImpl(true); } + + ThreadManager::STATE state() const { + return state_; + } + + shared_ptr threadFactory() const { + Synchronized s(monitor_); + return threadFactory_; + } + + void threadFactory(shared_ptr value) { + Synchronized s(monitor_); + threadFactory_ = value; + } + + void addWorker(size_t value); + + void removeWorker(size_t value); + + size_t idleWorkerCount() const { + return idleCount_; + } + + size_t workerCount() const { + Synchronized s(monitor_); + return workerCount_; + } + + size_t pendingTaskCount() const { + Synchronized s(monitor_); + return tasks_.size(); + } + + size_t totalTaskCount() const { + Synchronized s(monitor_); + return tasks_.size() + workerCount_ - idleCount_; + } + + size_t pendingTaskCountMax() const { + Synchronized s(monitor_); + return pendingTaskCountMax_; + } + + size_t expiredTaskCount() { + Synchronized s(monitor_); + size_t result = expiredCount_; + expiredCount_ = 0; + return result; + } + + void pendingTaskCountMax(const size_t value) { + Synchronized s(monitor_); + pendingTaskCountMax_ = value; + } + + bool canSleep(); + + void add(shared_ptr value, int64_t timeout, int64_t expiration); + + void remove(shared_ptr task); + + shared_ptr removeNextPending(); + + void removeExpiredTasks(); + + void setExpireCallback(ExpireCallback expireCallback); + +private: + void stopImpl(bool join); + + size_t workerCount_; + size_t workerMaxCount_; + size_t idleCount_; + size_t pendingTaskCountMax_; + size_t expiredCount_; + ExpireCallback expireCallback_; + + ThreadManager::STATE state_; + shared_ptr threadFactory_; + + + friend class ThreadManager::Task; + std::queue > tasks_; + Mutex mutex_; + Monitor monitor_; + Monitor maxMonitor_; + Monitor workerMonitor_; + + friend class ThreadManager::Worker; + std::set > workers_; + std::set > deadWorkers_; + std::map > idMap_; +}; + +class ThreadManager::Task : public Runnable { + + public: + enum STATE { + WAITING, + EXECUTING, + CANCELLED, + COMPLETE + }; + + Task(shared_ptr runnable, int64_t expiration=0LL) : + runnable_(runnable), + state_(WAITING), + expireTime_(expiration != 0LL ? Util::currentTime() + expiration : 0LL) {} + + ~Task() {} + + void run() { + if (state_ == EXECUTING) { + runnable_->run(); + state_ = COMPLETE; + } + } + + shared_ptr getRunnable() { + return runnable_; + } + + int64_t getExpireTime() const { + return expireTime_; + } + + private: + shared_ptr runnable_; + friend class ThreadManager::Worker; + STATE state_; + int64_t expireTime_; +}; + +class ThreadManager::Worker: public Runnable { + enum STATE { + UNINITIALIZED, + STARTING, + STARTED, + STOPPING, + STOPPED + }; + + public: + Worker(ThreadManager::Impl* manager) : + manager_(manager), + state_(UNINITIALIZED), + idle_(false) {} + + ~Worker() {} + + private: + bool isActive() const { + return + (manager_->workerCount_ <= manager_->workerMaxCount_) || + (manager_->state_ == JOINING && !manager_->tasks_.empty()); + } + + public: + /** + * Worker entry point + * + * As long as worker thread is running, pull tasks off the task queue and + * execute. + */ + void run() { + bool active = false; + bool notifyManager = false; + + /** + * Increment worker semaphore and notify manager if worker count reached + * desired max + * + * Note: We have to release the monitor and acquire the workerMonitor + * since that is what the manager blocks on for worker add/remove + */ + { + Synchronized s(manager_->monitor_); + active = manager_->workerCount_ < manager_->workerMaxCount_; + if (active) { + manager_->workerCount_++; + notifyManager = manager_->workerCount_ == manager_->workerMaxCount_; + } + } + + if (notifyManager) { + Synchronized s(manager_->workerMonitor_); + manager_->workerMonitor_.notify(); + notifyManager = false; + } + + while (active) { + shared_ptr task; + + /** + * While holding manager monitor block for non-empty task queue (Also + * check that the thread hasn't been requested to stop). Once the queue + * is non-empty, dequeue a task, release monitor, and execute. If the + * worker max count has been decremented such that we exceed it, mark + * ourself inactive, decrement the worker count and notify the manager + * (technically we're notifying the next blocked thread but eventually + * the manager will see it. + */ + { + Guard g(manager_->mutex_); + active = isActive(); + + while (active && manager_->tasks_.empty()) { + manager_->idleCount_++; + idle_ = true; + manager_->monitor_.wait(); + active = isActive(); + idle_ = false; + manager_->idleCount_--; + } + + if (active) { + manager_->removeExpiredTasks(); + + if (!manager_->tasks_.empty()) { + task = manager_->tasks_.front(); + manager_->tasks_.pop(); + if (task->state_ == ThreadManager::Task::WAITING) { + task->state_ = ThreadManager::Task::EXECUTING; + } + + /* If we have a pending task max and we just dropped below it, wakeup any + thread that might be blocked on add. */ + if (manager_->pendingTaskCountMax_ != 0 && + manager_->tasks_.size() <= manager_->pendingTaskCountMax_ - 1) { + manager_->maxMonitor_.notify(); + } + } + } else { + idle_ = true; + manager_->workerCount_--; + notifyManager = (manager_->workerCount_ == manager_->workerMaxCount_); + } + } + + if (task != NULL) { + if (task->state_ == ThreadManager::Task::EXECUTING) { + try { + task->run(); + } catch(...) { + // XXX need to log this + } + } + } + } + + { + Synchronized s(manager_->workerMonitor_); + manager_->deadWorkers_.insert(this->thread()); + if (notifyManager) { + manager_->workerMonitor_.notify(); + } + } + + return; + } + + private: + ThreadManager::Impl* manager_; + friend class ThreadManager::Impl; + STATE state_; + bool idle_; +}; + + + void ThreadManager::Impl::addWorker(size_t value) { + std::set > newThreads; + for (size_t ix = 0; ix < value; ix++) { + shared_ptr worker = shared_ptr(new ThreadManager::Worker(this)); + newThreads.insert(threadFactory_->newThread(worker)); + } + + { + Synchronized s(monitor_); + workerMaxCount_ += value; + workers_.insert(newThreads.begin(), newThreads.end()); + } + + for (std::set >::iterator ix = newThreads.begin(); ix != newThreads.end(); ix++) { + shared_ptr worker = dynamic_pointer_cast((*ix)->runnable()); + worker->state_ = ThreadManager::Worker::STARTING; + (*ix)->start(); + idMap_.insert(std::pair >((*ix)->getId(), *ix)); + } + + { + Synchronized s(workerMonitor_); + while (workerCount_ != workerMaxCount_) { + workerMonitor_.wait(); + } + } +} + +void ThreadManager::Impl::start() { + + if (state_ == ThreadManager::STOPPED) { + return; + } + + { + Synchronized s(monitor_); + if (state_ == ThreadManager::UNINITIALIZED) { + if (threadFactory_ == NULL) { + throw InvalidArgumentException(); + } + state_ = ThreadManager::STARTED; + monitor_.notifyAll(); + } + + while (state_ == STARTING) { + monitor_.wait(); + } + } +} + +void ThreadManager::Impl::stopImpl(bool join) { + bool doStop = false; + if (state_ == ThreadManager::STOPPED) { + return; + } + + { + Synchronized s(monitor_); + if (state_ != ThreadManager::STOPPING && + state_ != ThreadManager::JOINING && + state_ != ThreadManager::STOPPED) { + doStop = true; + state_ = join ? ThreadManager::JOINING : ThreadManager::STOPPING; + } + } + + if (doStop) { + removeWorker(workerCount_); + } + + // XXX + // should be able to block here for transition to STOPPED since we're no + // using shared_ptrs + + { + Synchronized s(monitor_); + state_ = ThreadManager::STOPPED; + } + +} + +void ThreadManager::Impl::removeWorker(size_t value) { + std::set > removedThreads; + { + Synchronized s(monitor_); + if (value > workerMaxCount_) { + throw InvalidArgumentException(); + } + + workerMaxCount_ -= value; + + if (idleCount_ < value) { + for (size_t ix = 0; ix < idleCount_; ix++) { + monitor_.notify(); + } + } else { + monitor_.notifyAll(); + } + } + + { + Synchronized s(workerMonitor_); + + while (workerCount_ != workerMaxCount_) { + workerMonitor_.wait(); + } + + for (std::set >::iterator ix = deadWorkers_.begin(); ix != deadWorkers_.end(); ix++) { + workers_.erase(*ix); + idMap_.erase((*ix)->getId()); + } + + deadWorkers_.clear(); + } +} + + bool ThreadManager::Impl::canSleep() { + const Thread::id_t id = threadFactory_->getCurrentThreadId(); + return idMap_.find(id) == idMap_.end(); + } + + void ThreadManager::Impl::add(shared_ptr value, + int64_t timeout, + int64_t expiration) { + Guard g(mutex_, timeout); + + if (!g) { + throw TimedOutException(); + } + + if (state_ != ThreadManager::STARTED) { + throw IllegalStateException("ThreadManager::Impl::add ThreadManager " + "not started"); + } + + removeExpiredTasks(); + if (pendingTaskCountMax_ > 0 && (tasks_.size() >= pendingTaskCountMax_)) { + if (canSleep() && timeout >= 0) { + while (pendingTaskCountMax_ > 0 && tasks_.size() >= pendingTaskCountMax_) { + // This is thread safe because the mutex is shared between monitors. + maxMonitor_.wait(timeout); + } + } else { + throw TooManyPendingTasksException(); + } + } + + tasks_.push(shared_ptr(new ThreadManager::Task(value, expiration))); + + // If idle thread is available notify it, otherwise all worker threads are + // running and will get around to this task in time. + if (idleCount_ > 0) { + monitor_.notify(); + } + } + +void ThreadManager::Impl::remove(shared_ptr task) { + (void) task; + Synchronized s(monitor_); + if (state_ != ThreadManager::STARTED) { + throw IllegalStateException("ThreadManager::Impl::remove ThreadManager not " + "started"); + } +} + +boost::shared_ptr ThreadManager::Impl::removeNextPending() { + Guard g(mutex_); + if (state_ != ThreadManager::STARTED) { + throw IllegalStateException("ThreadManager::Impl::removeNextPending " + "ThreadManager not started"); + } + + if (tasks_.empty()) { + return boost::shared_ptr(); + } + + shared_ptr task = tasks_.front(); + tasks_.pop(); + + return task->getRunnable(); +} + +void ThreadManager::Impl::removeExpiredTasks() { + int64_t now = 0LL; // we won't ask for the time untile we need it + + // note that this loop breaks at the first non-expiring task + while (!tasks_.empty()) { + shared_ptr task = tasks_.front(); + if (task->getExpireTime() == 0LL) { + break; + } + if (now == 0LL) { + now = Util::currentTime(); + } + if (task->getExpireTime() > now) { + break; + } + if (expireCallback_) { + expireCallback_(task->getRunnable()); + } + tasks_.pop(); + expiredCount_++; + } +} + + +void ThreadManager::Impl::setExpireCallback(ExpireCallback expireCallback) { + expireCallback_ = expireCallback; +} + +class SimpleThreadManager : public ThreadManager::Impl { + + public: + SimpleThreadManager(size_t workerCount=4, size_t pendingTaskCountMax=0) : + workerCount_(workerCount), + pendingTaskCountMax_(pendingTaskCountMax), + firstTime_(true) { + } + + void start() { + ThreadManager::Impl::pendingTaskCountMax(pendingTaskCountMax_); + ThreadManager::Impl::start(); + addWorker(workerCount_); + } + + private: + const size_t workerCount_; + const size_t pendingTaskCountMax_; + bool firstTime_; + Monitor monitor_; +}; + + +shared_ptr ThreadManager::newThreadManager() { + return shared_ptr(new ThreadManager::Impl()); +} + +shared_ptr ThreadManager::newSimpleThreadManager(size_t count, size_t pendingTaskCountMax) { + return shared_ptr(new SimpleThreadManager(count, pendingTaskCountMax)); +} + +}}} // apache::thrift::concurrency + diff --git a/sg_agent/thrid_party/thrift/include/concurrency/ThreadManager.h b/sg_agent/thrid_party/thrift/include/concurrency/ThreadManager.h new file mode 100644 index 0000000..6d7b0ef --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/ThreadManager.h @@ -0,0 +1,202 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_CONCURRENCY_THREADMANAGER_H_ +#define _THRIFT_CONCURRENCY_THREADMANAGER_H_ 1 + +#include +#include +#include +#include "Thread.h" + +namespace apache { namespace thrift { namespace concurrency { + +/** + * Thread Pool Manager and related classes + * + * @version $Id:$ + */ +class ThreadManager; + +/** + * ThreadManager class + * + * This class manages a pool of threads. It uses a ThreadFactory to create + * threads. It never actually creates or destroys worker threads, rather + * It maintains statistics on number of idle threads, number of active threads, + * task backlog, and average wait and service times and informs the PoolPolicy + * object bound to instances of this manager of interesting transitions. It is + * then up the PoolPolicy object to decide if the thread pool size needs to be + * adjusted and call this object addWorker and removeWorker methods to make + * changes. + * + * This design allows different policy implementations to used this code to + * handle basic worker thread management and worker task execution and focus on + * policy issues. The simplest policy, StaticPolicy, does nothing other than + * create a fixed number of threads. + */ +class ThreadManager { + + protected: + ThreadManager() {} + + public: + class Task; + typedef std::tr1::function)> ExpireCallback; + + virtual ~ThreadManager() {} + + /** + * Starts the thread manager. Verifies all attributes have been properly + * initialized, then allocates necessary resources to begin operation + */ + virtual void start() = 0; + + /** + * Stops the thread manager. Aborts all remaining unprocessed task, shuts + * down all created worker threads, and realeases all allocated resources. + * This method blocks for all worker threads to complete, thus it can + * potentially block forever if a worker thread is running a task that + * won't terminate. + */ + virtual void stop() = 0; + + /** + * Joins the thread manager. This is the same as stop, except that it will + * block until all the workers have finished their work. At that point + * the ThreadManager will transition into the STOPPED state. + */ + virtual void join() = 0; + + enum STATE { + UNINITIALIZED, + STARTING, + STARTED, + JOINING, + STOPPING, + STOPPED + }; + + virtual STATE state() const = 0; + + virtual boost::shared_ptr threadFactory() const = 0; + + virtual void threadFactory(boost::shared_ptr value) = 0; + + virtual void addWorker(size_t value=1) = 0; + + virtual void removeWorker(size_t value=1) = 0; + + /** + * Gets the current number of idle worker threads + */ + virtual size_t idleWorkerCount() const = 0; + + /** + * Gets the current number of total worker threads + */ + virtual size_t workerCount() const = 0; + + /** + * Gets the current number of pending tasks + */ + virtual size_t pendingTaskCount() const = 0; + + /** + * Gets the current number of pending and executing tasks + */ + virtual size_t totalTaskCount() const = 0; + + /** + * Gets the maximum pending task count. 0 indicates no maximum + */ + virtual size_t pendingTaskCountMax() const = 0; + + /** + * Gets the number of tasks which have been expired without being run. + */ + virtual size_t expiredTaskCount() = 0; + + /** + * Adds a task to be executed at some time in the future by a worker thread. + * + * This method will block if pendingTaskCountMax() in not zero and pendingTaskCount() + * is greater than or equalt to pendingTaskCountMax(). If this method is called in the + * context of a ThreadManager worker thread it will throw a + * TooManyPendingTasksException + * + * @param task The task to queue for execution + * + * @param timeout Time to wait in milliseconds to add a task when a pending-task-count + * is specified. Specific cases: + * timeout = 0 : Wait forever to queue task. + * timeout = -1 : Return immediately if pending task count exceeds specified max + * @param expiration when nonzero, the number of milliseconds the task is valid + * to be run; if exceeded, the task will be dropped off the queue and not run. + * + * @throws TooManyPendingTasksException Pending task count exceeds max pending task count + */ + virtual void add(boost::shared_ptrtask, + int64_t timeout=0LL, + int64_t expiration=0LL) = 0; + + /** + * Removes a pending task + */ + virtual void remove(boost::shared_ptr task) = 0; + + /** + * Remove the next pending task which would be run. + * + * @return the task removed. + */ + virtual boost::shared_ptr removeNextPending() = 0; + + /** + * Remove tasks from front of task queue that have expired. + */ + virtual void removeExpiredTasks() = 0; + + /** + * Set a callback to be called when a task is expired and not run. + * + * @param expireCallback a function called with the shared_ptr for + * the expired task. + */ + virtual void setExpireCallback(ExpireCallback expireCallback) = 0; + + static boost::shared_ptr newThreadManager(); + + /** + * Creates a simple thread manager the uses count number of worker threads and has + * a pendingTaskCountMax maximum pending tasks. The default, 0, specified no limit + * on pending tasks + */ + static boost::shared_ptr newSimpleThreadManager(size_t count=4, size_t pendingTaskCountMax=0); + + class Task; + + class Worker; + + class Impl; +}; + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_THREADMANAGER_H_ diff --git a/sg_agent/thrid_party/thrift/include/concurrency/TimerManager.cpp b/sg_agent/thrid_party/thrift/include/concurrency/TimerManager.cpp new file mode 100644 index 0000000..f7acd0a --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/TimerManager.cpp @@ -0,0 +1,284 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "TimerManager.h" +#include "Exception.h" +#include "Util.h" + +#include +#include +#include + +namespace apache { namespace thrift { namespace concurrency { + +using boost::shared_ptr; + +/** + * TimerManager class + * + * @version $Id:$ + */ +class TimerManager::Task : public Runnable { + + public: + enum STATE { + WAITING, + EXECUTING, + CANCELLED, + COMPLETE + }; + + Task(shared_ptr runnable) : + runnable_(runnable), + state_(WAITING) {} + + ~Task() { + } + + void run() { + if (state_ == EXECUTING) { + runnable_->run(); + state_ = COMPLETE; + } + } + + private: + shared_ptr runnable_; + friend class TimerManager::Dispatcher; + STATE state_; +}; + +class TimerManager::Dispatcher: public Runnable { + + public: + Dispatcher(TimerManager* manager) : + manager_(manager) {} + + ~Dispatcher() {} + + /** + * Dispatcher entry point + * + * As long as dispatcher thread is running, pull tasks off the task taskMap_ + * and execute. + */ + void run() { + { + Synchronized s(manager_->monitor_); + if (manager_->state_ == TimerManager::STARTING) { + manager_->state_ = TimerManager::STARTED; + manager_->monitor_.notifyAll(); + } + } + + do { + std::set > expiredTasks; + { + Synchronized s(manager_->monitor_); + task_iterator expiredTaskEnd; + int64_t now = Util::currentTime(); + while (manager_->state_ == TimerManager::STARTED && + (expiredTaskEnd = manager_->taskMap_.upper_bound(now)) == manager_->taskMap_.begin()) { + int64_t timeout = 0LL; + if (!manager_->taskMap_.empty()) { + timeout = manager_->taskMap_.begin()->first - now; + } + assert((timeout != 0 && manager_->taskCount_ > 0) || (timeout == 0 && manager_->taskCount_ == 0)); + try { + manager_->monitor_.wait(timeout); + } catch (TimedOutException &e) {} + now = Util::currentTime(); + } + + if (manager_->state_ == TimerManager::STARTED) { + for (task_iterator ix = manager_->taskMap_.begin(); ix != expiredTaskEnd; ix++) { + shared_ptr task = ix->second; + expiredTasks.insert(task); + if (task->state_ == TimerManager::Task::WAITING) { + task->state_ = TimerManager::Task::EXECUTING; + } + manager_->taskCount_--; + } + manager_->taskMap_.erase(manager_->taskMap_.begin(), expiredTaskEnd); + } + } + + for (std::set >::iterator ix = expiredTasks.begin(); ix != expiredTasks.end(); ix++) { + (*ix)->run(); + } + + } while (manager_->state_ == TimerManager::STARTED); + + { + Synchronized s(manager_->monitor_); + if (manager_->state_ == TimerManager::STOPPING) { + manager_->state_ = TimerManager::STOPPED; + manager_->monitor_.notify(); + } + } + return; + } + + private: + TimerManager* manager_; + friend class TimerManager; +}; + +TimerManager::TimerManager() : + taskCount_(0), + state_(TimerManager::UNINITIALIZED), + dispatcher_(shared_ptr(new Dispatcher(this))) { +} + + +TimerManager::~TimerManager() { + + // If we haven't been explicitly stopped, do so now. We don't need to grab + // the monitor here, since stop already takes care of reentrancy. + + if (state_ != STOPPED) { + try { + stop(); + } catch(...) { + throw; + // uhoh + } + } +} + +void TimerManager::start() { + bool doStart = false; + { + Synchronized s(monitor_); + if (threadFactory_ == NULL) { + throw InvalidArgumentException(); + } + if (state_ == TimerManager::UNINITIALIZED) { + state_ = TimerManager::STARTING; + doStart = true; + } + } + + if (doStart) { + dispatcherThread_ = threadFactory_->newThread(dispatcher_); + dispatcherThread_->start(); + } + + { + Synchronized s(monitor_); + while (state_ == TimerManager::STARTING) { + monitor_.wait(); + } + assert(state_ != TimerManager::STARTING); + } +} + +void TimerManager::stop() { + bool doStop = false; + { + Synchronized s(monitor_); + if (state_ == TimerManager::UNINITIALIZED) { + state_ = TimerManager::STOPPED; + } else if (state_ != STOPPING && state_ != STOPPED) { + doStop = true; + state_ = STOPPING; + monitor_.notifyAll(); + } + while (state_ != STOPPED) { + monitor_.wait(); + } + } + + if (doStop) { + // Clean up any outstanding tasks + taskMap_.clear(); + + // Remove dispatcher's reference to us. + dispatcher_->manager_ = NULL; + } +} + +shared_ptr TimerManager::threadFactory() const { + Synchronized s(monitor_); + return threadFactory_; +} + +void TimerManager::threadFactory(shared_ptr value) { + Synchronized s(monitor_); + threadFactory_ = value; +} + +size_t TimerManager::taskCount() const { + return taskCount_; +} + +void TimerManager::add(shared_ptr task, int64_t timeout) { + int64_t now = Util::currentTime(); + timeout += now; + + { + Synchronized s(monitor_); + if (state_ != TimerManager::STARTED) { + throw IllegalStateException(); + } + + // If the task map is empty, we will kick the dispatcher for sure. Otherwise, we kick him + // if the expiration time is shorter than the current value. Need to test before we insert, + // because the new task might insert at the front. + bool notifyRequired = (taskCount_ == 0) ? true : timeout < taskMap_.begin()->first; + + taskCount_++; + taskMap_.insert(std::pair >(timeout, shared_ptr(new Task(task)))); + + // If the task map was empty, or if we have an expiration that is earlier + // than any previously seen, kick the dispatcher so it can update its + // timeout + if (notifyRequired) { + monitor_.notify(); + } + } +} + +void TimerManager::add(shared_ptr task, const struct timespec& value) { + + int64_t expiration; + Util::toMilliseconds(expiration, value); + + int64_t now = Util::currentTime(); + + if (expiration < now) { + throw InvalidArgumentException(); + } + + add(task, expiration - now); +} + + +void TimerManager::remove(shared_ptr task) { + (void) task; + Synchronized s(monitor_); + if (state_ != TimerManager::STARTED) { + throw IllegalStateException(); + } +} + +TimerManager::STATE TimerManager::state() const { return state_; } + +}}} // apache::thrift::concurrency + diff --git a/sg_agent/thrid_party/thrift/include/concurrency/TimerManager.h b/sg_agent/thrid_party/thrift/include/concurrency/TimerManager.h new file mode 100644 index 0000000..d905ddb --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/TimerManager.h @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_CONCURRENCY_TIMERMANAGER_H_ +#define _THRIFT_CONCURRENCY_TIMERMANAGER_H_ 1 + +#include "Exception.h" +#include "Monitor.h" +#include "Thread.h" + +#include +#include +#include + +namespace apache { namespace thrift { namespace concurrency { + +/** + * Timer Manager + * + * This class dispatches timer tasks when they fall due. + * + * @version $Id:$ + */ +class TimerManager { + + public: + + TimerManager(); + + virtual ~TimerManager(); + + virtual boost::shared_ptr threadFactory() const; + + virtual void threadFactory(boost::shared_ptr value); + + /** + * Starts the timer manager service + * + * @throws IllegalArgumentException Missing thread factory attribute + */ + virtual void start(); + + /** + * Stops the timer manager service + */ + virtual void stop(); + + virtual size_t taskCount() const ; + + /** + * Adds a task to be executed at some time in the future by a worker thread. + * + * @param task The task to execute + * @param timeout Time in milliseconds to delay before executing task + */ + virtual void add(boost::shared_ptr task, int64_t timeout); + + /** + * Adds a task to be executed at some time in the future by a worker thread. + * + * @param task The task to execute + * @param timeout Absolute time in the future to execute task. + */ + virtual void add(boost::shared_ptr task, const struct timespec& timeout); + + /** + * Removes a pending task + * + * @throws NoSuchTaskException Specified task doesn't exist. It was either + * processed already or this call was made for a + * task that was never added to this timer + * + * @throws UncancellableTaskException Specified task is already being + * executed or has completed execution. + */ + virtual void remove(boost::shared_ptr task); + + enum STATE { + UNINITIALIZED, + STARTING, + STARTED, + STOPPING, + STOPPED + }; + + virtual STATE state() const; + + private: + boost::shared_ptr threadFactory_; + class Task; + friend class Task; + std::multimap > taskMap_; + size_t taskCount_; + Monitor monitor_; + STATE state_; + class Dispatcher; + friend class Dispatcher; + boost::shared_ptr dispatcher_; + boost::shared_ptr dispatcherThread_; + typedef std::multimap >::iterator task_iterator; + typedef std::pair task_range; +}; + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_TIMERMANAGER_H_ diff --git a/sg_agent/thrid_party/thrift/include/concurrency/Util.cpp b/sg_agent/thrid_party/thrift/include/concurrency/Util.cpp new file mode 100644 index 0000000..73b0c05 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/Util.cpp @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "Util.h" + +#if defined(HAVE_CLOCK_GETTIME) +#include +#elif defined(HAVE_SYS_TIME_H) +#include +#endif // defined(HAVE_CLOCK_GETTIME) + +namespace apache { namespace thrift { namespace concurrency { + +int64_t Util::currentTimeTicks(int64_t ticksPerSec) { + int64_t result; + +#if defined(HAVE_CLOCK_GETTIME) + struct timespec now; + int ret = clock_gettime(CLOCK_REALTIME, &now); + assert(ret == 0); + toTicks(result, now, ticksPerSec); +#elif defined(HAVE_GETTIMEOFDAY) + struct timeval now; + int ret = gettimeofday(&now, NULL); + assert(ret == 0); + toTicks(result, now, ticksPerSec); +#else +#error "No high-precision clock is available." +#endif // defined(HAVE_CLOCK_GETTIME) + + return result; +} + +}}} // apache::thrift::concurrency diff --git a/sg_agent/thrid_party/thrift/include/concurrency/Util.h b/sg_agent/thrid_party/thrift/include/concurrency/Util.h new file mode 100644 index 0000000..8ef07ef --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/Util.h @@ -0,0 +1,150 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_CONCURRENCY_UTIL_H_ +#define _THRIFT_CONCURRENCY_UTIL_H_ 1 + +#include +#include +#include +#include + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +namespace apache { namespace thrift { namespace concurrency { + +/** + * Utility methods + * + * This class contains basic utility methods for converting time formats, + * and other common platform-dependent concurrency operations. + * It should not be included in API headers for other concurrency library + * headers, since it will, by definition, pull in all sorts of horrid + * platform dependent stuff. Rather it should be inluded directly in + * concurrency library implementation source. + * + * @version $Id:$ + */ +class Util { + + static const int64_t NS_PER_S = 1000000000LL; + static const int64_t US_PER_S = 1000000LL; + static const int64_t MS_PER_S = 1000LL; + + static const int64_t NS_PER_MS = NS_PER_S / MS_PER_S; + static const int64_t NS_PER_US = NS_PER_S / US_PER_S; + static const int64_t US_PER_MS = US_PER_S / MS_PER_S; + + public: + + /** + * Converts millisecond timestamp into a timespec struct + * + * @param struct timespec& result + * @param time or duration in milliseconds + */ + static void toTimespec(struct timespec& result, int64_t value) { + result.tv_sec = value / MS_PER_S; // ms to s + result.tv_nsec = (value % MS_PER_S) * NS_PER_MS; // ms to ns + } + + static void toTimeval(struct timeval& result, int64_t value) { + result.tv_sec = value / MS_PER_S; // ms to s + result.tv_usec = (value % MS_PER_S) * US_PER_MS; // ms to us + } + + static void toTicks(int64_t& result, int64_t secs, int64_t oldTicks, + int64_t oldTicksPerSec, int64_t newTicksPerSec) { + result = secs * newTicksPerSec; + result += oldTicks * newTicksPerSec / oldTicksPerSec; + + int64_t oldPerNew = oldTicksPerSec / newTicksPerSec; + if (oldPerNew && ((oldTicks % oldPerNew) >= (oldPerNew / 2))) { + ++result; + } + } + /** + * Converts struct timespec to arbitrary-sized ticks since epoch + */ + static void toTicks(int64_t& result, + const struct timespec& value, + int64_t ticksPerSec) { + return toTicks(result, value.tv_sec, value.tv_nsec, NS_PER_S, ticksPerSec); + } + + /** + * Converts struct timeval to arbitrary-sized ticks since epoch + */ + static void toTicks(int64_t& result, + const struct timeval& value, + int64_t ticksPerSec) { + return toTicks(result, value.tv_sec, value.tv_usec, US_PER_S, ticksPerSec); + } + + /** + * Converts struct timespec to milliseconds + */ + static void toMilliseconds(int64_t& result, + const struct timespec& value) { + return toTicks(result, value, MS_PER_S); + } + + /** + * Converts struct timeval to milliseconds + */ + static void toMilliseconds(int64_t& result, + const struct timeval& value) { + return toTicks(result, value, MS_PER_S); + } + + /** + * Converts struct timespec to microseconds + */ + static void toUsec(int64_t& result, const struct timespec& value) { + return toTicks(result, value, US_PER_S); + } + + /** + * Converts struct timeval to microseconds + */ + static void toUsec(int64_t& result, const struct timeval& value) { + return toTicks(result, value, US_PER_S); + } + + /** + * Get current time as a number of arbitrary-size ticks from epoch + */ + static int64_t currentTimeTicks(int64_t ticksPerSec); + + /** + * Get current time as milliseconds from epoch + */ + static int64_t currentTime() { return currentTimeTicks(MS_PER_S); } + + /** + * Get current time as micros from epoch + */ + static int64_t currentTimeUsec() { return currentTimeTicks(US_PER_S); } +}; + +}}} // apache::thrift::concurrency + +#endif // #ifndef _THRIFT_CONCURRENCY_UTIL_H_ diff --git a/sg_agent/thrid_party/thrift/include/concurrency/test/Tests.cpp b/sg_agent/thrid_party/thrift/include/concurrency/test/Tests.cpp new file mode 100644 index 0000000..c80bb88 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/test/Tests.cpp @@ -0,0 +1,155 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include + +#include "ThreadFactoryTests.h" +#include "TimerManagerTests.h" +#include "ThreadManagerTests.h" + +int main(int argc, char** argv) { + + std::string arg; + + std::vector args(argc - 1 > 1 ? argc - 1 : 1); + + args[0] = "all"; + + for (int ix = 1; ix < argc; ix++) { + args[ix - 1] = std::string(argv[ix]); + } + + bool runAll = args[0].compare("all") == 0; + + if (runAll || args[0].compare("thread-factory") == 0) { + + ThreadFactoryTests threadFactoryTests; + + std::cout << "ThreadFactory tests..." << std::endl; + + size_t count = 1000; + size_t floodLoops = 1; + size_t floodCount = 100000; + + std::cout << "\t\tThreadFactory reap N threads test: N = " << count << std::endl; + + assert(threadFactoryTests.reapNThreads(count)); + + std::cout << "\t\tThreadFactory floodN threads test: N = " << floodCount << std::endl; + + assert(threadFactoryTests.floodNTest(floodLoops, floodCount)); + + std::cout << "\t\tThreadFactory synchronous start test" << std::endl; + + assert(threadFactoryTests.synchStartTest()); + + std::cout << "\t\tThreadFactory monitor timeout test" << std::endl; + + assert(threadFactoryTests.monitorTimeoutTest()); + } + + if (runAll || args[0].compare("util") == 0) { + + std::cout << "Util tests..." << std::endl; + + std::cout << "\t\tUtil minimum time" << std::endl; + + int64_t time00 = Util::currentTime(); + int64_t time01 = Util::currentTime(); + + std::cout << "\t\t\tMinimum time: " << time01 - time00 << "ms" << std::endl; + + time00 = Util::currentTime(); + time01 = time00; + size_t count = 0; + + while (time01 < time00 + 10) { + count++; + time01 = Util::currentTime(); + } + + std::cout << "\t\t\tscall per ms: " << count / (time01 - time00) << std::endl; + } + + + if (runAll || args[0].compare("timer-manager") == 0) { + + std::cout << "TimerManager tests..." << std::endl; + + std::cout << "\t\tTimerManager test00" << std::endl; + + TimerManagerTests timerManagerTests; + + assert(timerManagerTests.test00()); + } + + if (runAll || args[0].compare("thread-manager") == 0) { + + std::cout << "ThreadManager tests..." << std::endl; + + { + + size_t workerCount = 100; + + size_t taskCount = 100000; + + int64_t delay = 10LL; + + std::cout << "\t\tThreadManager load test: worker count: " << workerCount << " task count: " << taskCount << " delay: " << delay << std::endl; + + ThreadManagerTests threadManagerTests; + + assert(threadManagerTests.loadTest(taskCount, delay, workerCount)); + + std::cout << "\t\tThreadManager block test: worker count: " << workerCount << " delay: " << delay << std::endl; + + assert(threadManagerTests.blockTest(delay, workerCount)); + + } + } + + if (runAll || args[0].compare("thread-manager-benchmark") == 0) { + + std::cout << "ThreadManager benchmark tests..." << std::endl; + + { + + size_t minWorkerCount = 2; + + size_t maxWorkerCount = 512; + + size_t tasksPerWorker = 1000; + + int64_t delay = 10LL; + + for (size_t workerCount = minWorkerCount; workerCount < maxWorkerCount; workerCount*= 2) { + + size_t taskCount = workerCount * tasksPerWorker; + + std::cout << "\t\tThreadManager load test: worker count: " << workerCount << " task count: " << taskCount << " delay: " << delay << std::endl; + + ThreadManagerTests threadManagerTests; + + threadManagerTests.loadTest(taskCount, delay, workerCount); + } + } + } +} diff --git a/sg_agent/thrid_party/thrift/include/concurrency/test/ThreadFactoryTests.h b/sg_agent/thrid_party/thrift/include/concurrency/test/ThreadFactoryTests.h new file mode 100644 index 0000000..d9066b5 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/test/ThreadFactoryTests.h @@ -0,0 +1,355 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace apache { namespace thrift { namespace concurrency { namespace test { + +using boost::shared_ptr; +using namespace apache::thrift::concurrency; + +/** + * ThreadManagerTests class + * + * @version $Id:$ + */ +class ThreadFactoryTests { + +public: + + static const double ERROR; + + class Task: public Runnable { + + public: + + Task() {} + + void run() { + std::cout << "\t\t\tHello World" << std::endl; + } + }; + + /** + * Hello world test + */ + bool helloWorldTest() { + + PlatformThreadFactory threadFactory = PlatformThreadFactory(); + + shared_ptr task = shared_ptr(new ThreadFactoryTests::Task()); + + shared_ptr thread = threadFactory.newThread(task); + + thread->start(); + + thread->join(); + + std::cout << "\t\t\tSuccess!" << std::endl; + + return true; + } + + /** + * Reap N threads + */ + class ReapNTask: public Runnable { + + public: + + ReapNTask(Monitor& monitor, int& activeCount) : + _monitor(monitor), + _count(activeCount) {} + + void run() { + Synchronized s(_monitor); + + _count--; + + //std::cout << "\t\t\tthread count: " << _count << std::endl; + + if (_count == 0) { + _monitor.notify(); + } + } + + Monitor& _monitor; + + int& _count; + }; + + bool reapNThreads(int loop=1, int count=10) { + + PlatformThreadFactory threadFactory = PlatformThreadFactory(); + + Monitor* monitor = new Monitor(); + + for(int lix = 0; lix < loop; lix++) { + + int* activeCount = new int(count); + + std::set > threads; + + int tix; + + for (tix = 0; tix < count; tix++) { + try { + threads.insert(threadFactory.newThread(shared_ptr(new ReapNTask(*monitor, *activeCount)))); + } catch(SystemResourceException& e) { + std::cout << "\t\t\tfailed to create " << lix * count + tix << " thread " << e.what() << std::endl; + throw e; + } + } + + tix = 0; + for (std::set >::const_iterator thread = threads.begin(); thread != threads.end(); tix++, ++thread) { + + try { + (*thread)->start(); + } catch(SystemResourceException& e) { + std::cout << "\t\t\tfailed to start " << lix * count + tix << " thread " << e.what() << std::endl; + throw e; + } + } + + { + Synchronized s(*monitor); + while (*activeCount > 0) { + monitor->wait(1000); + } + } + delete activeCount; + std::cout << "\t\t\treaped " << lix * count << " threads" << std::endl; + } + + std::cout << "\t\t\tSuccess!" << std::endl; + + return true; + } + + class SynchStartTask: public Runnable { + + public: + + enum STATE { + UNINITIALIZED, + STARTING, + STARTED, + STOPPING, + STOPPED + }; + + SynchStartTask(Monitor& monitor, volatile STATE& state) : + _monitor(monitor), + _state(state) {} + + void run() { + { + Synchronized s(_monitor); + if (_state == SynchStartTask::STARTING) { + _state = SynchStartTask::STARTED; + _monitor.notify(); + } + } + + { + Synchronized s(_monitor); + while (_state == SynchStartTask::STARTED) { + _monitor.wait(); + } + + if (_state == SynchStartTask::STOPPING) { + _state = SynchStartTask::STOPPED; + _monitor.notifyAll(); + } + } + } + + private: + Monitor& _monitor; + volatile STATE& _state; + }; + + bool synchStartTest() { + + Monitor monitor; + + SynchStartTask::STATE state = SynchStartTask::UNINITIALIZED; + + shared_ptr task = shared_ptr(new SynchStartTask(monitor, state)); + + PlatformThreadFactory threadFactory = PlatformThreadFactory(); + + shared_ptr thread = threadFactory.newThread(task); + + if (state == SynchStartTask::UNINITIALIZED) { + + state = SynchStartTask::STARTING; + + thread->start(); + } + + { + Synchronized s(monitor); + while (state == SynchStartTask::STARTING) { + monitor.wait(); + } + } + + assert(state != SynchStartTask::STARTING); + + { + Synchronized s(monitor); + + try { + monitor.wait(100); + } catch(TimedOutException& e) { + } + + if (state == SynchStartTask::STARTED) { + + state = SynchStartTask::STOPPING; + + monitor.notify(); + } + + while (state == SynchStartTask::STOPPING) { + monitor.wait(); + } + } + + assert(state == SynchStartTask::STOPPED); + + bool success = true; + + std::cout << "\t\t\t" << (success ? "Success" : "Failure") << "!" << std::endl; + + return true; + } + + /** See how accurate monitor timeout is. */ + + bool monitorTimeoutTest(size_t count=1000, int64_t timeout=10) { + + Monitor monitor; + + int64_t startTime = Util::currentTime(); + + for (size_t ix = 0; ix < count; ix++) { + { + Synchronized s(monitor); + try { + monitor.wait(timeout); + } catch(TimedOutException& e) { + } + } + } + + int64_t endTime = Util::currentTime(); + + double error = ((endTime - startTime) - (count * timeout)) / (double)(count * timeout); + + if (error < 0.0) { + + error *= 1.0; + } + + bool success = error < ThreadFactoryTests::ERROR; + + std::cout << "\t\t\t" << (success ? "Success" : "Failure") << "! expected time: " << count * timeout << "ms elapsed time: "<< endTime - startTime << "ms error%: " << error * 100.0 << std::endl; + + return success; + } + + + class FloodTask : public Runnable { + public: + + FloodTask(const size_t id) :_id(id) {} + ~FloodTask(){ + if(_id % 1000 == 0) { + std::cout << "\t\tthread " << _id << " done" << std::endl; + } + } + + void run(){ + if(_id % 1000 == 0) { + std::cout << "\t\tthread " << _id << " started" << std::endl; + } + + usleep(1); + } + const size_t _id; + }; + + void foo(PlatformThreadFactory *tf) { + (void) tf; + } + + bool floodNTest(size_t loop=1, size_t count=100000) { + + bool success = false; + + for(size_t lix = 0; lix < loop; lix++) { + + PlatformThreadFactory threadFactory = PlatformThreadFactory(); + threadFactory.setDetached(true); + + for(size_t tix = 0; tix < count; tix++) { + + try { + + shared_ptr task(new FloodTask(lix * count + tix )); + + shared_ptr thread = threadFactory.newThread(task); + + thread->start(); + + usleep(1); + + } catch (TException& e) { + + std::cout << "\t\t\tfailed to start " << lix * count + tix << " thread " << e.what() << std::endl; + + return success; + } + } + + std::cout << "\t\t\tflooded " << (lix + 1) * count << " threads" << std::endl; + + success = true; + } + + return success; + } +}; + +const double ThreadFactoryTests::ERROR = .20; + +}}}} // apache::thrift::concurrency::test + diff --git a/sg_agent/thrid_party/thrift/include/concurrency/test/ThreadManagerTests.h b/sg_agent/thrid_party/thrift/include/concurrency/test/ThreadManagerTests.h new file mode 100644 index 0000000..e12201c --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/test/ThreadManagerTests.h @@ -0,0 +1,381 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace apache { namespace thrift { namespace concurrency { namespace test { + +using namespace apache::thrift::concurrency; + +/** + * ThreadManagerTests class + * + * @version $Id:$ + */ +class ThreadManagerTests { + +public: + + static const double ERROR; + + class Task: public Runnable { + + public: + + Task(Monitor& monitor, size_t& count, int64_t timeout) : + _monitor(monitor), + _count(count), + _timeout(timeout), + _done(false) {} + + void run() { + + _startTime = Util::currentTime(); + + { + Synchronized s(_sleep); + + try { + _sleep.wait(_timeout); + } catch(TimedOutException& e) { + ; + }catch(...) { + assert(0); + } + } + + _endTime = Util::currentTime(); + + _done = true; + + { + Synchronized s(_monitor); + + // std::cout << "Thread " << _count << " completed " << std::endl; + + _count--; + + if (_count == 0) { + + _monitor.notify(); + } + } + } + + Monitor& _monitor; + size_t& _count; + int64_t _timeout; + int64_t _startTime; + int64_t _endTime; + bool _done; + Monitor _sleep; + }; + + /** + * Dispatch count tasks, each of which blocks for timeout milliseconds then + * completes. Verify that all tasks completed and that thread manager cleans + * up properly on delete. + */ + bool loadTest(size_t count=100, int64_t timeout=100LL, size_t workerCount=4) { + + Monitor monitor; + + size_t activeCount = count; + + shared_ptr threadManager = ThreadManager::newSimpleThreadManager(workerCount); + + shared_ptr threadFactory = shared_ptr(new PlatformThreadFactory()); + +#ifndef USE_BOOST_THREAD + threadFactory->setPriority(PosixThreadFactory::HIGHEST); +#endif + threadManager->threadFactory(threadFactory); + + threadManager->start(); + + std::set > tasks; + + for (size_t ix = 0; ix < count; ix++) { + + tasks.insert(shared_ptr(new ThreadManagerTests::Task(monitor, activeCount, timeout))); + } + + int64_t time00 = Util::currentTime(); + + for (std::set >::iterator ix = tasks.begin(); ix != tasks.end(); ix++) { + + threadManager->add(*ix); + } + + { + Synchronized s(monitor); + + while(activeCount > 0) { + + monitor.wait(); + } + } + + int64_t time01 = Util::currentTime(); + + int64_t firstTime = 9223372036854775807LL; + int64_t lastTime = 0; + + double averageTime = 0; + int64_t minTime = 9223372036854775807LL; + int64_t maxTime = 0; + + for (std::set >::iterator ix = tasks.begin(); ix != tasks.end(); ix++) { + + shared_ptr task = *ix; + + int64_t delta = task->_endTime - task->_startTime; + + assert(delta > 0); + + if (task->_startTime < firstTime) { + firstTime = task->_startTime; + } + + if (task->_endTime > lastTime) { + lastTime = task->_endTime; + } + + if (delta < minTime) { + minTime = delta; + } + + if (delta > maxTime) { + maxTime = delta; + } + + averageTime+= delta; + } + + averageTime /= count; + + std::cout << "\t\t\tfirst start: " << firstTime << "ms Last end: " << lastTime << "ms min: " << minTime << "ms max: " << maxTime << "ms average: " << averageTime << "ms" << std::endl; + + double expectedTime = ((count + (workerCount - 1)) / workerCount) * timeout; + + double error = ((time01 - time00) - expectedTime) / expectedTime; + + if (error < 0) { + error*= -1.0; + } + + bool success = error < ERROR; + + std::cout << "\t\t\t" << (success ? "Success" : "Failure") << "! expected time: " << expectedTime << "ms elapsed time: "<< time01 - time00 << "ms error%: " << error * 100.0 << std::endl; + + return success; + } + + class BlockTask: public Runnable { + + public: + + BlockTask(Monitor& monitor, Monitor& bmonitor, size_t& count) : + _monitor(monitor), + _bmonitor(bmonitor), + _count(count) {} + + void run() { + { + Synchronized s(_bmonitor); + + _bmonitor.wait(); + + } + + { + Synchronized s(_monitor); + + _count--; + + if (_count == 0) { + + _monitor.notify(); + } + } + } + + Monitor& _monitor; + Monitor& _bmonitor; + size_t& _count; + }; + + /** + * Block test. Create pendingTaskCountMax tasks. Verify that we block adding the + * pendingTaskCountMax + 1th task. Verify that we unblock when a task completes */ + + bool blockTest(int64_t timeout=100LL, size_t workerCount=2) { + (void) timeout; + bool success = false; + + try { + + Monitor bmonitor; + Monitor monitor; + + size_t pendingTaskMaxCount = workerCount; + + size_t activeCounts[] = {workerCount, pendingTaskMaxCount, 1}; + + shared_ptr threadManager = ThreadManager::newSimpleThreadManager(workerCount, pendingTaskMaxCount); + + shared_ptr threadFactory = shared_ptr(new PlatformThreadFactory()); + +#ifndef USE_BOOST_THREAD + threadFactory->setPriority(PosixThreadFactory::HIGHEST); +#endif + threadManager->threadFactory(threadFactory); + + threadManager->start(); + + std::set > tasks; + + for (size_t ix = 0; ix < workerCount; ix++) { + + tasks.insert(shared_ptr(new ThreadManagerTests::BlockTask(monitor, bmonitor,activeCounts[0]))); + } + + for (size_t ix = 0; ix < pendingTaskMaxCount; ix++) { + + tasks.insert(shared_ptr(new ThreadManagerTests::BlockTask(monitor, bmonitor,activeCounts[1]))); + } + + for (std::set >::iterator ix = tasks.begin(); ix != tasks.end(); ix++) { + threadManager->add(*ix); + } + + if(!(success = (threadManager->totalTaskCount() == pendingTaskMaxCount + workerCount))) { + throw TException("Unexpected pending task count"); + } + + shared_ptr extraTask(new ThreadManagerTests::BlockTask(monitor, bmonitor, activeCounts[2])); + + try { + threadManager->add(extraTask, 1); + throw TException("Unexpected success adding task in excess of pending task count"); + } catch(TooManyPendingTasksException& e) { + throw TException("Should have timed out adding task in excess of pending task count"); + } catch(TimedOutException& e) { + // Expected result + } + + try { + threadManager->add(extraTask, -1); + throw TException("Unexpected success adding task in excess of pending task count"); + } catch(TimedOutException& e) { + throw TException("Unexpected timeout adding task in excess of pending task count"); + } catch(TooManyPendingTasksException& e) { + // Expected result + } + + std::cout << "\t\t\t" << "Pending tasks " << threadManager->pendingTaskCount() << std::endl; + + { + Synchronized s(bmonitor); + + bmonitor.notifyAll(); + } + + { + Synchronized s(monitor); + + while(activeCounts[0] != 0) { + monitor.wait(); + } + } + + std::cout << "\t\t\t" << "Pending tasks " << threadManager->pendingTaskCount() << std::endl; + + try { + threadManager->add(extraTask, 1); + } catch(TimedOutException& e) { + std::cout << "\t\t\t" << "add timed out unexpectedly" << std::endl; + throw TException("Unexpected timeout adding task"); + + } catch(TooManyPendingTasksException& e) { + std::cout << "\t\t\t" << "add encountered too many pending exepctions" << std::endl; + throw TException("Unexpected timeout adding task"); + } + + // Wake up tasks that were pending before and wait for them to complete + + { + Synchronized s(bmonitor); + + bmonitor.notifyAll(); + } + + { + Synchronized s(monitor); + + while(activeCounts[1] != 0) { + monitor.wait(); + } + } + + // Wake up the extra task and wait for it to complete + + { + Synchronized s(bmonitor); + + bmonitor.notifyAll(); + } + + { + Synchronized s(monitor); + + while(activeCounts[2] != 0) { + monitor.wait(); + } + } + + if(!(success = (threadManager->totalTaskCount() == 0))) { + throw TException("Unexpected pending task count"); + } + + } catch(TException& e) { + std::cout << "ERROR: " << e.what() << std::endl; + } + + std::cout << "\t\t\t" << (success ? "Success" : "Failure") << std::endl; + return success; + } +}; + +const double ThreadManagerTests::ERROR = .20; + +}}}} // apache::thrift::concurrency + +using namespace apache::thrift::concurrency::test; + diff --git a/sg_agent/thrid_party/thrift/include/concurrency/test/TimerManagerTests.h b/sg_agent/thrid_party/thrift/include/concurrency/test/TimerManagerTests.h new file mode 100644 index 0000000..41f1674 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/concurrency/test/TimerManagerTests.h @@ -0,0 +1,155 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include + +#include +#include + +namespace apache { namespace thrift { namespace concurrency { namespace test { + +using namespace apache::thrift::concurrency; + +/** + * ThreadManagerTests class + * + * @version $Id:$ + */ +class TimerManagerTests { + + public: + + static const double ERROR; + + class Task: public Runnable { + public: + + Task(Monitor& monitor, int64_t timeout) : + _timeout(timeout), + _startTime(Util::currentTime()), + _monitor(monitor), + _success(false), + _done(false) {} + + ~Task() { std::cerr << this << std::endl; } + + void run() { + + _endTime = Util::currentTime(); + + // Figure out error percentage + + int64_t delta = _endTime - _startTime; + + + delta = delta > _timeout ? delta - _timeout : _timeout - delta; + + float error = delta / _timeout; + + if(error < ERROR) { + _success = true; + } + + _done = true; + + std::cout << "\t\t\tTimerManagerTests::Task[" << this << "] done" << std::endl; //debug + + {Synchronized s(_monitor); + _monitor.notifyAll(); + } + } + + int64_t _timeout; + int64_t _startTime; + int64_t _endTime; + Monitor& _monitor; + bool _success; + bool _done; + }; + + /** + * This test creates two tasks and waits for the first to expire within 10% + * of the expected expiration time. It then verifies that the timer manager + * properly clean up itself and the remaining orphaned timeout task when the + * manager goes out of scope and its destructor is called. + */ + bool test00(int64_t timeout=1000LL) { + + shared_ptr orphanTask = shared_ptr(new TimerManagerTests::Task(_monitor, 10 * timeout)); + + { + + TimerManager timerManager; + + timerManager.threadFactory(shared_ptr(new PlatformThreadFactory())); + + timerManager.start(); + + assert(timerManager.state() == TimerManager::STARTED); + + // Don't create task yet, because its constructor sets the expected completion time, and we + // need to delay between inserting the two tasks into the run queue. + shared_ptr task; + + { + Synchronized s(_monitor); + + timerManager.add(orphanTask, 10 * timeout); + + try { + // Wait for 1 second in order to give timerManager a chance to start sleeping in response + // to adding orphanTask. We need to do this so we can verify that adding the second task + // kicks the dispatcher out of the current wait and starts the new 1 second wait. + _monitor.wait (1000); + assert (0 == "ERROR: This wait should time out. TimerManager dispatcher may have a problem."); + } catch (TimedOutException &ex) { + } + + task.reset (new TimerManagerTests::Task(_monitor, timeout)); + + timerManager.add(task, timeout); + + _monitor.wait(); + } + + assert(task->_done); + + + std::cout << "\t\t\t" << (task->_success ? "Success" : "Failure") << "!" << std::endl; + } + + // timerManager.stop(); This is where it happens via destructor + + assert(!orphanTask->_done); + + return true; + } + + friend class TestTask; + + Monitor _monitor; +}; + +const double TimerManagerTests::ERROR = .20; + +}}}} // apache::thrift::concurrency + diff --git a/sg_agent/thrid_party/thrift/include/processor/PeekProcessor.cpp b/sg_agent/thrid_party/thrift/include/processor/PeekProcessor.cpp new file mode 100644 index 0000000..9a9b672 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/processor/PeekProcessor.cpp @@ -0,0 +1,127 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "PeekProcessor.h" + +using namespace apache::thrift::transport; +using namespace apache::thrift::protocol; +using namespace apache::thrift; + +namespace apache { namespace thrift { namespace processor { + +PeekProcessor::PeekProcessor() { + memoryBuffer_.reset(new TMemoryBuffer()); + targetTransport_ = memoryBuffer_; +} +PeekProcessor::~PeekProcessor() {} + +void PeekProcessor::initialize(boost::shared_ptr actualProcessor, + boost::shared_ptr protocolFactory, + boost::shared_ptr transportFactory) { + actualProcessor_ = actualProcessor; + pipedProtocol_ = protocolFactory->getProtocol(targetTransport_); + transportFactory_ = transportFactory; + transportFactory_->initializeTargetTransport(targetTransport_); +} + +boost::shared_ptr PeekProcessor::getPipedTransport(boost::shared_ptr in) { + return transportFactory_->getTransport(in); +} + +void PeekProcessor::setTargetTransport(boost::shared_ptr targetTransport) { + targetTransport_ = targetTransport; + if (boost::dynamic_pointer_cast(targetTransport_)) { + memoryBuffer_ = boost::dynamic_pointer_cast(targetTransport); + } else if (boost::dynamic_pointer_cast(targetTransport_)) { + memoryBuffer_ = boost::dynamic_pointer_cast(boost::dynamic_pointer_cast(targetTransport_)->getTargetTransport()); + } + + if (!memoryBuffer_) { + throw TException("Target transport must be a TMemoryBuffer or a TPipedTransport with TMemoryBuffer"); + } +} + +bool PeekProcessor::process(boost::shared_ptr in, + boost::shared_ptr out, + void* connectionContext) { + + std::string fname; + TMessageType mtype; + int32_t seqid; + in->readMessageBegin(fname, mtype, seqid); + + if (mtype != T_CALL) { + throw TException("Unexpected message type"); + } + + // Peek at the name + peekName(fname); + + TType ftype; + int16_t fid; + while (true) { + in->readFieldBegin(fname, ftype, fid); + if (ftype == T_STOP) { + break; + } + + // Peek at the variable + peek(in, ftype, fid); + in->readFieldEnd(); + } + in->readMessageEnd(); + in->getTransport()->readEnd(); + + // + // All the data is now in memoryBuffer_ and ready to be processed + // + + // Let's first take a peek at the full data in memory + uint8_t* buffer; + uint32_t size; + memoryBuffer_->getBuffer(&buffer, &size); + peekBuffer(buffer, size); + + // Done peeking at variables + peekEnd(); + + bool ret = actualProcessor_->process(pipedProtocol_, out, connectionContext); + memoryBuffer_->resetBuffer(); + return ret; +} + +void PeekProcessor::peekName(const std::string& fname) { + (void) fname; +} + +void PeekProcessor::peekBuffer(uint8_t* buffer, uint32_t size) { + (void) buffer; + (void) size; +} + +void PeekProcessor::peek(boost::shared_ptr in, + TType ftype, + int16_t fid) { + (void) fid; + in->skip(ftype); +} + +void PeekProcessor::peekEnd() {} + +}}} diff --git a/sg_agent/thrid_party/thrift/include/processor/PeekProcessor.h b/sg_agent/thrid_party/thrift/include/processor/PeekProcessor.h new file mode 100644 index 0000000..cb703f6 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/processor/PeekProcessor.h @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef PEEKPROCESSOR_H +#define PEEKPROCESSOR_H + +#include +#include +#include +#include +#include +#include + +namespace apache { namespace thrift { namespace processor { + +/* + * Class for peeking at the raw data that is being processed by another processor + * and gives the derived class a chance to change behavior accordingly + * + */ +class PeekProcessor : public apache::thrift::TProcessor { + + public: + PeekProcessor(); + virtual ~PeekProcessor(); + + // Input here: actualProcessor - the underlying processor + // protocolFactory - the protocol factory used to wrap the memory buffer + // transportFactory - this TPipedTransportFactory is used to wrap the source transport + // via a call to getPipedTransport + void initialize(boost::shared_ptr actualProcessor, + boost::shared_ptr protocolFactory, + boost::shared_ptr transportFactory); + + boost::shared_ptr getPipedTransport(boost::shared_ptr in); + + void setTargetTransport(boost::shared_ptr targetTransport); + + virtual bool process(boost::shared_ptr in, + boost::shared_ptr out, + void* connectionContext); + + // The following three functions can be overloaded by child classes to + // achieve desired peeking behavior + virtual void peekName(const std::string& fname); + virtual void peekBuffer(uint8_t* buffer, uint32_t size); + virtual void peek(boost::shared_ptr in, + apache::thrift::protocol::TType ftype, + int16_t fid); + virtual void peekEnd(); + + private: + boost::shared_ptr actualProcessor_; + boost::shared_ptr pipedProtocol_; + boost::shared_ptr transportFactory_; + boost::shared_ptr memoryBuffer_; + boost::shared_ptr targetTransport_; +}; + +}}} // apache::thrift::processor + +#endif diff --git a/sg_agent/thrid_party/thrift/include/processor/StatsProcessor.h b/sg_agent/thrid_party/thrift/include/processor/StatsProcessor.h new file mode 100644 index 0000000..8600c6b --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/processor/StatsProcessor.h @@ -0,0 +1,266 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef STATSPROCESSOR_H +#define STATSPROCESSOR_H + +#include +#include +#include +#include + +namespace apache { namespace thrift { namespace processor { + +/* + * Class for keeping track of function call statistics and printing them if desired + * + */ +class StatsProcessor : public apache::thrift::TProcessor { +public: + StatsProcessor(bool print, bool frequency) + : print_(print), + frequency_(frequency) + {} + virtual ~StatsProcessor() {}; + + virtual bool process(boost::shared_ptr piprot, + boost::shared_ptr poprot, + void* serverContext) { + + piprot_ = piprot; + + std::string fname; + apache::thrift::protocol::TMessageType mtype; + int32_t seqid; + + piprot_->readMessageBegin(fname, mtype, seqid); + if (mtype != apache::thrift::protocol::T_CALL) { + if (print_) { + printf("Unknown message type\n"); + } + throw apache::thrift::TException("Unexpected message type"); + } + if (print_) { + printf("%s (", fname.c_str()); + } + if (frequency_) { + if (frequency_map_.find(fname) != frequency_map_.end()) { + frequency_map_[fname]++; + } else { + frequency_map_[fname] = 1; + } + } + + apache::thrift::protocol::TType ftype; + int16_t fid; + + while (true) { + piprot_->readFieldBegin(fname, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + + printAndPassToBuffer(ftype); + if (print_) { + printf(", "); + } + } + + if (print_) { + printf("\b\b)\n"); + } + return true; + } + + const std::map& get_frequency_map() { + return frequency_map_; + } + +protected: + void printAndPassToBuffer(apache::thrift::protocol::TType ftype) { + switch (ftype) { + case apache::thrift::protocol::T_BOOL: + { + bool boolv; + piprot_->readBool(boolv); + if (print_) { + printf("%d", boolv); + } + } + break; + case apache::thrift::protocol::T_BYTE: + { + int8_t bytev; + piprot_->readByte(bytev); + if (print_) { + printf("%d", bytev); + } + } + break; + case apache::thrift::protocol::T_I16: + { + int16_t i16; + piprot_->readI16(i16); + if (print_) { + printf("%d", i16); + } + } + break; + case apache::thrift::protocol::T_I32: + { + int32_t i32; + piprot_->readI32(i32); + if (print_) { + printf("%d", i32); + } + } + break; + case apache::thrift::protocol::T_I64: + { + int64_t i64; + piprot_->readI64(i64); + if (print_) { + printf("%ld", i64); + } + } + break; + case apache::thrift::protocol::T_DOUBLE: + { + double dub; + piprot_->readDouble(dub); + if (print_) { + printf("%f", dub); + } + } + break; + case apache::thrift::protocol::T_STRING: + { + std::string str; + piprot_->readString(str); + if (print_) { + printf("%s", str.c_str()); + } + } + break; + case apache::thrift::protocol::T_STRUCT: + { + std::string name; + int16_t fid; + apache::thrift::protocol::TType ftype; + piprot_->readStructBegin(name); + if (print_) { + printf("<"); + } + while (true) { + piprot_->readFieldBegin(name, ftype, fid); + if (ftype == apache::thrift::protocol::T_STOP) { + break; + } + printAndPassToBuffer(ftype); + if (print_) { + printf(","); + } + piprot_->readFieldEnd(); + } + piprot_->readStructEnd(); + if (print_) { + printf("\b>"); + } + } + break; + case apache::thrift::protocol::T_MAP: + { + apache::thrift::protocol::TType keyType; + apache::thrift::protocol::TType valType; + uint32_t i, size; + piprot_->readMapBegin(keyType, valType, size); + if (print_) { + printf("{"); + } + for (i = 0; i < size; i++) { + printAndPassToBuffer(keyType); + if (print_) { + printf("=>"); + } + printAndPassToBuffer(valType); + if (print_) { + printf(","); + } + } + piprot_->readMapEnd(); + if (print_) { + printf("\b}"); + } + } + break; + case apache::thrift::protocol::T_SET: + { + apache::thrift::protocol::TType elemType; + uint32_t i, size; + piprot_->readSetBegin(elemType, size); + if (print_) { + printf("{"); + } + for (i = 0; i < size; i++) { + printAndPassToBuffer(elemType); + if (print_) { + printf(","); + } + } + piprot_->readSetEnd(); + if (print_) { + printf("\b}"); + } + } + break; + case apache::thrift::protocol::T_LIST: + { + apache::thrift::protocol::TType elemType; + uint32_t i, size; + piprot_->readListBegin(elemType, size); + if (print_) { + printf("["); + } + for (i = 0; i < size; i++) { + printAndPassToBuffer(elemType); + if (print_) { + printf(","); + } + } + piprot_->readListEnd(); + if (print_) { + printf("\b]"); + } + } + break; + default: + break; + } + } + + boost::shared_ptr piprot_; + std::map frequency_map_; + + bool print_; + bool frequency_; +}; + +}}} // apache::thrift::processor + +#endif diff --git a/sg_agent/thrid_party/thrift/include/protocol/TBase64Utils.cpp b/sg_agent/thrid_party/thrift/include/protocol/TBase64Utils.cpp new file mode 100644 index 0000000..14481c4 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/protocol/TBase64Utils.cpp @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "TBase64Utils.h" + +#include + +using std::string; + +namespace apache { namespace thrift { namespace protocol { + + +static const uint8_t *kBase64EncodeTable = (const uint8_t *) + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +void base64_encode(const uint8_t *in, uint32_t len, uint8_t *buf) { + buf[0] = kBase64EncodeTable[(in[0] >> 2) & 0x3F]; + if (len == 3) { + buf[1] = kBase64EncodeTable[((in[0] << 4) + (in[1] >> 4)) & 0x3f]; + buf[2] = kBase64EncodeTable[((in[1] << 2) + (in[2] >> 6)) & 0x3f]; + buf[3] = kBase64EncodeTable[in[2] & 0x3f]; + } else if (len == 2) { + buf[1] = kBase64EncodeTable[((in[0] << 4) + (in[1] >> 4)) & 0x3f]; + buf[2] = kBase64EncodeTable[(in[1] << 2) & 0x3f]; + } else { // len == 1 + buf[1] = kBase64EncodeTable[(in[0] << 4) & 0x3f]; + } +} + +static const uint8_t kBase64DecodeTable[256] ={ + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, + 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, + 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, + -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, + 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, +}; + +void base64_decode(uint8_t *buf, uint32_t len) { + buf[0] = (kBase64DecodeTable[buf[0]] << 2) | + (kBase64DecodeTable[buf[1]] >> 4); + if (len > 2) { + buf[1] = ((kBase64DecodeTable[buf[1]] << 4) & 0xf0) | + (kBase64DecodeTable[buf[2]] >> 2); + if (len > 3) { + buf[2] = ((kBase64DecodeTable[buf[2]] << 6) & 0xc0) | + (kBase64DecodeTable[buf[3]]); + } + } +} + + +}}} // apache::thrift::protocol diff --git a/sg_agent/thrid_party/thrift/include/protocol/TBase64Utils.h b/sg_agent/thrid_party/thrift/include/protocol/TBase64Utils.h new file mode 100644 index 0000000..3def733 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/protocol/TBase64Utils.h @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_PROTOCOL_TBASE64UTILS_H_ +#define _THRIFT_PROTOCOL_TBASE64UTILS_H_ + +#include +#include + +namespace apache { namespace thrift { namespace protocol { + +// in must be at least len bytes +// len must be 1, 2, or 3 +// buf must be a buffer of at least 4 bytes and may not overlap in +// the data is not padded with '='; the caller can do this if desired +void base64_encode(const uint8_t *in, uint32_t len, uint8_t *buf); + +// buf must be a buffer of at least 4 bytes and contain base64 encoded values +// buf will be changed to contain output bytes +// len is number of bytes to consume from input (must be 2, 3, or 4) +// no '=' padding should be included in the input +void base64_decode(uint8_t *buf, uint32_t len); + +}}} // apache::thrift::protocol + +#endif // #define _THRIFT_PROTOCOL_TBASE64UTILS_H_ diff --git a/sg_agent/thrid_party/thrift/include/protocol/TBinaryProtocol.h b/sg_agent/thrid_party/thrift/include/protocol/TBinaryProtocol.h new file mode 100644 index 0000000..edb8834 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/protocol/TBinaryProtocol.h @@ -0,0 +1,279 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ 1 + +#include "TProtocol.h" +#include "TVirtualProtocol.h" + +#include + +namespace apache { namespace thrift { namespace protocol { + +/** + * The default binary protocol for thrift. Writes all data in a very basic + * binary format, essentially just spitting out the raw bytes. + * + */ +template +class TBinaryProtocolT + : public TVirtualProtocol< TBinaryProtocolT > { + protected: + static const int32_t VERSION_MASK = 0xffff0000; + static const int32_t VERSION_1 = 0x80010000; + // VERSION_2 (0x80020000) is taken by TDenseProtocol. + + public: + TBinaryProtocolT(boost::shared_ptr trans) : + TVirtualProtocol< TBinaryProtocolT >(trans), + trans_(trans.get()), + string_limit_(0), + container_limit_(0), + strict_read_(false), + strict_write_(true), + string_buf_(NULL), + string_buf_size_(0) {} + + TBinaryProtocolT(boost::shared_ptr trans, + int32_t string_limit, + int32_t container_limit, + bool strict_read, + bool strict_write) : + TVirtualProtocol< TBinaryProtocolT >(trans), + trans_(trans.get()), + string_limit_(string_limit), + container_limit_(container_limit), + strict_read_(strict_read), + strict_write_(strict_write), + string_buf_(NULL), + string_buf_size_(0) {} + + ~TBinaryProtocolT() { + if (string_buf_ != NULL) { + std::free(string_buf_); + string_buf_size_ = 0; + } + } + + void setStringSizeLimit(int32_t string_limit) { + string_limit_ = string_limit; + } + + void setContainerSizeLimit(int32_t container_limit) { + container_limit_ = container_limit; + } + + void setStrict(bool strict_read, bool strict_write) { + strict_read_ = strict_read; + strict_write_ = strict_write; + } + + /** + * Writing functions. + */ + + /*ol*/ uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid); + + /*ol*/ uint32_t writeMessageEnd(); + + + inline uint32_t writeStructBegin(const char* name); + + inline uint32_t writeStructEnd(); + + inline uint32_t writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId); + + inline uint32_t writeFieldEnd(); + + inline uint32_t writeFieldStop(); + + inline uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size); + + inline uint32_t writeMapEnd(); + + inline uint32_t writeListBegin(const TType elemType, const uint32_t size); + + inline uint32_t writeListEnd(); + + inline uint32_t writeSetBegin(const TType elemType, const uint32_t size); + + inline uint32_t writeSetEnd(); + + inline uint32_t writeBool(const bool value); + + inline uint32_t writeByte(const int8_t byte); + + inline uint32_t writeI16(const int16_t i16); + + inline uint32_t writeI32(const int32_t i32); + + inline uint32_t writeI64(const int64_t i64); + + inline uint32_t writeDouble(const double dub); + + inline uint32_t writeString(const std::string& str); + + inline uint32_t writeBinary(const std::string& str); + + /** + * Reading functions + */ + + + /*ol*/ uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid); + + /*ol*/ uint32_t readMessageEnd(); + + inline uint32_t readStructBegin(std::string& name); + + inline uint32_t readStructEnd(); + + inline uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId); + + inline uint32_t readFieldEnd(); + + inline uint32_t readMapBegin(TType& keyType, + TType& valType, + uint32_t& size); + + inline uint32_t readMapEnd(); + + inline uint32_t readListBegin(TType& elemType, uint32_t& size); + + inline uint32_t readListEnd(); + + inline uint32_t readSetBegin(TType& elemType, uint32_t& size); + + inline uint32_t readSetEnd(); + + inline uint32_t readBool(bool& value); + // Provide the default readBool() implementation for std::vector + using TVirtualProtocol< TBinaryProtocolT >::readBool; + + inline uint32_t readByte(int8_t& byte); + + inline uint32_t readI16(int16_t& i16); + + inline uint32_t readI32(int32_t& i32); + + inline uint32_t readI64(int64_t& i64); + + inline uint32_t readDouble(double& dub); + + inline uint32_t readString(std::string& str); + + inline uint32_t readBinary(std::string& str); + + protected: + uint32_t readStringBody(std::string& str, int32_t sz); + + Transport_* trans_; + + int32_t string_limit_; + int32_t container_limit_; + + // Enforce presence of version identifier + bool strict_read_; + bool strict_write_; + + // Buffer for reading strings, save for the lifetime of the protocol to + // avoid memory churn allocating memory on every string read + uint8_t* string_buf_; + int32_t string_buf_size_; + +}; + +typedef TBinaryProtocolT TBinaryProtocol; + +/** + * Constructs binary protocol handlers + */ +template +class TBinaryProtocolFactoryT : public TProtocolFactory { + public: + TBinaryProtocolFactoryT() : + string_limit_(0), + container_limit_(0), + strict_read_(false), + strict_write_(true) {} + + TBinaryProtocolFactoryT(int32_t string_limit, int32_t container_limit, + bool strict_read, bool strict_write) : + string_limit_(string_limit), + container_limit_(container_limit), + strict_read_(strict_read), + strict_write_(strict_write) {} + + virtual ~TBinaryProtocolFactoryT() {} + + void setStringSizeLimit(int32_t string_limit) { + string_limit_ = string_limit; + } + + void setContainerSizeLimit(int32_t container_limit) { + container_limit_ = container_limit; + } + + void setStrict(bool strict_read, bool strict_write) { + strict_read_ = strict_read; + strict_write_ = strict_write; + } + + boost::shared_ptr getProtocol(boost::shared_ptr trans) { + boost::shared_ptr specific_trans = + boost::dynamic_pointer_cast(trans); + TProtocol* prot; + if (specific_trans) { + prot = new TBinaryProtocolT(specific_trans, string_limit_, + container_limit_, strict_read_, + strict_write_); + } else { + prot = new TBinaryProtocol(trans, string_limit_, container_limit_, + strict_read_, strict_write_); + } + + return boost::shared_ptr(prot); + } + + private: + int32_t string_limit_; + int32_t container_limit_; + bool strict_read_; + bool strict_write_; + +}; + +typedef TBinaryProtocolFactoryT TBinaryProtocolFactory; + +}}} // apache::thrift::protocol + +#include "TBinaryProtocol.tcc" + +#endif // #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_H_ diff --git a/sg_agent/thrid_party/thrift/include/protocol/TBinaryProtocol.tcc b/sg_agent/thrid_party/thrift/include/protocol/TBinaryProtocol.tcc new file mode 100644 index 0000000..721e897 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/protocol/TBinaryProtocol.tcc @@ -0,0 +1,460 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_ +#define _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_ 1 + +#include "TBinaryProtocol.h" + +#include + + +namespace apache { namespace thrift { namespace protocol { + +template +uint32_t TBinaryProtocolT::writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid) { + if (this->strict_write_) { + int32_t version = (VERSION_1) | ((int32_t)messageType); + uint32_t wsize = 0; + wsize += writeI32(version); + wsize += writeString(name); + wsize += writeI32(seqid); + return wsize; + } else { + uint32_t wsize = 0; + wsize += writeString(name); + wsize += writeByte((int8_t)messageType); + wsize += writeI32(seqid); + return wsize; + } +} + +template +uint32_t TBinaryProtocolT::writeMessageEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::writeStructBegin(const char* name) { + (void) name; + return 0; +} + +template +uint32_t TBinaryProtocolT::writeStructEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId) { + (void) name; + uint32_t wsize = 0; + wsize += writeByte((int8_t)fieldType); + wsize += writeI16(fieldId); + return wsize; +} + +template +uint32_t TBinaryProtocolT::writeFieldEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::writeFieldStop() { + return + writeByte((int8_t)T_STOP); +} + +template +uint32_t TBinaryProtocolT::writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size) { + uint32_t wsize = 0; + wsize += writeByte((int8_t)keyType); + wsize += writeByte((int8_t)valType); + wsize += writeI32((int32_t)size); + return wsize; +} + +template +uint32_t TBinaryProtocolT::writeMapEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::writeListBegin(const TType elemType, + const uint32_t size) { + uint32_t wsize = 0; + wsize += writeByte((int8_t) elemType); + wsize += writeI32((int32_t)size); + return wsize; +} + +template +uint32_t TBinaryProtocolT::writeListEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::writeSetBegin(const TType elemType, + const uint32_t size) { + uint32_t wsize = 0; + wsize += writeByte((int8_t)elemType); + wsize += writeI32((int32_t)size); + return wsize; +} + +template +uint32_t TBinaryProtocolT::writeSetEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::writeBool(const bool value) { + uint8_t tmp = value ? 1 : 0; + this->trans_->write(&tmp, 1); + return 1; +} + +template +uint32_t TBinaryProtocolT::writeByte(const int8_t byte) { + this->trans_->write((uint8_t*)&byte, 1); + return 1; +} + +template +uint32_t TBinaryProtocolT::writeI16(const int16_t i16) { + int16_t net = (int16_t)htons(i16); + this->trans_->write((uint8_t*)&net, 2); + return 2; +} + +template +uint32_t TBinaryProtocolT::writeI32(const int32_t i32) { + int32_t net = (int32_t)htonl(i32); + this->trans_->write((uint8_t*)&net, 4); + return 4; +} + +template +uint32_t TBinaryProtocolT::writeI64(const int64_t i64) { + int64_t net = (int64_t)htonll(i64); + this->trans_->write((uint8_t*)&net, 8); + return 8; +} + +template +uint32_t TBinaryProtocolT::writeDouble(const double dub) { + BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); + BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + + uint64_t bits = bitwise_cast(dub); + bits = htonll(bits); + this->trans_->write((uint8_t*)&bits, 8); + return 8; +} + + +template +uint32_t TBinaryProtocolT::writeString(const std::string& str) { + uint32_t size = str.size(); + uint32_t result = writeI32((int32_t)size); + if (size > 0) { + this->trans_->write((uint8_t*)str.data(), size); + } + return result + size; +} + +template +uint32_t TBinaryProtocolT::writeBinary(const std::string& str) { + return TBinaryProtocolT::writeString(str); +} + +/** + * Reading functions + */ + +template +uint32_t TBinaryProtocolT::readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid) { + uint32_t result = 0; + int32_t sz; + result += readI32(sz); + + if (sz < 0) { + // Check for correct version number + int32_t version = sz & VERSION_MASK; + if (version != VERSION_1) { + throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier"); + } + messageType = (TMessageType)(sz & 0x000000ff); + result += readString(name); + result += readI32(seqid); + } else { + if (this->strict_read_) { + throw TProtocolException(TProtocolException::BAD_VERSION, "No version identifier... old protocol client in strict mode?"); + } else { + // Handle pre-versioned input + int8_t type; + result += readStringBody(name, sz); + result += readByte(type); + messageType = (TMessageType)type; + result += readI32(seqid); + } + } + return result; +} + +template +uint32_t TBinaryProtocolT::readMessageEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::readStructBegin(std::string& name) { + name = ""; + return 0; +} + +template +uint32_t TBinaryProtocolT::readStructEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId) { + (void) name; + uint32_t result = 0; + int8_t type; + result += readByte(type); + fieldType = (TType)type; + if (fieldType == T_STOP) { + fieldId = 0; + return result; + } + result += readI16(fieldId); + return result; +} + +template +uint32_t TBinaryProtocolT::readFieldEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::readMapBegin(TType& keyType, + TType& valType, + uint32_t& size) { + int8_t k, v; + uint32_t result = 0; + int32_t sizei; + result += readByte(k); + keyType = (TType)k; + result += readByte(v); + valType = (TType)v; + result += readI32(sizei); + if (sizei < 0) { + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } else if (this->container_limit_ && sizei > this->container_limit_) { + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + size = (uint32_t)sizei; + return result; +} + +template +uint32_t TBinaryProtocolT::readMapEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::readListBegin(TType& elemType, + uint32_t& size) { + int8_t e; + uint32_t result = 0; + int32_t sizei; + result += readByte(e); + elemType = (TType)e; + result += readI32(sizei); + if (sizei < 0) { + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } else if (this->container_limit_ && sizei > this->container_limit_) { + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + size = (uint32_t)sizei; + return result; +} + +template +uint32_t TBinaryProtocolT::readListEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::readSetBegin(TType& elemType, + uint32_t& size) { + int8_t e; + uint32_t result = 0; + int32_t sizei; + result += readByte(e); + elemType = (TType)e; + result += readI32(sizei); + if (sizei < 0) { + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } else if (this->container_limit_ && sizei > this->container_limit_) { + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + size = (uint32_t)sizei; + return result; +} + +template +uint32_t TBinaryProtocolT::readSetEnd() { + return 0; +} + +template +uint32_t TBinaryProtocolT::readBool(bool& value) { + uint8_t b[1]; + this->trans_->readAll(b, 1); + value = *(int8_t*)b != 0; + return 1; +} + +template +uint32_t TBinaryProtocolT::readByte(int8_t& byte) { + uint8_t b[1]; + this->trans_->readAll(b, 1); + byte = *(int8_t*)b; + return 1; +} + +template +uint32_t TBinaryProtocolT::readI16(int16_t& i16) { + union bytes { + uint8_t b[2]; + int16_t all; + } theBytes; + this->trans_->readAll(theBytes.b, 2); + i16 = (int16_t)ntohs(theBytes.all); + return 2; +} + +template +uint32_t TBinaryProtocolT::readI32(int32_t& i32) { + union bytes { + uint8_t b[4]; + int32_t all; + } theBytes; + this->trans_->readAll(theBytes.b, 4); + i32 = (int32_t)ntohl(theBytes.all); + return 4; +} + +template +uint32_t TBinaryProtocolT::readI64(int64_t& i64) { + union bytes { + uint8_t b[8]; + int64_t all; + } theBytes; + this->trans_->readAll(theBytes.b, 8); + i64 = (int64_t)ntohll(theBytes.all); + return 8; +} + +template +uint32_t TBinaryProtocolT::readDouble(double& dub) { + BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); + BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + + union bytes { + uint8_t b[8]; + uint64_t all; + } theBytes; + this->trans_->readAll(theBytes.b, 8); + theBytes.all = ntohll(theBytes.all); + dub = bitwise_cast(theBytes.all); + return 8; +} + +template +uint32_t TBinaryProtocolT::readString(std::string& str) { + uint32_t result; + int32_t size; + result = readI32(size); + return result + readStringBody(str, size); +} + +template +uint32_t TBinaryProtocolT::readBinary(std::string& str) { + return TBinaryProtocolT::readString(str); +} + +template +uint32_t TBinaryProtocolT::readStringBody(std::string& str, + int32_t size) { + uint32_t result = 0; + + // Catch error cases + if (size < 0) { + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } + if (this->string_limit_ > 0 && size > this->string_limit_) { + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + + // Catch empty string case + if (size == 0) { + str = ""; + return result; + } + + // Try to borrow first + const uint8_t* borrow_buf; + uint32_t got = size; + if ((borrow_buf = this->trans_->borrow(NULL, &got))) { + str.assign((const char*)borrow_buf, size); + this->trans_->consume(size); + return size; + } + + // Use the heap here to prevent stack overflow for v. large strings + if (size > this->string_buf_size_ || this->string_buf_ == NULL) { + void* new_string_buf = std::realloc(this->string_buf_, (uint32_t)size); + if (new_string_buf == NULL) { + throw std::bad_alloc(); + } + this->string_buf_ = (uint8_t*)new_string_buf; + this->string_buf_size_ = size; + } + this->trans_->readAll(this->string_buf_, size); + str = std::string((char*)this->string_buf_, size); + return (uint32_t)size; +} + +}}} // apache::thrift::protocol + +#endif // #ifndef _THRIFT_PROTOCOL_TBINARYPROTOCOL_TCC_ diff --git a/sg_agent/thrid_party/thrift/include/protocol/TCompactProtocol.h b/sg_agent/thrid_party/thrift/include/protocol/TCompactProtocol.h new file mode 100644 index 0000000..c4d1f08 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/protocol/TCompactProtocol.h @@ -0,0 +1,289 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_PROTOCOL_TCOMPACTPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TCOMPACTPROTOCOL_H_ 1 + +#include "TVirtualProtocol.h" + +#include +#include + +namespace apache { namespace thrift { namespace protocol { + +/** + * C++ Implementation of the Compact Protocol as described in THRIFT-110 + */ +template +class TCompactProtocolT + : public TVirtualProtocol< TCompactProtocolT > { + + protected: + static const int8_t PROTOCOL_ID = (int8_t)0x82; + static const int8_t VERSION_N = 1; + static const int8_t VERSION_MASK = 0x1f; // 0001 1111 + static const int8_t TYPE_MASK = (int8_t)0xE0; // 1110 0000 + static const int32_t TYPE_SHIFT_AMOUNT = 5; + + Transport_* trans_; + + /** + * (Writing) If we encounter a boolean field begin, save the TField here + * so it can have the value incorporated. + */ + struct { + const char* name; + TType fieldType; + int16_t fieldId; + } booleanField_; + + /** + * (Reading) If we read a field header, and it's a boolean field, save + * the boolean value here so that readBool can use it. + */ + struct { + bool hasBoolValue; + bool boolValue; + } boolValue_; + + /** + * Used to keep track of the last field for the current and previous structs, + * so we can do the delta stuff. + */ + + std::stack lastField_; + int16_t lastFieldId_; + + public: + TCompactProtocolT(boost::shared_ptr trans) : + TVirtualProtocol< TCompactProtocolT >(trans), + trans_(trans.get()), + lastFieldId_(0), + string_limit_(0), + string_buf_(NULL), + string_buf_size_(0), + container_limit_(0) { + booleanField_.name = NULL; + boolValue_.hasBoolValue = false; + } + + TCompactProtocolT(boost::shared_ptr trans, + int32_t string_limit, + int32_t container_limit) : + TVirtualProtocol< TCompactProtocolT >(trans), + trans_(trans.get()), + lastFieldId_(0), + string_limit_(string_limit), + string_buf_(NULL), + string_buf_size_(0), + container_limit_(container_limit) { + booleanField_.name = NULL; + boolValue_.hasBoolValue = false; + } + + ~TCompactProtocolT() { + free(string_buf_); + } + + + /** + * Writing functions + */ + + virtual uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid); + + uint32_t writeStructBegin(const char* name); + + uint32_t writeStructEnd(); + + uint32_t writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId); + + uint32_t writeFieldStop(); + + uint32_t writeListBegin(const TType elemType, + const uint32_t size); + + uint32_t writeSetBegin(const TType elemType, + const uint32_t size); + + virtual uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size); + + uint32_t writeBool(const bool value); + + uint32_t writeByte(const int8_t byte); + + uint32_t writeI16(const int16_t i16); + + uint32_t writeI32(const int32_t i32); + + uint32_t writeI64(const int64_t i64); + + uint32_t writeDouble(const double dub); + + uint32_t writeString(const std::string& str); + + uint32_t writeBinary(const std::string& str); + + /** + * These methods are called by structs, but don't actually have any wired + * output or purpose + */ + virtual uint32_t writeMessageEnd() { return 0; } + uint32_t writeMapEnd() { return 0; } + uint32_t writeListEnd() { return 0; } + uint32_t writeSetEnd() { return 0; } + uint32_t writeFieldEnd() { return 0; } + + protected: + int32_t writeFieldBeginInternal(const char* name, + const TType fieldType, + const int16_t fieldId, + int8_t typeOverride); + uint32_t writeCollectionBegin(int8_t elemType, int32_t size); + uint32_t writeVarint32(uint32_t n); + uint32_t writeVarint64(uint64_t n); + uint64_t i64ToZigzag(const int64_t l); + uint32_t i32ToZigzag(const int32_t n); + inline int8_t getCompactType(int8_t ttype); + + public: + uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid); + + uint32_t readStructBegin(std::string& name); + + uint32_t readStructEnd(); + + uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId); + + uint32_t readMapBegin(TType& keyType, + TType& valType, + uint32_t& size); + + uint32_t readListBegin(TType& elemType, + uint32_t& size); + + uint32_t readSetBegin(TType& elemType, + uint32_t& size); + + uint32_t readBool(bool& value); + // Provide the default readBool() implementation for std::vector + using TVirtualProtocol< TCompactProtocolT >::readBool; + + uint32_t readByte(int8_t& byte); + + uint32_t readI16(int16_t& i16); + + uint32_t readI32(int32_t& i32); + + uint32_t readI64(int64_t& i64); + + uint32_t readDouble(double& dub); + + uint32_t readString(std::string& str); + + uint32_t readBinary(std::string& str); + + /* + *These methods are here for the struct to call, but don't have any wire + * encoding. + */ + uint32_t readMessageEnd() { return 0; } + uint32_t readFieldEnd() { return 0; } + uint32_t readMapEnd() { return 0; } + uint32_t readListEnd() { return 0; } + uint32_t readSetEnd() { return 0; } + + protected: + uint32_t readVarint32(int32_t& i32); + uint32_t readVarint64(int64_t& i64); + int32_t zigzagToI32(uint32_t n); + int64_t zigzagToI64(uint64_t n); + TType getTType(int8_t type); + + // Buffer for reading strings, save for the lifetime of the protocol to + // avoid memory churn allocating memory on every string read + int32_t string_limit_; + uint8_t* string_buf_; + int32_t string_buf_size_; + int32_t container_limit_; +}; + +typedef TCompactProtocolT TCompactProtocol; + +/** + * Constructs compact protocol handlers + */ +template +class TCompactProtocolFactoryT : public TProtocolFactory { + public: + TCompactProtocolFactoryT() : + string_limit_(0), + container_limit_(0) {} + + TCompactProtocolFactoryT(int32_t string_limit, int32_t container_limit) : + string_limit_(string_limit), + container_limit_(container_limit) {} + + virtual ~TCompactProtocolFactoryT() {} + + void setStringSizeLimit(int32_t string_limit) { + string_limit_ = string_limit; + } + + void setContainerSizeLimit(int32_t container_limit) { + container_limit_ = container_limit; + } + + boost::shared_ptr getProtocol(boost::shared_ptr trans) { + boost::shared_ptr specific_trans = + boost::dynamic_pointer_cast(trans); + TProtocol* prot; + if (specific_trans) { + prot = new TCompactProtocolT(specific_trans, string_limit_, + container_limit_); + } else { + prot = new TCompactProtocol(trans, string_limit_, container_limit_); + } + + return boost::shared_ptr(prot); + } + + private: + int32_t string_limit_; + int32_t container_limit_; + +}; + +typedef TCompactProtocolFactoryT TCompactProtocolFactory; + +}}} // apache::thrift::protocol + +#include "TCompactProtocol.tcc" + +#endif diff --git a/sg_agent/thrid_party/thrift/include/protocol/TCompactProtocol.tcc b/sg_agent/thrid_party/thrift/include/protocol/TCompactProtocol.tcc new file mode 100644 index 0000000..55b784f --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/protocol/TCompactProtocol.tcc @@ -0,0 +1,811 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef _THRIFT_PROTOCOL_TCOMPACTPROTOCOL_TCC_ +#define _THRIFT_PROTOCOL_TCOMPACTPROTOCOL_TCC_ 1 + +#include + +/* + * TCompactProtocol::i*ToZigzag depend on the fact that the right shift + * operator on a signed integer is an arithmetic (sign-extending) shift. + * If this is not the case, the current implementation will not work. + * If anyone encounters this error, we can try to figure out the best + * way to implement an arithmetic right shift on their platform. + */ +#if !defined(SIGNED_RIGHT_SHIFT_IS) || !defined(ARITHMETIC_RIGHT_SHIFT) +# error "Unable to determine the behavior of a signed right shift" +#endif +#if SIGNED_RIGHT_SHIFT_IS != ARITHMETIC_RIGHT_SHIFT +# error "TCompactProtocol currently only works if a signed right shift is arithmetic" +#endif + +#ifdef __GNUC__ +#define UNLIKELY(val) (__builtin_expect((val), 0)) +#else +#define UNLIKELY(val) (val) +#endif + +namespace apache { namespace thrift { namespace protocol { + +namespace detail { namespace compact { + +enum Types { + CT_STOP = 0x00, + CT_BOOLEAN_TRUE = 0x01, + CT_BOOLEAN_FALSE = 0x02, + CT_BYTE = 0x03, + CT_I16 = 0x04, + CT_I32 = 0x05, + CT_I64 = 0x06, + CT_DOUBLE = 0x07, + CT_BINARY = 0x08, + CT_LIST = 0x09, + CT_SET = 0x0A, + CT_MAP = 0x0B, + CT_STRUCT = 0x0C +}; + +const int8_t TTypeToCType[16] = { + CT_STOP, // T_STOP + 0, // unused + CT_BOOLEAN_TRUE, // T_BOOL + CT_BYTE, // T_BYTE + CT_DOUBLE, // T_DOUBLE + 0, // unused + CT_I16, // T_I16 + 0, // unused + CT_I32, // T_I32 + 0, // unused + CT_I64, // T_I64 + CT_BINARY, // T_STRING + CT_STRUCT, // T_STRUCT + CT_MAP, // T_MAP + CT_SET, // T_SET + CT_LIST, // T_LIST +}; + +}} // end detail::compact namespace + + +template +uint32_t TCompactProtocolT::writeMessageBegin( + const std::string& name, + const TMessageType messageType, + const int32_t seqid) { + uint32_t wsize = 0; + wsize += writeByte(PROTOCOL_ID); + wsize += writeByte((VERSION_N & VERSION_MASK) | (((int32_t)messageType << TYPE_SHIFT_AMOUNT) & TYPE_MASK)); + wsize += writeVarint32(seqid); + wsize += writeString(name); + return wsize; +} + +/** + * Write a field header containing the field id and field type. If the + * difference between the current field id and the last one is small (< 15), + * then the field id will be encoded in the 4 MSB as a delta. Otherwise, the + * field id will follow the type header as a zigzag varint. + */ +template +uint32_t TCompactProtocolT::writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId) { + if (fieldType == T_BOOL) { + booleanField_.name = name; + booleanField_.fieldType = fieldType; + booleanField_.fieldId = fieldId; + } else { + return writeFieldBeginInternal(name, fieldType, fieldId, -1); + } + return 0; +} + +/** + * Write the STOP symbol so we know there are no more fields in this struct. + */ +template +uint32_t TCompactProtocolT::writeFieldStop() { + return writeByte(T_STOP); +} + +/** + * Write a struct begin. This doesn't actually put anything on the wire. We + * use it as an opportunity to put special placeholder markers on the field + * stack so we can get the field id deltas correct. + */ +template +uint32_t TCompactProtocolT::writeStructBegin(const char* name) { + (void) name; + lastField_.push(lastFieldId_); + lastFieldId_ = 0; + return 0; +} + +/** + * Write a struct end. This doesn't actually put anything on the wire. We use + * this as an opportunity to pop the last field from the current struct off + * of the field stack. + */ +template +uint32_t TCompactProtocolT::writeStructEnd() { + lastFieldId_ = lastField_.top(); + lastField_.pop(); + return 0; +} + +/** + * Write a List header. + */ +template +uint32_t TCompactProtocolT::writeListBegin(const TType elemType, + const uint32_t size) { + return writeCollectionBegin(elemType, size); +} + +/** + * Write a set header. + */ +template +uint32_t TCompactProtocolT::writeSetBegin(const TType elemType, + const uint32_t size) { + return writeCollectionBegin(elemType, size); +} + +/** + * Write a map header. If the map is empty, omit the key and value type + * headers, as we don't need any additional information to skip it. + */ +template +uint32_t TCompactProtocolT::writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size) { + uint32_t wsize = 0; + + if (size == 0) { + wsize += writeByte(0); + } else { + wsize += writeVarint32(size); + wsize += writeByte(getCompactType(keyType) << 4 | getCompactType(valType)); + } + return wsize; +} + +/** + * Write a boolean value. Potentially, this could be a boolean field, in + * which case the field header info isn't written yet. If so, decide what the + * right type header is for the value and then write the field header. + * Otherwise, write a single byte. + */ +template +uint32_t TCompactProtocolT::writeBool(const bool value) { + uint32_t wsize = 0; + + if (booleanField_.name != NULL) { + // we haven't written the field header yet + wsize += writeFieldBeginInternal(booleanField_.name, + booleanField_.fieldType, + booleanField_.fieldId, + value ? detail::compact::CT_BOOLEAN_TRUE : + detail::compact::CT_BOOLEAN_FALSE); + booleanField_.name = NULL; + } else { + // we're not part of a field, so just write the value + wsize += writeByte(value ? detail::compact::CT_BOOLEAN_TRUE : + detail::compact::CT_BOOLEAN_FALSE); + } + return wsize; +} + +template +uint32_t TCompactProtocolT::writeByte(const int8_t byte) { + trans_->write((uint8_t*)&byte, 1); + return 1; +} + +/** + * Write an i16 as a zigzag varint. + */ +template +uint32_t TCompactProtocolT::writeI16(const int16_t i16) { + return writeVarint32(i32ToZigzag(i16)); +} + +/** + * Write an i32 as a zigzag varint. + */ +template +uint32_t TCompactProtocolT::writeI32(const int32_t i32) { + return writeVarint32(i32ToZigzag(i32)); +} + +/** + * Write an i64 as a zigzag varint. + */ +template +uint32_t TCompactProtocolT::writeI64(const int64_t i64) { + return writeVarint64(i64ToZigzag(i64)); +} + +/** + * Write a double to the wire as 8 bytes. + */ +template +uint32_t TCompactProtocolT::writeDouble(const double dub) { + BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); + BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + + uint64_t bits = bitwise_cast(dub); + bits = htolell(bits); + trans_->write((uint8_t*)&bits, 8); + return 8; +} + +/** + * Write a string to the wire with a varint size preceeding. + */ +template +uint32_t TCompactProtocolT::writeString(const std::string& str) { + return writeBinary(str); +} + +template +uint32_t TCompactProtocolT::writeBinary(const std::string& str) { + uint32_t ssize = str.size(); + uint32_t wsize = writeVarint32(ssize) + ssize; + trans_->write((uint8_t*)str.data(), ssize); + return wsize; +} + +// +// Internal Writing methods +// + +/** + * The workhorse of writeFieldBegin. It has the option of doing a + * 'type override' of the type header. This is used specifically in the + * boolean field case. + */ +template +int32_t TCompactProtocolT::writeFieldBeginInternal( + const char* name, + const TType fieldType, + const int16_t fieldId, + int8_t typeOverride) { + (void) name; + uint32_t wsize = 0; + + // if there's a type override, use that. + int8_t typeToWrite = (typeOverride == -1 ? getCompactType(fieldType) : typeOverride); + + // check if we can use delta encoding for the field id + if (fieldId > lastFieldId_ && fieldId - lastFieldId_ <= 15) { + // write them together + wsize += writeByte((fieldId - lastFieldId_) << 4 | typeToWrite); + } else { + // write them separate + wsize += writeByte(typeToWrite); + wsize += writeI16(fieldId); + } + + lastFieldId_ = fieldId; + return wsize; +} + +/** + * Abstract method for writing the start of lists and sets. List and sets on + * the wire differ only by the type indicator. + */ +template +uint32_t TCompactProtocolT::writeCollectionBegin(int8_t elemType, + int32_t size) { + uint32_t wsize = 0; + if (size <= 14) { + wsize += writeByte(size << 4 | getCompactType(elemType)); + } else { + wsize += writeByte(0xf0 | getCompactType(elemType)); + wsize += writeVarint32(size); + } + return wsize; +} + +/** + * Write an i32 as a varint. Results in 1-5 bytes on the wire. + */ +template +uint32_t TCompactProtocolT::writeVarint32(uint32_t n) { + uint8_t buf[5]; + uint32_t wsize = 0; + + while (true) { + if ((n & ~0x7F) == 0) { + buf[wsize++] = (int8_t)n; + break; + } else { + buf[wsize++] = (int8_t)((n & 0x7F) | 0x80); + n >>= 7; + } + } + trans_->write(buf, wsize); + return wsize; +} + +/** + * Write an i64 as a varint. Results in 1-10 bytes on the wire. + */ +template +uint32_t TCompactProtocolT::writeVarint64(uint64_t n) { + uint8_t buf[10]; + uint32_t wsize = 0; + + while (true) { + if ((n & ~0x7FL) == 0) { + buf[wsize++] = (int8_t)n; + break; + } else { + buf[wsize++] = (int8_t)((n & 0x7F) | 0x80); + n >>= 7; + } + } + trans_->write(buf, wsize); + return wsize; +} + +/** + * Convert l into a zigzag long. This allows negative numbers to be + * represented compactly as a varint. + */ +template +uint64_t TCompactProtocolT::i64ToZigzag(const int64_t l) { + return (l << 1) ^ (l >> 63); +} + +/** + * Convert n into a zigzag int. This allows negative numbers to be + * represented compactly as a varint. + */ +template +uint32_t TCompactProtocolT::i32ToZigzag(const int32_t n) { + return (n << 1) ^ (n >> 31); +} + +/** + * Given a TType value, find the appropriate detail::compact::Types value + */ +template +int8_t TCompactProtocolT::getCompactType(int8_t ttype) { + return detail::compact::TTypeToCType[ttype]; +} + +// +// Reading Methods +// + +/** + * Read a message header. + */ +template +uint32_t TCompactProtocolT::readMessageBegin( + std::string& name, + TMessageType& messageType, + int32_t& seqid) { + uint32_t rsize = 0; + int8_t protocolId; + int8_t versionAndType; + int8_t version; + + rsize += readByte(protocolId); + if (protocolId != PROTOCOL_ID) { + throw TProtocolException(TProtocolException::BAD_VERSION, "Bad protocol identifier"); + } + + rsize += readByte(versionAndType); + version = (int8_t)(versionAndType & VERSION_MASK); + if (version != VERSION_N) { + throw TProtocolException(TProtocolException::BAD_VERSION, "Bad protocol version"); + } + + messageType = (TMessageType)((versionAndType >> TYPE_SHIFT_AMOUNT) & 0x03); + rsize += readVarint32(seqid); + rsize += readString(name); + + return rsize; +} + +/** + * Read a struct begin. There's nothing on the wire for this, but it is our + * opportunity to push a new struct begin marker on the field stack. + */ +template +uint32_t TCompactProtocolT::readStructBegin(std::string& name) { + name = ""; + lastField_.push(lastFieldId_); + lastFieldId_ = 0; + return 0; +} + +/** + * Doesn't actually consume any wire data, just removes the last field for + * this struct from the field stack. + */ +template +uint32_t TCompactProtocolT::readStructEnd() { + lastFieldId_ = lastField_.top(); + lastField_.pop(); + return 0; +} + +/** + * Read a field header off the wire. + */ +template +uint32_t TCompactProtocolT::readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId) { + (void) name; + uint32_t rsize = 0; + int8_t byte; + int8_t type; + + rsize += readByte(byte); + type = (byte & 0x0f); + + // if it's a stop, then we can return immediately, as the struct is over. + if (type == T_STOP) { + fieldType = T_STOP; + fieldId = 0; + return rsize; + } + + // mask off the 4 MSB of the type header. it could contain a field id delta. + int16_t modifier = (int16_t)(((uint8_t)byte & 0xf0) >> 4); + if (modifier == 0) { + // not a delta, look ahead for the zigzag varint field id. + rsize += readI16(fieldId); + } else { + fieldId = (int16_t)(lastFieldId_ + modifier); + } + fieldType = getTType(type); + + // if this happens to be a boolean field, the value is encoded in the type + if (type == detail::compact::CT_BOOLEAN_TRUE || + type == detail::compact::CT_BOOLEAN_FALSE) { + // save the boolean value in a special instance variable. + boolValue_.hasBoolValue = true; + boolValue_.boolValue = + (type == detail::compact::CT_BOOLEAN_TRUE ? true : false); + } + + // push the new field onto the field stack so we can keep the deltas going. + lastFieldId_ = fieldId; + return rsize; +} + +/** + * Read a map header off the wire. If the size is zero, skip reading the key + * and value type. This means that 0-length maps will yield TMaps without the + * "correct" types. + */ +template +uint32_t TCompactProtocolT::readMapBegin(TType& keyType, + TType& valType, + uint32_t& size) { + uint32_t rsize = 0; + int8_t kvType = 0; + int32_t msize = 0; + + rsize += readVarint32(msize); + if (msize != 0) + rsize += readByte(kvType); + + if (msize < 0) { + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } else if (container_limit_ && msize > container_limit_) { + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + + keyType = getTType((int8_t)((uint8_t)kvType >> 4)); + valType = getTType((int8_t)((uint8_t)kvType & 0xf)); + size = (uint32_t)msize; + + return rsize; +} + +/** + * Read a list header off the wire. If the list size is 0-14, the size will + * be packed into the element type header. If it's a longer list, the 4 MSB + * of the element type header will be 0xF, and a varint will follow with the + * true size. + */ +template +uint32_t TCompactProtocolT::readListBegin(TType& elemType, + uint32_t& size) { + int8_t size_and_type; + uint32_t rsize = 0; + int32_t lsize; + + rsize += readByte(size_and_type); + + lsize = ((uint8_t)size_and_type >> 4) & 0x0f; + if (lsize == 15) { + rsize += readVarint32(lsize); + } + + if (lsize < 0) { + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } else if (container_limit_ && lsize > container_limit_) { + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + + elemType = getTType((int8_t)(size_and_type & 0x0f)); + size = (uint32_t)lsize; + + return rsize; +} + +/** + * Read a set header off the wire. If the set size is 0-14, the size will + * be packed into the element type header. If it's a longer set, the 4 MSB + * of the element type header will be 0xF, and a varint will follow with the + * true size. + */ +template +uint32_t TCompactProtocolT::readSetBegin(TType& elemType, + uint32_t& size) { + return readListBegin(elemType, size); +} + +/** + * Read a boolean off the wire. If this is a boolean field, the value should + * already have been read during readFieldBegin, so we'll just consume the + * pre-stored value. Otherwise, read a byte. + */ +template +uint32_t TCompactProtocolT::readBool(bool& value) { + if (boolValue_.hasBoolValue == true) { + value = boolValue_.boolValue; + boolValue_.hasBoolValue = false; + return 0; + } else { + int8_t val; + readByte(val); + value = (val == detail::compact::CT_BOOLEAN_TRUE); + return 1; + } +} + +/** + * Read a single byte off the wire. Nothing interesting here. + */ +template +uint32_t TCompactProtocolT::readByte(int8_t& byte) { + uint8_t b[1]; + trans_->readAll(b, 1); + byte = *(int8_t*)b; + return 1; +} + +/** + * Read an i16 from the wire as a zigzag varint. + */ +template +uint32_t TCompactProtocolT::readI16(int16_t& i16) { + int32_t value; + uint32_t rsize = readVarint32(value); + i16 = (int16_t)zigzagToI32(value); + return rsize; +} + +/** + * Read an i32 from the wire as a zigzag varint. + */ +template +uint32_t TCompactProtocolT::readI32(int32_t& i32) { + int32_t value; + uint32_t rsize = readVarint32(value); + i32 = zigzagToI32(value); + return rsize; +} + +/** + * Read an i64 from the wire as a zigzag varint. + */ +template +uint32_t TCompactProtocolT::readI64(int64_t& i64) { + int64_t value; + uint32_t rsize = readVarint64(value); + i64 = zigzagToI64(value); + return rsize; +} + +/** + * No magic here - just read a double off the wire. + */ +template +uint32_t TCompactProtocolT::readDouble(double& dub) { + BOOST_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t)); + BOOST_STATIC_ASSERT(std::numeric_limits::is_iec559); + + uint64_t bits; + uint8_t b[8]; + trans_->readAll(b, 8); + bits = *(uint64_t*)b; + bits = letohll(bits); + dub = bitwise_cast(bits); + return 8; +} + +template +uint32_t TCompactProtocolT::readString(std::string& str) { + return readBinary(str); +} + +/** + * Read a byte[] from the wire. + */ +template +uint32_t TCompactProtocolT::readBinary(std::string& str) { + int32_t rsize = 0; + int32_t size; + + rsize += readVarint32(size); + // Catch empty string case + if (size == 0) { + str = ""; + return rsize; + } + + // Catch error cases + if (size < 0) { + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } + if (string_limit_ > 0 && size > string_limit_) { + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + + // Use the heap here to prevent stack overflow for v. large strings + if (size > string_buf_size_ || string_buf_ == NULL) { + void* new_string_buf = std::realloc(string_buf_, (uint32_t)size); + if (new_string_buf == NULL) { + throw std::bad_alloc(); + } + string_buf_ = (uint8_t*)new_string_buf; + string_buf_size_ = size; + } + trans_->readAll(string_buf_, size); + str.assign((char*)string_buf_, size); + + return rsize + (uint32_t)size; +} + +/** + * Read an i32 from the wire as a varint. The MSB of each byte is set + * if there is another byte to follow. This can read up to 5 bytes. + */ +template +uint32_t TCompactProtocolT::readVarint32(int32_t& i32) { + int64_t val; + uint32_t rsize = readVarint64(val); + i32 = (int32_t)val; + return rsize; +} + +/** + * Read an i64 from the wire as a proper varint. The MSB of each byte is set + * if there is another byte to follow. This can read up to 10 bytes. + */ +template +uint32_t TCompactProtocolT::readVarint64(int64_t& i64) { + uint32_t rsize = 0; + uint64_t val = 0; + int shift = 0; + uint8_t buf[10]; // 64 bits / (7 bits/byte) = 10 bytes. + uint32_t buf_size = sizeof(buf); + const uint8_t* borrowed = trans_->borrow(buf, &buf_size); + + // Fast path. + if (borrowed != NULL) { + while (true) { + uint8_t byte = borrowed[rsize]; + rsize++; + val |= (uint64_t)(byte & 0x7f) << shift; + shift += 7; + if (!(byte & 0x80)) { + i64 = val; + trans_->consume(rsize); + return rsize; + } + // Have to check for invalid data so we don't crash. + if (UNLIKELY(rsize == sizeof(buf))) { + throw TProtocolException(TProtocolException::INVALID_DATA, "Variable-length int over 10 bytes."); + } + } + } + + // Slow path. + else { + while (true) { + uint8_t byte; + rsize += trans_->readAll(&byte, 1); + val |= (uint64_t)(byte & 0x7f) << shift; + shift += 7; + if (!(byte & 0x80)) { + i64 = val; + return rsize; + } + // Might as well check for invalid data on the slow path too. + if (UNLIKELY(rsize >= sizeof(buf))) { + throw TProtocolException(TProtocolException::INVALID_DATA, "Variable-length int over 10 bytes."); + } + } + } +} + +/** + * Convert from zigzag int to int. + */ +template +int32_t TCompactProtocolT::zigzagToI32(uint32_t n) { + return (n >> 1) ^ -(n & 1); +} + +/** + * Convert from zigzag long to long. + */ +template +int64_t TCompactProtocolT::zigzagToI64(uint64_t n) { + return (n >> 1) ^ -(n & 1); +} + +template +TType TCompactProtocolT::getTType(int8_t type) { + switch (type) { + case T_STOP: + return T_STOP; + case detail::compact::CT_BOOLEAN_FALSE: + case detail::compact::CT_BOOLEAN_TRUE: + return T_BOOL; + case detail::compact::CT_BYTE: + return T_BYTE; + case detail::compact::CT_I16: + return T_I16; + case detail::compact::CT_I32: + return T_I32; + case detail::compact::CT_I64: + return T_I64; + case detail::compact::CT_DOUBLE: + return T_DOUBLE; + case detail::compact::CT_BINARY: + return T_STRING; + case detail::compact::CT_LIST: + return T_LIST; + case detail::compact::CT_SET: + return T_SET; + case detail::compact::CT_MAP: + return T_MAP; + case detail::compact::CT_STRUCT: + return T_STRUCT; + default: + throw TException("don't know what type: " + type); + } + return T_STOP; +} + +}}} // apache::thrift::protocol + +#endif // _THRIFT_PROTOCOL_TCOMPACTPROTOCOL_TCC_ diff --git a/sg_agent/thrid_party/thrift/include/protocol/TDebugProtocol.cpp b/sg_agent/thrid_party/thrift/include/protocol/TDebugProtocol.cpp new file mode 100644 index 0000000..28e175b --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/protocol/TDebugProtocol.cpp @@ -0,0 +1,348 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "TDebugProtocol.h" + +#include +#include +#include +#include +#include +#include + +using std::string; + + +static string byte_to_hex(const uint8_t byte) { + char buf[3]; + int ret = std::sprintf(buf, "%02x", (int)byte); + assert(ret == 2); + assert(buf[2] == '\0'); + return buf; +} + + +namespace apache { namespace thrift { namespace protocol { + +string TDebugProtocol::fieldTypeName(TType type) { + switch (type) { + case T_STOP : return "stop" ; + case T_VOID : return "void" ; + case T_BOOL : return "bool" ; + case T_BYTE : return "byte" ; + case T_I16 : return "i16" ; + case T_I32 : return "i32" ; + case T_U64 : return "u64" ; + case T_I64 : return "i64" ; + case T_DOUBLE : return "double" ; + case T_STRING : return "string" ; + case T_STRUCT : return "struct" ; + case T_MAP : return "map" ; + case T_SET : return "set" ; + case T_LIST : return "list" ; + case T_UTF8 : return "utf8" ; + case T_UTF16 : return "utf16" ; + default: return "unknown"; + } +} + +void TDebugProtocol::indentUp() { + indent_str_ += string(indent_inc, ' '); +} + +void TDebugProtocol::indentDown() { + if (indent_str_.length() < (string::size_type)indent_inc) { + throw TProtocolException(TProtocolException::INVALID_DATA); + } + indent_str_.erase(indent_str_.length() - indent_inc); +} + +uint32_t TDebugProtocol::writePlain(const string& str) { + trans_->write((uint8_t*)str.data(), str.length()); + return str.length(); +} + +uint32_t TDebugProtocol::writeIndented(const string& str) { + trans_->write((uint8_t*)indent_str_.data(), indent_str_.length()); + trans_->write((uint8_t*)str.data(), str.length()); + return indent_str_.length() + str.length(); +} + +uint32_t TDebugProtocol::startItem() { + uint32_t size; + + switch (write_state_.back()) { + case UNINIT: + // XXX figure out what to do here. + //throw TProtocolException(TProtocolException::INVALID_DATA); + //return writeIndented(str); + return 0; + case STRUCT: + return 0; + case SET: + return writeIndented(""); + case MAP_KEY: + return writeIndented(""); + case MAP_VALUE: + return writePlain(" -> "); + case LIST: + size = writeIndented( + "[" + boost::lexical_cast(list_idx_.back()) + "] = "); + list_idx_.back()++; + return size; + default: + throw std::logic_error("Invalid enum value."); + } +} + +uint32_t TDebugProtocol::endItem() { + //uint32_t size; + + switch (write_state_.back()) { + case UNINIT: + // XXX figure out what to do here. + //throw TProtocolException(TProtocolException::INVALID_DATA); + //return writeIndented(str); + return 0; + case STRUCT: + return writePlain(",\n"); + case SET: + return writePlain(",\n"); + case MAP_KEY: + write_state_.back() = MAP_VALUE; + return 0; + case MAP_VALUE: + write_state_.back() = MAP_KEY; + return writePlain(",\n"); + case LIST: + return writePlain(",\n"); + default: + throw std::logic_error("Invalid enum value."); + } +} + +uint32_t TDebugProtocol::writeItem(const std::string& str) { + uint32_t size = 0; + size += startItem(); + size += writePlain(str); + size += endItem(); + return size; +} + +uint32_t TDebugProtocol::writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid) { + (void) seqid; + string mtype; + switch (messageType) { + case T_CALL : mtype = "call" ; break; + case T_REPLY : mtype = "reply" ; break; + case T_EXCEPTION : mtype = "exn" ; break; + case T_ONEWAY : mtype = "oneway" ; break; + } + + uint32_t size = writeIndented("(" + mtype + ") " + name + "("); + indentUp(); + return size; +} + +uint32_t TDebugProtocol::writeMessageEnd() { + indentDown(); + return writeIndented(")\n"); +} + +uint32_t TDebugProtocol::writeStructBegin(const char* name) { + uint32_t size = 0; + size += startItem(); + size += writePlain(string(name) + " {\n"); + indentUp(); + write_state_.push_back(STRUCT); + return size; +} + +uint32_t TDebugProtocol::writeStructEnd() { + indentDown(); + write_state_.pop_back(); + uint32_t size = 0; + size += writeIndented("}"); + size += endItem(); + return size; +} + +uint32_t TDebugProtocol::writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId) { + // sprintf(id_str, "%02d", fieldId); + string id_str = boost::lexical_cast(fieldId); + if (id_str.length() == 1) id_str = '0' + id_str; + + return writeIndented( + id_str + ": " + + name + " (" + + fieldTypeName(fieldType) + ") = "); +} + +uint32_t TDebugProtocol::writeFieldEnd() { + assert(write_state_.back() == STRUCT); + return 0; +} + +uint32_t TDebugProtocol::writeFieldStop() { + return 0; + //writeIndented("***STOP***\n"); +} + +uint32_t TDebugProtocol::writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size) { + // TODO(dreiss): Optimize short maps? + uint32_t bsize = 0; + bsize += startItem(); + bsize += writePlain( + "map<" + fieldTypeName(keyType) + "," + fieldTypeName(valType) + ">" + "[" + boost::lexical_cast(size) + "] {\n"); + indentUp(); + write_state_.push_back(MAP_KEY); + return bsize; +} + +uint32_t TDebugProtocol::writeMapEnd() { + indentDown(); + write_state_.pop_back(); + uint32_t size = 0; + size += writeIndented("}"); + size += endItem(); + return size; +} + +uint32_t TDebugProtocol::writeListBegin(const TType elemType, + const uint32_t size) { + // TODO(dreiss): Optimize short arrays. + uint32_t bsize = 0; + bsize += startItem(); + bsize += writePlain( + "list<" + fieldTypeName(elemType) + ">" + "[" + boost::lexical_cast(size) + "] {\n"); + indentUp(); + write_state_.push_back(LIST); + list_idx_.push_back(0); + return bsize; +} + +uint32_t TDebugProtocol::writeListEnd() { + indentDown(); + write_state_.pop_back(); + list_idx_.pop_back(); + uint32_t size = 0; + size += writeIndented("}"); + size += endItem(); + return size; +} + +uint32_t TDebugProtocol::writeSetBegin(const TType elemType, + const uint32_t size) { + // TODO(dreiss): Optimize short sets. + uint32_t bsize = 0; + bsize += startItem(); + bsize += writePlain( + "set<" + fieldTypeName(elemType) + ">" + "[" + boost::lexical_cast(size) + "] {\n"); + indentUp(); + write_state_.push_back(SET); + return bsize; +} + +uint32_t TDebugProtocol::writeSetEnd() { + indentDown(); + write_state_.pop_back(); + uint32_t size = 0; + size += writeIndented("}"); + size += endItem(); + return size; +} + +uint32_t TDebugProtocol::writeBool(const bool value) { + return writeItem(value ? "true" : "false"); +} + +uint32_t TDebugProtocol::writeByte(const int8_t byte) { + return writeItem("0x" + byte_to_hex(byte)); +} + +uint32_t TDebugProtocol::writeI16(const int16_t i16) { + return writeItem(boost::lexical_cast(i16)); +} + +uint32_t TDebugProtocol::writeI32(const int32_t i32) { + return writeItem(boost::lexical_cast(i32)); +} + +uint32_t TDebugProtocol::writeI64(const int64_t i64) { + return writeItem(boost::lexical_cast(i64)); +} + +uint32_t TDebugProtocol::writeDouble(const double dub) { + return writeItem(boost::lexical_cast(dub)); +} + + +uint32_t TDebugProtocol::writeString(const string& str) { + // XXX Raw/UTF-8? + + string to_show = str; + if (to_show.length() > (string::size_type)string_limit_) { + to_show = str.substr(0, string_prefix_size_); + to_show += "[...](" + boost::lexical_cast(str.length()) + ")"; + } + + string output = "\""; + + for (string::const_iterator it = to_show.begin(); it != to_show.end(); ++it) { + if (*it == '\\') { + output += "\\\\"; + } else if (*it == '"') { + output += "\\\""; + } else if (std::isprint(*it)) { + output += *it; + } else { + switch (*it) { + case '\a': output += "\\a"; break; + case '\b': output += "\\b"; break; + case '\f': output += "\\f"; break; + case '\n': output += "\\n"; break; + case '\r': output += "\\r"; break; + case '\t': output += "\\t"; break; + case '\v': output += "\\v"; break; + default: + output += "\\x"; + output += byte_to_hex(*it); + } + } + } + + output += '\"'; + return writeItem(output); +} + +uint32_t TDebugProtocol::writeBinary(const string& str) { + // XXX Hex? + return TDebugProtocol::writeString(str); +} + +}}} // apache::thrift::protocol diff --git a/sg_agent/thrid_party/thrift/include/protocol/TDebugProtocol.h b/sg_agent/thrid_party/thrift/include/protocol/TDebugProtocol.h new file mode 100644 index 0000000..3f7877c --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/protocol/TDebugProtocol.h @@ -0,0 +1,227 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_ 1 + +#include "TVirtualProtocol.h" + +#include + +namespace apache { namespace thrift { namespace protocol { + +/* + +!!! EXPERIMENTAL CODE !!! + +This protocol is very much a work in progress. +It doesn't handle many cases properly. +It throws exceptions in many cases. +It probably segfaults in many cases. +Bug reports and feature requests are welcome. +Complaints are not. :R + +*/ + + +/** + * Protocol that prints the payload in a nice human-readable format. + * Reading from this protocol is not supported. + * + */ +class TDebugProtocol : public TVirtualProtocol { + private: + enum write_state_t + { UNINIT + , STRUCT + , LIST + , SET + , MAP_KEY + , MAP_VALUE + }; + + public: + TDebugProtocol(boost::shared_ptr trans) + : TVirtualProtocol(trans) + , trans_(trans.get()) + , string_limit_(DEFAULT_STRING_LIMIT) + , string_prefix_size_(DEFAULT_STRING_PREFIX_SIZE) + { + write_state_.push_back(UNINIT); + } + + static const int32_t DEFAULT_STRING_LIMIT = 256; + static const int32_t DEFAULT_STRING_PREFIX_SIZE = 16; + + void setStringSizeLimit(int32_t string_limit) { + string_limit_ = string_limit; + } + + void setStringPrefixSize(int32_t string_prefix_size) { + string_prefix_size_ = string_prefix_size; + } + + + uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid); + + uint32_t writeMessageEnd(); + + + uint32_t writeStructBegin(const char* name); + + uint32_t writeStructEnd(); + + uint32_t writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId); + + uint32_t writeFieldEnd(); + + uint32_t writeFieldStop(); + + uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size); + + uint32_t writeMapEnd(); + + uint32_t writeListBegin(const TType elemType, + const uint32_t size); + + uint32_t writeListEnd(); + + uint32_t writeSetBegin(const TType elemType, + const uint32_t size); + + uint32_t writeSetEnd(); + + uint32_t writeBool(const bool value); + + uint32_t writeByte(const int8_t byte); + + uint32_t writeI16(const int16_t i16); + + uint32_t writeI32(const int32_t i32); + + uint32_t writeI64(const int64_t i64); + + uint32_t writeDouble(const double dub); + + uint32_t writeString(const std::string& str); + + uint32_t writeBinary(const std::string& str); + + + private: + void indentUp(); + void indentDown(); + uint32_t writePlain(const std::string& str); + uint32_t writeIndented(const std::string& str); + uint32_t startItem(); + uint32_t endItem(); + uint32_t writeItem(const std::string& str); + + static std::string fieldTypeName(TType type); + + TTransport* trans_; + + int32_t string_limit_; + int32_t string_prefix_size_; + + std::string indent_str_; + static const int indent_inc = 2; + + std::vector write_state_; + std::vector list_idx_; +}; + +/** + * Constructs debug protocol handlers + */ +class TDebugProtocolFactory : public TProtocolFactory { + public: + TDebugProtocolFactory() {} + virtual ~TDebugProtocolFactory() {} + + boost::shared_ptr getProtocol(boost::shared_ptr trans) { + return boost::shared_ptr(new TDebugProtocol(trans)); + } + +}; + +}}} // apache::thrift::protocol + + +// TODO(dreiss): Move (part of) ThriftDebugString into a .cpp file and remove this. +#include + +namespace apache { namespace thrift { + +template +std::string ThriftDebugString(const ThriftStruct& ts) { + using namespace apache::thrift::transport; + using namespace apache::thrift::protocol; + TMemoryBuffer* buffer = new TMemoryBuffer; + boost::shared_ptr trans(buffer); + TDebugProtocol protocol(trans); + + ts.write(&protocol); + + uint8_t* buf; + uint32_t size; + buffer->getBuffer(&buf, &size); + return std::string((char*)buf, (unsigned int)size); +} + +// TODO(dreiss): This is badly broken. Don't use it unless you are me. +#if 0 +template +std::string DebugString(const std::vector& vec) { + using namespace apache::thrift::transport; + using namespace apache::thrift::protocol; + TMemoryBuffer* buffer = new TMemoryBuffer; + boost::shared_ptr trans(buffer); + TDebugProtocol protocol(trans); + + // I am gross! + protocol.writeStructBegin("SomeRandomVector"); + + // TODO: Fix this with a trait. + protocol.writeListBegin((TType)99, vec.size()); + typename std::vector::const_iterator it; + for (it = vec.begin(); it != vec.end(); ++it) { + it->write(&protocol); + } + protocol.writeListEnd(); + + uint8_t* buf; + uint32_t size; + buffer->getBuffer(&buf, &size); + return std::string((char*)buf, (unsigned int)size); +} +#endif // 0 + +}} // apache::thrift + + +#endif // #ifndef _THRIFT_PROTOCOL_TDEBUGPROTOCOL_H_ + + diff --git a/sg_agent/thrid_party/thrift/include/protocol/TDenseProtocol.cpp b/sg_agent/thrid_party/thrift/include/protocol/TDenseProtocol.cpp new file mode 100644 index 0000000..86e5e28 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/protocol/TDenseProtocol.cpp @@ -0,0 +1,766 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* + +IMPLEMENTATION DETAILS + +TDenseProtocol was designed to have a smaller serialized form than +TBinaryProtocol. This is accomplished using two techniques. The first is +variable-length integer encoding. We use the same technique that the Standard +MIDI File format uses for "variable-length quantities" +(http://en.wikipedia.org/wiki/Variable-length_quantity). +All integers (including i16, but not byte) are first cast to uint64_t, +then written out as variable-length quantities. This has the unfortunate side +effect that all negative numbers require 10 bytes, but negative numbers tend +to be far less common than positive ones. + +The second technique eliminating the field ids used by TBinaryProtocol. This +decision required support from the Thrift compiler and also sacrifices some of +the backward and forward compatibility of TBinaryProtocol. + +We considered implementing this technique by generating separate readers and +writers for the dense protocol (this is how Pillar, Thrift's predecessor, +worked), but this idea had a few problems: +- Our abstractions go out the window. +- We would have to maintain a second code generator. +- Preserving compatibility with old versions of the structures would be a + nightmare. + +Therefore, we chose an alternate implementation that stored the description of +the data neither in the data itself (like TBinaryProtocol) nor in the +serialization code (like Pillar), but instead in a separate data structure, +called a TypeSpec. TypeSpecs are generated by the Thrift compiler +(specifically in the t_cpp_generator), and their structure should be +documented there (TODO(dreiss): s/should be/is/). + +We maintain a stack of TypeSpecs within the protocol so it knows where the +generated code is in the reading/writing process. For example, if we are +writing an i32 contained in a struct bar, contained in a struct foo, then the +stack would look like: TOP , i32 , struct bar , struct foo , BOTTOM. +The following invariant: whenever we are about to read/write an object +(structBegin, containerBegin, or a scalar), the TypeSpec on the top of the +stack must match the type being read/written. The main reasons that this +invariant must be maintained is that if we ever start reading a structure, we +must have its exact TypeSpec in order to pass the right tags to the +deserializer. + +We use the following strategies for maintaining this invariant: + +- For structures, we have a separate stack of indexes, one for each structure + on the TypeSpec stack. These are indexes into the list of fields in the + structure's TypeSpec. When we {read,write}FieldBegin, we push on the + TypeSpec for the field. +- When we begin writing a list or set, we push on the TypeSpec for the + element type. +- For maps, we have a separate stack of booleans, one for each map on the + TypeSpec stack. The boolean is true if we are writing the key for that + map, and false if we are writing the value. Maps are the trickiest case + because the generated code does not call any protocol method between + the key and the value. As a result, we potentially have to switch + between map key state and map value state after reading/writing any object. +- This job is handled by the stateTransition method. It is called after + reading/writing every object. It pops the current TypeSpec off the stack, + then optionally pushes a new one on, depending on what the next TypeSpec is. + If it is a struct, the job is left to the next writeFieldBegin. If it is a + set or list, the just-popped typespec is pushed back on. If it is a map, + the top of the key/value stack is toggled, and the appropriate TypeSpec + is pushed. + +Optional fields are a little tricky also. We write a zero byte if they are +absent and prefix them with an 0x01 byte if they are present +*/ + +#define __STDC_LIMIT_MACROS +#include +#include "TDenseProtocol.h" +#include "TReflectionLocal.h" + +// Leaving this on for now. Disabling it will turn off asserts, which should +// give a performance boost. When we have *really* thorough test cases, +// we should drop this. +#define DEBUG_TDENSEPROTOCOL + +// NOTE: Assertions should *only* be used to detect bugs in code, +// either in TDenseProtocol itself, or in code using it. +// (For example, using the wrong TypeSpec.) +// Invalid data should NEVER cause an assertion failure, +// no matter how grossly corrupted, nor how ingeniously crafted. +#ifdef DEBUG_TDENSEPROTOCOL +#undef NDEBUG +#else +#define NDEBUG +#endif +#include + +using std::string; + +#ifdef __GNUC__ +#define UNLIKELY(val) (__builtin_expect((val), 0)) +#else +#define UNLIKELY(val) (val) +#endif + +namespace apache { namespace thrift { namespace protocol { + +const int TDenseProtocol::FP_PREFIX_LEN = + apache::thrift::reflection::local::FP_PREFIX_LEN; + +// Top TypeSpec. TypeSpec of the structure being encoded. +#define TTS (ts_stack_.back()) // type = TypeSpec* +// InDeX. Index into TTS of the current/next field to encode. +#define IDX (idx_stack_.back()) // type = int +// Field TypeSpec. TypeSpec of the current/next field to encode. +#define FTS (TTS->tstruct.specs[IDX]) // type = TypeSpec* +// Field MeTa. Metadata of the current/next field to encode. +#define FMT (TTS->tstruct.metas[IDX]) // type = FieldMeta +// SubType 1/2. TypeSpec of the first/second subtype of this container. +#define ST1 (TTS->tcontainer.subtype1) +#define ST2 (TTS->tcontainer.subtype2) + + +/** + * Checks that @c ttype is indeed the ttype that we should be writing, + * according to our typespec. Aborts if the test fails and debugging in on. + */ +inline void TDenseProtocol::checkTType(const TType ttype) { + assert(!ts_stack_.empty()); + assert(TTS->ttype == ttype); +} + +/** + * Makes sure that the TypeSpec stack is correct for the next object. + * See top-of-file comments. + */ +inline void TDenseProtocol::stateTransition() { + TypeSpec* old_tts = ts_stack_.back(); + ts_stack_.pop_back(); + + // If this is the end of the top-level write, we should have just popped + // the TypeSpec passed to the constructor. + if (ts_stack_.empty()) { + assert(old_tts = type_spec_); + return; + } + + switch (TTS->ttype) { + + case T_STRUCT: + assert(old_tts == FTS); + break; + + case T_LIST: + case T_SET: + assert(old_tts == ST1); + ts_stack_.push_back(old_tts); + break; + + case T_MAP: + assert(old_tts == (mkv_stack_.back() ? ST1 : ST2)); + mkv_stack_.back() = !mkv_stack_.back(); + ts_stack_.push_back(mkv_stack_.back() ? ST1 : ST2); + break; + + default: + assert(!"Invalid TType in stateTransition."); + break; + + } +} + + +/* + * Variable-length quantity functions. + */ + +inline uint32_t TDenseProtocol::vlqRead(uint64_t& vlq) { + uint32_t used = 0; + uint64_t val = 0; + uint8_t buf[10]; // 64 bits / (7 bits/byte) = 10 bytes. + uint32_t buf_size = sizeof(buf); + const uint8_t* borrowed = trans_->borrow(buf, &buf_size); + + // Fast path. TODO(dreiss): Make it faster. + if (borrowed != NULL) { + while (true) { + uint8_t byte = borrowed[used]; + used++; + val = (val << 7) | (byte & 0x7f); + if (!(byte & 0x80)) { + vlq = val; + trans_->consume(used); + return used; + } + // Have to check for invalid data so we don't crash. + if (UNLIKELY(used == sizeof(buf))) { + resetState(); + throw TProtocolException(TProtocolException::INVALID_DATA, "Variable-length int over 10 bytes."); + } + } + } + + // Slow path. + else { + while (true) { + uint8_t byte; + used += trans_->readAll(&byte, 1); + val = (val << 7) | (byte & 0x7f); + if (!(byte & 0x80)) { + vlq = val; + return used; + } + // Might as well check for invalid data on the slow path too. + if (UNLIKELY(used >= sizeof(buf))) { + resetState(); + throw TProtocolException(TProtocolException::INVALID_DATA, "Variable-length int over 10 bytes."); + } + } + } +} + +inline uint32_t TDenseProtocol::vlqWrite(uint64_t vlq) { + uint8_t buf[10]; // 64 bits / (7 bits/byte) = 10 bytes. + int32_t pos = sizeof(buf) - 1; + + // Write the thing from back to front. + buf[pos] = vlq & 0x7f; + vlq >>= 7; + pos--; + + while (vlq > 0) { + assert(pos >= 0); + buf[pos] = (vlq | 0x80); + vlq >>= 7; + pos--; + } + + // Back up one step before writing. + pos++; + + trans_->write(buf+pos, sizeof(buf) - pos); + return sizeof(buf) - pos; +} + + + +/* + * Writing functions. + */ + +uint32_t TDenseProtocol::writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid) { + throw TException("TDenseProtocol doesn't work with messages (yet)."); + + int32_t version = (VERSION_2) | ((int32_t)messageType); + uint32_t wsize = 0; + wsize += subWriteI32(version); + wsize += subWriteString(name); + wsize += subWriteI32(seqid); + return wsize; +} + +uint32_t TDenseProtocol::writeMessageEnd() { + return 0; +} + +uint32_t TDenseProtocol::writeStructBegin(const char* name) { + (void) name; + uint32_t xfer = 0; + + // The TypeSpec stack should be empty if this is the top-level read/write. + // If it is, we push the TypeSpec passed to the constructor. + if (ts_stack_.empty()) { + assert(standalone_); + + if (type_spec_ == NULL) { + resetState(); + throw TException("TDenseProtocol: No type specified."); + } else { + assert(type_spec_->ttype == T_STRUCT); + ts_stack_.push_back(type_spec_); + // Write out a prefix of the structure fingerprint. + trans_->write(type_spec_->fp_prefix, FP_PREFIX_LEN); + xfer += FP_PREFIX_LEN; + } + } + + // We need a new field index for this structure. + idx_stack_.push_back(0); + return 0; +} + +uint32_t TDenseProtocol::writeStructEnd() { + idx_stack_.pop_back(); + stateTransition(); + return 0; +} + +uint32_t TDenseProtocol::writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId) { + (void) name; + uint32_t xfer = 0; + + // Skip over optional fields. + while (FMT.tag != fieldId) { + // TODO(dreiss): Old meta here. + assert(FTS->ttype != T_STOP); + assert(FMT.is_optional); + // Write a zero byte so the reader can skip it. + xfer += subWriteBool(false); + // And advance to the next field. + IDX++; + } + + // TODO(dreiss): give a better exception. + assert(FTS->ttype == fieldType); + + if (FMT.is_optional) { + subWriteBool(true); + xfer += 1; + } + + // writeFieldStop shares all lot of logic up to this point. + // Instead of replicating it all, we just call this method from that one + // and use a gross special case here. + if (UNLIKELY(FTS->ttype != T_STOP)) { + // For normal fields, push the TypeSpec that we're about to use. + ts_stack_.push_back(FTS); + } + return xfer; +} + +uint32_t TDenseProtocol::writeFieldEnd() { + // Just move on to the next field. + IDX++; + return 0; +} + +uint32_t TDenseProtocol::writeFieldStop() { + return TDenseProtocol::writeFieldBegin("", T_STOP, 0); +} + +uint32_t TDenseProtocol::writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size) { + checkTType(T_MAP); + + assert(keyType == ST1->ttype); + assert(valType == ST2->ttype); + + ts_stack_.push_back(ST1); + mkv_stack_.push_back(true); + + return subWriteI32((int32_t)size); +} + +uint32_t TDenseProtocol::writeMapEnd() { + // Pop off the value type, as well as our entry in the map key/value stack. + // stateTransition takes care of popping off our TypeSpec. + ts_stack_.pop_back(); + mkv_stack_.pop_back(); + stateTransition(); + return 0; +} + +uint32_t TDenseProtocol::writeListBegin(const TType elemType, + const uint32_t size) { + checkTType(T_LIST); + + assert(elemType == ST1->ttype); + ts_stack_.push_back(ST1); + return subWriteI32((int32_t)size); +} + +uint32_t TDenseProtocol::writeListEnd() { + // Pop off the element type. stateTransition takes care of popping off ours. + ts_stack_.pop_back(); + stateTransition(); + return 0; +} + +uint32_t TDenseProtocol::writeSetBegin(const TType elemType, + const uint32_t size) { + checkTType(T_SET); + + assert(elemType == ST1->ttype); + ts_stack_.push_back(ST1); + return subWriteI32((int32_t)size); +} + +uint32_t TDenseProtocol::writeSetEnd() { + // Pop off the element type. stateTransition takes care of popping off ours. + ts_stack_.pop_back(); + stateTransition(); + return 0; +} + +uint32_t TDenseProtocol::writeBool(const bool value) { + checkTType(T_BOOL); + stateTransition(); + return TBinaryProtocol::writeBool(value); +} + +uint32_t TDenseProtocol::writeByte(const int8_t byte) { + checkTType(T_BYTE); + stateTransition(); + return TBinaryProtocol::writeByte(byte); +} + +uint32_t TDenseProtocol::writeI16(const int16_t i16) { + checkTType(T_I16); + stateTransition(); + return vlqWrite(i16); +} + +uint32_t TDenseProtocol::writeI32(const int32_t i32) { + checkTType(T_I32); + stateTransition(); + return vlqWrite(i32); +} + +uint32_t TDenseProtocol::writeI64(const int64_t i64) { + checkTType(T_I64); + stateTransition(); + return vlqWrite(i64); +} + +uint32_t TDenseProtocol::writeDouble(const double dub) { + checkTType(T_DOUBLE); + stateTransition(); + return TBinaryProtocol::writeDouble(dub); +} + +uint32_t TDenseProtocol::writeString(const std::string& str) { + checkTType(T_STRING); + stateTransition(); + return subWriteString(str); +} + +uint32_t TDenseProtocol::writeBinary(const std::string& str) { + return TDenseProtocol::writeString(str); +} + +inline uint32_t TDenseProtocol::subWriteI32(const int32_t i32) { + return vlqWrite(i32); +} + +uint32_t TDenseProtocol::subWriteString(const std::string& str) { + uint32_t size = str.size(); + uint32_t xfer = subWriteI32((int32_t)size); + if (size > 0) { + trans_->write((uint8_t*)str.data(), size); + } + return xfer + size; +} + + + +/* + * Reading functions + * + * These have a lot of the same logic as the writing functions, so if + * something is confusing, look for comments in the corresponding writer. + */ + +uint32_t TDenseProtocol::readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid) { + throw TException("TDenseProtocol doesn't work with messages (yet)."); + + uint32_t xfer = 0; + int32_t sz; + xfer += subReadI32(sz); + + if (sz < 0) { + // Check for correct version number + int32_t version = sz & VERSION_MASK; + if (version != VERSION_2) { + throw TProtocolException(TProtocolException::BAD_VERSION, "Bad version identifier"); + } + messageType = (TMessageType)(sz & 0x000000ff); + xfer += subReadString(name); + xfer += subReadI32(seqid); + } else { + throw TProtocolException(TProtocolException::BAD_VERSION, "No version identifier... old protocol client in strict mode?"); + } + return xfer; +} + +uint32_t TDenseProtocol::readMessageEnd() { + return 0; +} + +uint32_t TDenseProtocol::readStructBegin(string& name) { + (void) name; + uint32_t xfer = 0; + + if (ts_stack_.empty()) { + assert(standalone_); + + if (type_spec_ == NULL) { + resetState(); + throw TException("TDenseProtocol: No type specified."); + } else { + assert(type_spec_->ttype == T_STRUCT); + ts_stack_.push_back(type_spec_); + + // Check the fingerprint prefix. + uint8_t buf[FP_PREFIX_LEN]; + xfer += trans_->read(buf, FP_PREFIX_LEN); + if (std::memcmp(buf, type_spec_->fp_prefix, FP_PREFIX_LEN) != 0) { + resetState(); + throw TProtocolException(TProtocolException::INVALID_DATA, + "Fingerprint in data does not match type_spec."); + } + } + } + + // We need a new field index for this structure. + idx_stack_.push_back(0); + return 0; +} + +uint32_t TDenseProtocol::readStructEnd() { + idx_stack_.pop_back(); + stateTransition(); + return 0; +} + +uint32_t TDenseProtocol::readFieldBegin(string& name, + TType& fieldType, + int16_t& fieldId) { + (void) name; + uint32_t xfer = 0; + + // For optional fields, check to see if they are there. + while (FMT.is_optional) { + bool is_present; + xfer += subReadBool(is_present); + if (is_present) { + break; + } + IDX++; + } + + // Once we hit a mandatory field, or an optional field that is present, + // we know that FMT and FTS point to the appropriate field. + + fieldId = FMT.tag; + fieldType = FTS->ttype; + + // Normally, we push the TypeSpec that we are about to read, + // but no reading is done for T_STOP. + if (FTS->ttype != T_STOP) { + ts_stack_.push_back(FTS); + } + return xfer; +} + +uint32_t TDenseProtocol::readFieldEnd() { + IDX++; + return 0; +} + +uint32_t TDenseProtocol::readMapBegin(TType& keyType, + TType& valType, + uint32_t& size) { + checkTType(T_MAP); + + uint32_t xfer = 0; + int32_t sizei; + xfer += subReadI32(sizei); + if (sizei < 0) { + resetState(); + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } else if (container_limit_ && sizei > container_limit_) { + resetState(); + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + size = (uint32_t)sizei; + + keyType = ST1->ttype; + valType = ST2->ttype; + + ts_stack_.push_back(ST1); + mkv_stack_.push_back(true); + + return xfer; +} + +uint32_t TDenseProtocol::readMapEnd() { + ts_stack_.pop_back(); + mkv_stack_.pop_back(); + stateTransition(); + return 0; +} + +uint32_t TDenseProtocol::readListBegin(TType& elemType, + uint32_t& size) { + checkTType(T_LIST); + + uint32_t xfer = 0; + int32_t sizei; + xfer += subReadI32(sizei); + if (sizei < 0) { + resetState(); + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } else if (container_limit_ && sizei > container_limit_) { + resetState(); + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + size = (uint32_t)sizei; + + elemType = ST1->ttype; + + ts_stack_.push_back(ST1); + + return xfer; +} + +uint32_t TDenseProtocol::readListEnd() { + ts_stack_.pop_back(); + stateTransition(); + return 0; +} + +uint32_t TDenseProtocol::readSetBegin(TType& elemType, + uint32_t& size) { + checkTType(T_SET); + + uint32_t xfer = 0; + int32_t sizei; + xfer += subReadI32(sizei); + if (sizei < 0) { + resetState(); + throw TProtocolException(TProtocolException::NEGATIVE_SIZE); + } else if (container_limit_ && sizei > container_limit_) { + resetState(); + throw TProtocolException(TProtocolException::SIZE_LIMIT); + } + size = (uint32_t)sizei; + + elemType = ST1->ttype; + + ts_stack_.push_back(ST1); + + return xfer; +} + +uint32_t TDenseProtocol::readSetEnd() { + ts_stack_.pop_back(); + stateTransition(); + return 0; +} + +uint32_t TDenseProtocol::readBool(bool& value) { + checkTType(T_BOOL); + stateTransition(); + return TBinaryProtocol::readBool(value); +} + +uint32_t TDenseProtocol::readByte(int8_t& byte) { + checkTType(T_BYTE); + stateTransition(); + return TBinaryProtocol::readByte(byte); +} + +uint32_t TDenseProtocol::readI16(int16_t& i16) { + checkTType(T_I16); + stateTransition(); + uint64_t u64; + uint32_t rv = vlqRead(u64); + int64_t val = (int64_t)u64; + if (UNLIKELY(val > INT16_MAX || val < INT16_MIN)) { + resetState(); + throw TProtocolException(TProtocolException::INVALID_DATA, + "i16 out of range."); + } + i16 = (int16_t)val; + return rv; +} + +uint32_t TDenseProtocol::readI32(int32_t& i32) { + checkTType(T_I32); + stateTransition(); + uint64_t u64; + uint32_t rv = vlqRead(u64); + int64_t val = (int64_t)u64; + if (UNLIKELY(val > INT32_MAX || val < INT32_MIN)) { + resetState(); + throw TProtocolException(TProtocolException::INVALID_DATA, + "i32 out of range."); + } + i32 = (int32_t)val; + return rv; +} + +uint32_t TDenseProtocol::readI64(int64_t& i64) { + checkTType(T_I64); + stateTransition(); + uint64_t u64; + uint32_t rv = vlqRead(u64); + int64_t val = (int64_t)u64; + if (UNLIKELY(val > INT64_MAX || val < INT64_MIN)) { + resetState(); + throw TProtocolException(TProtocolException::INVALID_DATA, + "i64 out of range."); + } + i64 = (int64_t)val; + return rv; +} + +uint32_t TDenseProtocol::readDouble(double& dub) { + checkTType(T_DOUBLE); + stateTransition(); + return TBinaryProtocol::readDouble(dub); +} + +uint32_t TDenseProtocol::readString(std::string& str) { + checkTType(T_STRING); + stateTransition(); + return subReadString(str); +} + +uint32_t TDenseProtocol::readBinary(std::string& str) { + return TDenseProtocol::readString(str); +} + +uint32_t TDenseProtocol::subReadI32(int32_t& i32) { + uint64_t u64; + uint32_t rv = vlqRead(u64); + int64_t val = (int64_t)u64; + if (UNLIKELY(val > INT32_MAX || val < INT32_MIN)) { + resetState(); + throw TProtocolException(TProtocolException::INVALID_DATA, + "i32 out of range."); + } + i32 = (int32_t)val; + return rv; +} + +uint32_t TDenseProtocol::subReadString(std::string& str) { + uint32_t xfer; + int32_t size; + xfer = subReadI32(size); + return xfer + readStringBody(str, size); +} + +}}} // apache::thrift::protocol diff --git a/sg_agent/thrid_party/thrift/include/protocol/TDenseProtocol.h b/sg_agent/thrid_party/thrift/include/protocol/TDenseProtocol.h new file mode 100644 index 0000000..438ed89 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/protocol/TDenseProtocol.h @@ -0,0 +1,254 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_ 1 + +#include "TBinaryProtocol.h" + +namespace apache { namespace thrift { namespace protocol { + +/** + * !!!WARNING!!! + * This class is still highly experimental. Incompatible changes + * WILL be made to it without notice. DO NOT USE IT YET unless + * you are coordinating your testing with the author. + * + * The dense protocol is designed to use as little space as possible. + * + * There are two types of dense protocol instances. Standalone instances + * are not used for RPC and just encoded and decode structures of + * a predetermined type. Non-standalone instances are used for RPC. + * Currently, only standalone instances exist. + * + * To use a standalone dense protocol object, you must set the type_spec + * property (either in the constructor, or with setTypeSpec) to the local + * reflection TypeSpec of the structures you will write to (or read from) the + * protocol instance. + * + * BEST PRACTICES: + * - Never use optional for primitives or containers. + * - Only use optional for structures if they are very big and very rarely set. + * - All integers are variable-length, so you can use i64 without bloating. + * - NEVER EVER change the struct definitions IN ANY WAY without either + * changing your cache keys or talking to dreiss. + * + * TODO(dreiss): New class write with old meta. + * + * We override all of TBinaryProtocol's methods. + * We inherit so that we can can explicitly call TBPs's primitive-writing + * methods within our versions. + * + */ +class TDenseProtocol + : public TVirtualProtocol { + protected: + static const int32_t VERSION_MASK = 0xffff0000; + // VERSION_1 (0x80010000) is taken by TBinaryProtocol. + static const int32_t VERSION_2 = 0x80020000; + + public: + typedef apache::thrift::reflection::local::TypeSpec TypeSpec; + static const int FP_PREFIX_LEN; + + /** + * @param tran The transport to use. + * @param type_spec The TypeSpec of the structures using this protocol. + */ + TDenseProtocol(boost::shared_ptr trans, + TypeSpec* type_spec = NULL) : + TVirtualProtocol(trans), + type_spec_(type_spec), + standalone_(true) + {} + + void setTypeSpec(TypeSpec* type_spec) { + type_spec_ = type_spec; + } + TypeSpec* getTypeSpec() { + return type_spec_; + } + + + /* + * Writing functions. + */ + + uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid); + + uint32_t writeMessageEnd(); + + + uint32_t writeStructBegin(const char* name); + + uint32_t writeStructEnd(); + + uint32_t writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId); + + uint32_t writeFieldEnd(); + + uint32_t writeFieldStop(); + + uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size); + + uint32_t writeMapEnd(); + + uint32_t writeListBegin(const TType elemType, const uint32_t size); + + uint32_t writeListEnd(); + + uint32_t writeSetBegin(const TType elemType, const uint32_t size); + + uint32_t writeSetEnd(); + + uint32_t writeBool(const bool value); + + uint32_t writeByte(const int8_t byte); + + uint32_t writeI16(const int16_t i16); + + uint32_t writeI32(const int32_t i32); + + uint32_t writeI64(const int64_t i64); + + uint32_t writeDouble(const double dub); + + uint32_t writeString(const std::string& str); + + uint32_t writeBinary(const std::string& str); + + + /* + * Helper writing functions (don't do state transitions). + */ + inline uint32_t subWriteI32(const int32_t i32); + + inline uint32_t subWriteString(const std::string& str); + + uint32_t subWriteBool(const bool value) { + return TBinaryProtocol::writeBool(value); + } + + + /* + * Reading functions + */ + + uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid); + + uint32_t readMessageEnd(); + + uint32_t readStructBegin(std::string& name); + + uint32_t readStructEnd(); + + uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId); + + uint32_t readFieldEnd(); + + uint32_t readMapBegin(TType& keyType, + TType& valType, + uint32_t& size); + + uint32_t readMapEnd(); + + uint32_t readListBegin(TType& elemType, + uint32_t& size); + + uint32_t readListEnd(); + + uint32_t readSetBegin(TType& elemType, + uint32_t& size); + + uint32_t readSetEnd(); + + uint32_t readBool(bool& value); + // Provide the default readBool() implementation for std::vector + using TVirtualProtocol::readBool; + + uint32_t readByte(int8_t& byte); + + uint32_t readI16(int16_t& i16); + + uint32_t readI32(int32_t& i32); + + uint32_t readI64(int64_t& i64); + + uint32_t readDouble(double& dub); + + uint32_t readString(std::string& str); + + uint32_t readBinary(std::string& str); + + /* + * Helper reading functions (don't do state transitions). + */ + inline uint32_t subReadI32(int32_t& i32); + + inline uint32_t subReadString(std::string& str); + + uint32_t subReadBool(bool& value) { + return TBinaryProtocol::readBool(value); + } + + + private: + + // Implementation functions, documented in the .cpp. + inline void checkTType(const TType ttype); + inline void stateTransition(); + + // Read and write variable-length integers. + // Uses the same technique as the MIDI file format. + inline uint32_t vlqRead(uint64_t& vlq); + inline uint32_t vlqWrite(uint64_t vlq); + + // Called before throwing an exception to make the object reusable. + void resetState() { + ts_stack_.clear(); + idx_stack_.clear(); + mkv_stack_.clear(); + } + + // TypeSpec of the top-level structure to write, + // for standalone protocol objects. + TypeSpec* type_spec_; + + std::vector ts_stack_; // TypeSpec stack. + std::vector idx_stack_; // InDeX stack. + std::vector mkv_stack_; // Map Key/Vlue stack. + // True = key, False = value. + + // True iff this is a standalone instance (no RPC). + bool standalone_; +}; + +}}} // apache::thrift::protocol + +#endif // #ifndef _THRIFT_PROTOCOL_TDENSEPROTOCOL_H_ diff --git a/sg_agent/thrid_party/thrift/include/protocol/TJSONProtocol.cpp b/sg_agent/thrid_party/thrift/include/protocol/TJSONProtocol.cpp new file mode 100644 index 0000000..d038df4 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/protocol/TJSONProtocol.cpp @@ -0,0 +1,1005 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "TJSONProtocol.h" + +#include +#include +#include "TBase64Utils.h" +#include + +using namespace apache::thrift::transport; + +namespace apache { namespace thrift { namespace protocol { + + +// Static data + +static const uint8_t kJSONObjectStart = '{'; +static const uint8_t kJSONObjectEnd = '}'; +static const uint8_t kJSONArrayStart = '['; +static const uint8_t kJSONArrayEnd = ']'; +static const uint8_t kJSONNewline = '\n'; +static const uint8_t kJSONPairSeparator = ':'; +static const uint8_t kJSONElemSeparator = ','; +static const uint8_t kJSONBackslash = '\\'; +static const uint8_t kJSONStringDelimiter = '"'; +static const uint8_t kJSONZeroChar = '0'; +static const uint8_t kJSONEscapeChar = 'u'; + +static const std::string kJSONEscapePrefix("\\u00"); + +static const uint32_t kThriftVersion1 = 1; + +static const std::string kThriftNan("NaN"); +static const std::string kThriftInfinity("Infinity"); +static const std::string kThriftNegativeInfinity("-Infinity"); + +static const std::string kTypeNameBool("tf"); +static const std::string kTypeNameByte("i8"); +static const std::string kTypeNameI16("i16"); +static const std::string kTypeNameI32("i32"); +static const std::string kTypeNameI64("i64"); +static const std::string kTypeNameDouble("dbl"); +static const std::string kTypeNameStruct("rec"); +static const std::string kTypeNameString("str"); +static const std::string kTypeNameMap("map"); +static const std::string kTypeNameList("lst"); +static const std::string kTypeNameSet("set"); + +static const std::string &getTypeNameForTypeID(TType typeID) { + switch (typeID) { + case T_BOOL: + return kTypeNameBool; + case T_BYTE: + return kTypeNameByte; + case T_I16: + return kTypeNameI16; + case T_I32: + return kTypeNameI32; + case T_I64: + return kTypeNameI64; + case T_DOUBLE: + return kTypeNameDouble; + case T_STRING: + return kTypeNameString; + case T_STRUCT: + return kTypeNameStruct; + case T_MAP: + return kTypeNameMap; + case T_SET: + return kTypeNameSet; + case T_LIST: + return kTypeNameList; + default: + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "Unrecognized type"); + } +} + +static TType getTypeIDForTypeName(const std::string &name) { + TType result = T_STOP; // Sentinel value + if (name.length() > 1) { + switch (name[0]) { + case 'd': + result = T_DOUBLE; + break; + case 'i': + switch (name[1]) { + case '8': + result = T_BYTE; + break; + case '1': + result = T_I16; + break; + case '3': + result = T_I32; + break; + case '6': + result = T_I64; + break; + } + break; + case 'l': + result = T_LIST; + break; + case 'm': + result = T_MAP; + break; + case 'r': + result = T_STRUCT; + break; + case 's': + if (name[1] == 't') { + result = T_STRING; + } + else if (name[1] == 'e') { + result = T_SET; + } + break; + case 't': + result = T_BOOL; + break; + } + } + if (result == T_STOP) { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "Unrecognized type"); + } + return result; +} + + +// This table describes the handling for the first 0x30 characters +// 0 : escape using "\u00xx" notation +// 1 : just output index +// : escape using "\" notation +static const uint8_t kJSONCharTable[0x30] = { +// 0 1 2 3 4 5 6 7 8 9 A B C D E F + 0, 0, 0, 0, 0, 0, 0, 0,'b','t','n', 0,'f','r', 0, 0, // 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1 + 1, 1,'"', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2 +}; + + +// This string's characters must match up with the elements in kEscapeCharVals. +// I don't have '/' on this list even though it appears on www.json.org -- +// it is not in the RFC +const static std::string kEscapeChars("\"\\bfnrt"); + +// The elements of this array must match up with the sequence of characters in +// kEscapeChars +const static uint8_t kEscapeCharVals[7] = { + '"', '\\', '\b', '\f', '\n', '\r', '\t', +}; + + +// Static helper functions + +// Read 1 character from the transport trans and verify that it is the +// expected character ch. +// Throw a protocol exception if it is not. +static uint32_t readSyntaxChar(TJSONProtocol::LookaheadReader &reader, + uint8_t ch) { + uint8_t ch2 = reader.read(); + if (ch2 != ch) { + throw TProtocolException(TProtocolException::INVALID_DATA, + "Expected \'" + std::string((char *)&ch, 1) + + "\'; got \'" + std::string((char *)&ch2, 1) + + "\'."); + } + return 1; +} + +// Return the integer value of a hex character ch. +// Throw a protocol exception if the character is not [0-9a-f]. +static uint8_t hexVal(uint8_t ch) { + if ((ch >= '0') && (ch <= '9')) { + return ch - '0'; + } + else if ((ch >= 'a') && (ch <= 'f')) { + return ch - 'a' + 10; + } + else { + throw TProtocolException(TProtocolException::INVALID_DATA, + "Expected hex val ([0-9a-f]); got \'" + + std::string((char *)&ch, 1) + "\'."); + } +} + +// Return the hex character representing the integer val. The value is masked +// to make sure it is in the correct range. +static uint8_t hexChar(uint8_t val) { + val &= 0x0F; + if (val < 10) { + return val + '0'; + } + else { + return val - 10 + 'a'; + } +} + +// Return true if the character ch is in [-+0-9.Ee]; false otherwise +static bool isJSONNumeric(uint8_t ch) { + switch (ch) { + case '+': + case '-': + case '.': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 'E': + case 'e': + return true; + } + return false; +} + + +/** + * Class to serve as base JSON context and as base class for other context + * implementations + */ +class TJSONContext { + + public: + + TJSONContext() {}; + + virtual ~TJSONContext() {}; + + /** + * Write context data to the transport. Default is to do nothing. + */ + virtual uint32_t write(TTransport &trans) { + (void) trans; + return 0; + }; + + /** + * Read context data from the transport. Default is to do nothing. + */ + virtual uint32_t read(TJSONProtocol::LookaheadReader &reader) { + (void) reader; + return 0; + }; + + /** + * Return true if numbers need to be escaped as strings in this context. + * Default behavior is to return false. + */ + virtual bool escapeNum() { + return false; + } +}; + +// Context class for object member key-value pairs +class JSONPairContext : public TJSONContext { + +public: + + JSONPairContext() : + first_(true), + colon_(true) { + } + + uint32_t write(TTransport &trans) { + if (first_) { + first_ = false; + colon_ = true; + return 0; + } + else { + trans.write(colon_ ? &kJSONPairSeparator : &kJSONElemSeparator, 1); + colon_ = !colon_; + return 1; + } + } + + uint32_t read(TJSONProtocol::LookaheadReader &reader) { + if (first_) { + first_ = false; + colon_ = true; + return 0; + } + else { + uint8_t ch = (colon_ ? kJSONPairSeparator : kJSONElemSeparator); + colon_ = !colon_; + return readSyntaxChar(reader, ch); + } + } + + // Numbers must be turned into strings if they are the key part of a pair + virtual bool escapeNum() { + return colon_; + } + + private: + + bool first_; + bool colon_; +}; + +// Context class for lists +class JSONListContext : public TJSONContext { + +public: + + JSONListContext() : + first_(true) { + } + + uint32_t write(TTransport &trans) { + if (first_) { + first_ = false; + return 0; + } + else { + trans.write(&kJSONElemSeparator, 1); + return 1; + } + } + + uint32_t read(TJSONProtocol::LookaheadReader &reader) { + if (first_) { + first_ = false; + return 0; + } + else { + return readSyntaxChar(reader, kJSONElemSeparator); + } + } + + private: + bool first_; +}; + + +TJSONProtocol::TJSONProtocol(boost::shared_ptr ptrans) : + TVirtualProtocol(ptrans), + trans_(ptrans.get()), + context_(new TJSONContext()), + reader_(*ptrans) { +} + +TJSONProtocol::~TJSONProtocol() {} + +void TJSONProtocol::pushContext(boost::shared_ptr c) { + contexts_.push(context_); + context_ = c; +} + +void TJSONProtocol::popContext() { + context_ = contexts_.top(); + contexts_.pop(); +} + +// Write the character ch as a JSON escape sequence ("\u00xx") +uint32_t TJSONProtocol::writeJSONEscapeChar(uint8_t ch) { + trans_->write((const uint8_t *)kJSONEscapePrefix.c_str(), + kJSONEscapePrefix.length()); + uint8_t outCh = hexChar(ch >> 4); + trans_->write(&outCh, 1); + outCh = hexChar(ch); + trans_->write(&outCh, 1); + return 6; +} + +// Write the character ch as part of a JSON string, escaping as appropriate. +uint32_t TJSONProtocol::writeJSONChar(uint8_t ch) { + if (ch >= 0x30) { + if (ch == kJSONBackslash) { // Only special character >= 0x30 is '\' + trans_->write(&kJSONBackslash, 1); + trans_->write(&kJSONBackslash, 1); + return 2; + } + else { + trans_->write(&ch, 1); + return 1; + } + } + else { + uint8_t outCh = kJSONCharTable[ch]; + // Check if regular character, backslash escaped, or JSON escaped + if (outCh == 1) { + trans_->write(&ch, 1); + return 1; + } + else if (outCh > 1) { + trans_->write(&kJSONBackslash, 1); + trans_->write(&outCh, 1); + return 2; + } + else { + return writeJSONEscapeChar(ch); + } + } +} + +// Write out the contents of the string str as a JSON string, escaping +// characters as appropriate. +uint32_t TJSONProtocol::writeJSONString(const std::string &str) { + uint32_t result = context_->write(*trans_); + result += 2; // For quotes + trans_->write(&kJSONStringDelimiter, 1); + std::string::const_iterator iter(str.begin()); + std::string::const_iterator end(str.end()); + while (iter != end) { + result += writeJSONChar(*iter++); + } + trans_->write(&kJSONStringDelimiter, 1); + return result; +} + +// Write out the contents of the string as JSON string, base64-encoding +// the string's contents, and escaping as appropriate +uint32_t TJSONProtocol::writeJSONBase64(const std::string &str) { + uint32_t result = context_->write(*trans_); + result += 2; // For quotes + trans_->write(&kJSONStringDelimiter, 1); + uint8_t b[4]; + const uint8_t *bytes = (const uint8_t *)str.c_str(); + uint32_t len = str.length(); + while (len >= 3) { + // Encode 3 bytes at a time + base64_encode(bytes, 3, b); + trans_->write(b, 4); + result += 4; + bytes += 3; + len -=3; + } + if (len) { // Handle remainder + base64_encode(bytes, len, b); + trans_->write(b, len + 1); + result += len + 1; + } + trans_->write(&kJSONStringDelimiter, 1); + return result; +} + +// Convert the given integer type to a JSON number, or a string +// if the context requires it (eg: key in a map pair). +template +uint32_t TJSONProtocol::writeJSONInteger(NumberType num) { + uint32_t result = context_->write(*trans_); + std::string val(boost::lexical_cast(num)); + bool escapeNum = context_->escapeNum(); + if (escapeNum) { + trans_->write(&kJSONStringDelimiter, 1); + result += 1; + } + trans_->write((const uint8_t *)val.c_str(), val.length()); + result += val.length(); + if (escapeNum) { + trans_->write(&kJSONStringDelimiter, 1); + result += 1; + } + return result; +} + +// Convert the given double to a JSON string, which is either the number, +// "NaN" or "Infinity" or "-Infinity". +uint32_t TJSONProtocol::writeJSONDouble(double num) { + uint32_t result = context_->write(*trans_); + std::string val(boost::lexical_cast(num)); + + // Normalize output of boost::lexical_cast for NaNs and Infinities + bool special = false; + switch (val[0]) { + case 'N': + case 'n': + val = kThriftNan; + special = true; + break; + case 'I': + case 'i': + val = kThriftInfinity; + special = true; + break; + case '-': + if ((val[1] == 'I') || (val[1] == 'i')) { + val = kThriftNegativeInfinity; + special = true; + } + break; + } + + bool escapeNum = special || context_->escapeNum(); + if (escapeNum) { + trans_->write(&kJSONStringDelimiter, 1); + result += 1; + } + trans_->write((const uint8_t *)val.c_str(), val.length()); + result += val.length(); + if (escapeNum) { + trans_->write(&kJSONStringDelimiter, 1); + result += 1; + } + return result; +} + +uint32_t TJSONProtocol::writeJSONObjectStart() { + uint32_t result = context_->write(*trans_); + trans_->write(&kJSONObjectStart, 1); + pushContext(boost::shared_ptr(new JSONPairContext())); + return result + 1; +} + +uint32_t TJSONProtocol::writeJSONObjectEnd() { + popContext(); + trans_->write(&kJSONObjectEnd, 1); + return 1; +} + +uint32_t TJSONProtocol::writeJSONArrayStart() { + uint32_t result = context_->write(*trans_); + trans_->write(&kJSONArrayStart, 1); + pushContext(boost::shared_ptr(new JSONListContext())); + return result + 1; +} + +uint32_t TJSONProtocol::writeJSONArrayEnd() { + popContext(); + trans_->write(&kJSONArrayEnd, 1); + return 1; +} + +uint32_t TJSONProtocol::writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid) { + uint32_t result = writeJSONArrayStart(); + result += writeJSONInteger(kThriftVersion1); + result += writeJSONString(name); + result += writeJSONInteger(messageType); + result += writeJSONInteger(seqid); + return result; +} + +uint32_t TJSONProtocol::writeMessageEnd() { + return writeJSONArrayEnd(); +} + +uint32_t TJSONProtocol::writeStructBegin(const char* name) { + (void) name; + return writeJSONObjectStart(); +} + +uint32_t TJSONProtocol::writeStructEnd() { + return writeJSONObjectEnd(); +} + +uint32_t TJSONProtocol::writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId) { + (void) name; + uint32_t result = writeJSONInteger(fieldId); + result += writeJSONObjectStart(); + result += writeJSONString(getTypeNameForTypeID(fieldType)); + return result; +} + +uint32_t TJSONProtocol::writeFieldEnd() { + return writeJSONObjectEnd(); +} + +uint32_t TJSONProtocol::writeFieldStop() { + return 0; +} + +uint32_t TJSONProtocol::writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size) { + uint32_t result = writeJSONArrayStart(); + result += writeJSONString(getTypeNameForTypeID(keyType)); + result += writeJSONString(getTypeNameForTypeID(valType)); + result += writeJSONInteger((int64_t)size); + result += writeJSONObjectStart(); + return result; +} + +uint32_t TJSONProtocol::writeMapEnd() { + return writeJSONObjectEnd() + writeJSONArrayEnd(); +} + +uint32_t TJSONProtocol::writeListBegin(const TType elemType, + const uint32_t size) { + uint32_t result = writeJSONArrayStart(); + result += writeJSONString(getTypeNameForTypeID(elemType)); + result += writeJSONInteger((int64_t)size); + return result; +} + +uint32_t TJSONProtocol::writeListEnd() { + return writeJSONArrayEnd(); +} + +uint32_t TJSONProtocol::writeSetBegin(const TType elemType, + const uint32_t size) { + uint32_t result = writeJSONArrayStart(); + result += writeJSONString(getTypeNameForTypeID(elemType)); + result += writeJSONInteger((int64_t)size); + return result; +} + +uint32_t TJSONProtocol::writeSetEnd() { + return writeJSONArrayEnd(); +} + +uint32_t TJSONProtocol::writeBool(const bool value) { + return writeJSONInteger(value); +} + +uint32_t TJSONProtocol::writeByte(const int8_t byte) { + // writeByte() must be handled specially becuase boost::lexical cast sees + // int8_t as a text type instead of an integer type + return writeJSONInteger((int16_t)byte); +} + +uint32_t TJSONProtocol::writeI16(const int16_t i16) { + return writeJSONInteger(i16); +} + +uint32_t TJSONProtocol::writeI32(const int32_t i32) { + return writeJSONInteger(i32); +} + +uint32_t TJSONProtocol::writeI64(const int64_t i64) { + return writeJSONInteger(i64); +} + +uint32_t TJSONProtocol::writeDouble(const double dub) { + return writeJSONDouble(dub); +} + +uint32_t TJSONProtocol::writeString(const std::string& str) { + return writeJSONString(str); +} + +uint32_t TJSONProtocol::writeBinary(const std::string& str) { + return writeJSONBase64(str); +} + + /** + * Reading functions + */ + +// Reads 1 byte and verifies that it matches ch. +uint32_t TJSONProtocol::readJSONSyntaxChar(uint8_t ch) { + return readSyntaxChar(reader_, ch); +} + +// Decodes the four hex parts of a JSON escaped string character and returns +// the character via out. The first two characters must be "00". +uint32_t TJSONProtocol::readJSONEscapeChar(uint8_t *out) { + uint8_t b[2]; + readJSONSyntaxChar(kJSONZeroChar); + readJSONSyntaxChar(kJSONZeroChar); + b[0] = reader_.read(); + b[1] = reader_.read(); + *out = (hexVal(b[0]) << 4) + hexVal(b[1]); + return 4; +} + +// Decodes a JSON string, including unescaping, and returns the string via str +uint32_t TJSONProtocol::readJSONString(std::string &str, bool skipContext) { + uint32_t result = (skipContext ? 0 : context_->read(reader_)); + result += readJSONSyntaxChar(kJSONStringDelimiter); + uint8_t ch; + str.clear(); + while (true) { + ch = reader_.read(); + ++result; + if (ch == kJSONStringDelimiter) { + break; + } + if (ch == kJSONBackslash) { + ch = reader_.read(); + ++result; + if (ch == kJSONEscapeChar) { + result += readJSONEscapeChar(&ch); + } + else { + size_t pos = kEscapeChars.find(ch); + if (pos == std::string::npos) { + throw TProtocolException(TProtocolException::INVALID_DATA, + "Expected control char, got '" + + std::string((const char *)&ch, 1) + "'."); + } + ch = kEscapeCharVals[pos]; + } + } + str += ch; + } + return result; +} + +// Reads a block of base64 characters, decoding it, and returns via str +uint32_t TJSONProtocol::readJSONBase64(std::string &str) { + std::string tmp; + uint32_t result = readJSONString(tmp); + uint8_t *b = (uint8_t *)tmp.c_str(); + uint32_t len = tmp.length(); + str.clear(); + while (len >= 4) { + base64_decode(b, 4); + str.append((const char *)b, 3); + b += 4; + len -= 4; + } + // Don't decode if we hit the end or got a single leftover byte (invalid + // base64 but legal for skip of regular string type) + if (len > 1) { + base64_decode(b, len); + str.append((const char *)b, len - 1); + } + return result; +} + +// Reads a sequence of characters, stopping at the first one that is not +// a valid JSON numeric character. +uint32_t TJSONProtocol::readJSONNumericChars(std::string &str) { + uint32_t result = 0; + str.clear(); + while (true) { + uint8_t ch = reader_.peek(); + if (!isJSONNumeric(ch)) { + break; + } + reader_.read(); + str += ch; + ++result; + } + return result; +} + +// Reads a sequence of characters and assembles them into a number, +// returning them via num +template +uint32_t TJSONProtocol::readJSONInteger(NumberType &num) { + uint32_t result = context_->read(reader_); + if (context_->escapeNum()) { + result += readJSONSyntaxChar(kJSONStringDelimiter); + } + std::string str; + result += readJSONNumericChars(str); + try { + num = boost::lexical_cast(str); + } + catch (boost::bad_lexical_cast e) { + throw new TProtocolException(TProtocolException::INVALID_DATA, + "Expected numeric value; got \"" + str + + "\""); + } + if (context_->escapeNum()) { + result += readJSONSyntaxChar(kJSONStringDelimiter); + } + return result; +} + +// Reads a JSON number or string and interprets it as a double. +uint32_t TJSONProtocol::readJSONDouble(double &num) { + uint32_t result = context_->read(reader_); + std::string str; + if (reader_.peek() == kJSONStringDelimiter) { + result += readJSONString(str, true); + // Check for NaN, Infinity and -Infinity + if (str == kThriftNan) { + num = HUGE_VAL/HUGE_VAL; // generates NaN + } + else if (str == kThriftInfinity) { + num = HUGE_VAL; + } + else if (str == kThriftNegativeInfinity) { + num = -HUGE_VAL; + } + else { + if (!context_->escapeNum()) { + // Throw exception -- we should not be in a string in this case + throw new TProtocolException(TProtocolException::INVALID_DATA, + "Numeric data unexpectedly quoted"); + } + try { + num = boost::lexical_cast(str); + } + catch (boost::bad_lexical_cast e) { + throw new TProtocolException(TProtocolException::INVALID_DATA, + "Expected numeric value; got \"" + str + + "\""); + } + } + } + else { + if (context_->escapeNum()) { + // This will throw - we should have had a quote if escapeNum == true + readJSONSyntaxChar(kJSONStringDelimiter); + } + result += readJSONNumericChars(str); + try { + num = boost::lexical_cast(str); + } + catch (boost::bad_lexical_cast e) { + throw new TProtocolException(TProtocolException::INVALID_DATA, + "Expected numeric value; got \"" + str + + "\""); + } + } + return result; +} + +uint32_t TJSONProtocol::readJSONObjectStart() { + uint32_t result = context_->read(reader_); + result += readJSONSyntaxChar(kJSONObjectStart); + pushContext(boost::shared_ptr(new JSONPairContext())); + return result; +} + +uint32_t TJSONProtocol::readJSONObjectEnd() { + uint32_t result = readJSONSyntaxChar(kJSONObjectEnd); + popContext(); + return result; +} + +uint32_t TJSONProtocol::readJSONArrayStart() { + uint32_t result = context_->read(reader_); + result += readJSONSyntaxChar(kJSONArrayStart); + pushContext(boost::shared_ptr(new JSONListContext())); + return result; +} + +uint32_t TJSONProtocol::readJSONArrayEnd() { + uint32_t result = readJSONSyntaxChar(kJSONArrayEnd); + popContext(); + return result; +} + +uint32_t TJSONProtocol::readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid) { + uint32_t result = readJSONArrayStart(); + uint64_t tmpVal = 0; + result += readJSONInteger(tmpVal); + if (tmpVal != kThriftVersion1) { + throw TProtocolException(TProtocolException::BAD_VERSION, + "Message contained bad version."); + } + result += readJSONString(name); + result += readJSONInteger(tmpVal); + messageType = (TMessageType)tmpVal; + result += readJSONInteger(tmpVal); + seqid = tmpVal; + return result; +} + +uint32_t TJSONProtocol::readMessageEnd() { + return readJSONArrayEnd(); +} + +uint32_t TJSONProtocol::readStructBegin(std::string& name) { + (void) name; + return readJSONObjectStart(); +} + +uint32_t TJSONProtocol::readStructEnd() { + return readJSONObjectEnd(); +} + +uint32_t TJSONProtocol::readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId) { + (void) name; + uint32_t result = 0; + // Check if we hit the end of the list + uint8_t ch = reader_.peek(); + if (ch == kJSONObjectEnd) { + fieldType = apache::thrift::protocol::T_STOP; + } + else { + uint64_t tmpVal = 0; + std::string tmpStr; + result += readJSONInteger(tmpVal); + fieldId = tmpVal; + result += readJSONObjectStart(); + result += readJSONString(tmpStr); + fieldType = getTypeIDForTypeName(tmpStr); + } + return result; +} + +uint32_t TJSONProtocol::readFieldEnd() { + return readJSONObjectEnd(); +} + +uint32_t TJSONProtocol::readMapBegin(TType& keyType, + TType& valType, + uint32_t& size) { + uint64_t tmpVal = 0; + std::string tmpStr; + uint32_t result = readJSONArrayStart(); + result += readJSONString(tmpStr); + keyType = getTypeIDForTypeName(tmpStr); + result += readJSONString(tmpStr); + valType = getTypeIDForTypeName(tmpStr); + result += readJSONInteger(tmpVal); + size = tmpVal; + result += readJSONObjectStart(); + return result; +} + +uint32_t TJSONProtocol::readMapEnd() { + return readJSONObjectEnd() + readJSONArrayEnd(); +} + +uint32_t TJSONProtocol::readListBegin(TType& elemType, + uint32_t& size) { + uint64_t tmpVal = 0; + std::string tmpStr; + uint32_t result = readJSONArrayStart(); + result += readJSONString(tmpStr); + elemType = getTypeIDForTypeName(tmpStr); + result += readJSONInteger(tmpVal); + size = tmpVal; + return result; +} + +uint32_t TJSONProtocol::readListEnd() { + return readJSONArrayEnd(); +} + +uint32_t TJSONProtocol::readSetBegin(TType& elemType, + uint32_t& size) { + uint64_t tmpVal = 0; + std::string tmpStr; + uint32_t result = readJSONArrayStart(); + result += readJSONString(tmpStr); + elemType = getTypeIDForTypeName(tmpStr); + result += readJSONInteger(tmpVal); + size = tmpVal; + return result; +} + +uint32_t TJSONProtocol::readSetEnd() { + return readJSONArrayEnd(); +} + +uint32_t TJSONProtocol::readBool(bool& value) { + return readJSONInteger(value); +} + +// readByte() must be handled properly becuase boost::lexical cast sees int8_t +// as a text type instead of an integer type +uint32_t TJSONProtocol::readByte(int8_t& byte) { + int16_t tmp = (int16_t) byte; + uint32_t result = readJSONInteger(tmp); + assert(tmp < 256); + byte = (int8_t)tmp; + return result; +} + +uint32_t TJSONProtocol::readI16(int16_t& i16) { + return readJSONInteger(i16); +} + +uint32_t TJSONProtocol::readI32(int32_t& i32) { + return readJSONInteger(i32); +} + +uint32_t TJSONProtocol::readI64(int64_t& i64) { + return readJSONInteger(i64); +} + +uint32_t TJSONProtocol::readDouble(double& dub) { + return readJSONDouble(dub); +} + +uint32_t TJSONProtocol::readString(std::string &str) { + return readJSONString(str); +} + +uint32_t TJSONProtocol::readBinary(std::string &str) { + return readJSONBase64(str); +} + +}}} // apache::thrift::protocol diff --git a/sg_agent/thrid_party/thrift/include/protocol/TJSONProtocol.h b/sg_agent/thrid_party/thrift/include/protocol/TJSONProtocol.h new file mode 100644 index 0000000..799c361 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/protocol/TJSONProtocol.h @@ -0,0 +1,339 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_PROTOCOL_TJSONPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TJSONPROTOCOL_H_ 1 + +#include "TVirtualProtocol.h" + +#include + +namespace apache { namespace thrift { namespace protocol { + +// Forward declaration +class TJSONContext; + +/** + * JSON protocol for Thrift. + * + * Implements a protocol which uses JSON as the wire-format. + * + * Thrift types are represented as described below: + * + * 1. Every Thrift integer type is represented as a JSON number. + * + * 2. Thrift doubles are represented as JSON numbers. Some special values are + * represented as strings: + * a. "NaN" for not-a-number values + * b. "Infinity" for postive infinity + * c. "-Infinity" for negative infinity + * + * 3. Thrift string values are emitted as JSON strings, with appropriate + * escaping. + * + * 4. Thrift binary values are encoded into Base64 and emitted as JSON strings. + * The readBinary() method is written such that it will properly skip if + * called on a Thrift string (although it will decode garbage data). + * + * 5. Thrift structs are represented as JSON objects, with the field ID as the + * key, and the field value represented as a JSON object with a single + * key-value pair. The key is a short string identifier for that type, + * followed by the value. The valid type identifiers are: "tf" for bool, + * "i8" for byte, "i16" for 16-bit integer, "i32" for 32-bit integer, "i64" + * for 64-bit integer, "dbl" for double-precision loating point, "str" for + * string (including binary), "rec" for struct ("records"), "map" for map, + * "lst" for list, "set" for set. + * + * 6. Thrift lists and sets are represented as JSON arrays, with the first + * element of the JSON array being the string identifier for the Thrift + * element type and the second element of the JSON array being the count of + * the Thrift elements. The Thrift elements then follow. + * + * 7. Thrift maps are represented as JSON arrays, with the first two elements + * of the JSON array being the string identifiers for the Thrift key type + * and value type, followed by the count of the Thrift pairs, followed by a + * JSON object containing the key-value pairs. Note that JSON keys can only + * be strings, which means that the key type of the Thrift map should be + * restricted to numeric or string types -- in the case of numerics, they + * are serialized as strings. + * + * 8. Thrift messages are represented as JSON arrays, with the protocol + * version #, the message name, the message type, and the sequence ID as + * the first 4 elements. + * + * More discussion of the double handling is probably warranted. The aim of + * the current implementation is to match as closely as possible the behavior + * of Java's Double.toString(), which has no precision loss. Implementors in + * other languages should strive to achieve that where possible. I have not + * yet verified whether boost:lexical_cast, which is doing that work for me in + * C++, loses any precision, but I am leaving this as a future improvement. I + * may try to provide a C component for this, so that other languages could + * bind to the same underlying implementation for maximum consistency. + * + */ +class TJSONProtocol : public TVirtualProtocol { + public: + + TJSONProtocol(boost::shared_ptr ptrans); + + ~TJSONProtocol(); + + private: + + void pushContext(boost::shared_ptr c); + + void popContext(); + + uint32_t writeJSONEscapeChar(uint8_t ch); + + uint32_t writeJSONChar(uint8_t ch); + + uint32_t writeJSONString(const std::string &str); + + uint32_t writeJSONBase64(const std::string &str); + + template + uint32_t writeJSONInteger(NumberType num); + + uint32_t writeJSONDouble(double num); + + uint32_t writeJSONObjectStart() ; + + uint32_t writeJSONObjectEnd(); + + uint32_t writeJSONArrayStart(); + + uint32_t writeJSONArrayEnd(); + + uint32_t readJSONSyntaxChar(uint8_t ch); + + uint32_t readJSONEscapeChar(uint8_t *out); + + uint32_t readJSONString(std::string &str, bool skipContext = false); + + uint32_t readJSONBase64(std::string &str); + + uint32_t readJSONNumericChars(std::string &str); + + template + uint32_t readJSONInteger(NumberType &num); + + uint32_t readJSONDouble(double &num); + + uint32_t readJSONObjectStart(); + + uint32_t readJSONObjectEnd(); + + uint32_t readJSONArrayStart(); + + uint32_t readJSONArrayEnd(); + + public: + + /** + * Writing functions. + */ + + uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid); + + uint32_t writeMessageEnd(); + + uint32_t writeStructBegin(const char* name); + + uint32_t writeStructEnd(); + + uint32_t writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId); + + uint32_t writeFieldEnd(); + + uint32_t writeFieldStop(); + + uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size); + + uint32_t writeMapEnd(); + + uint32_t writeListBegin(const TType elemType, + const uint32_t size); + + uint32_t writeListEnd(); + + uint32_t writeSetBegin(const TType elemType, + const uint32_t size); + + uint32_t writeSetEnd(); + + uint32_t writeBool(const bool value); + + uint32_t writeByte(const int8_t byte); + + uint32_t writeI16(const int16_t i16); + + uint32_t writeI32(const int32_t i32); + + uint32_t writeI64(const int64_t i64); + + uint32_t writeDouble(const double dub); + + uint32_t writeString(const std::string& str); + + uint32_t writeBinary(const std::string& str); + + /** + * Reading functions + */ + + uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid); + + uint32_t readMessageEnd(); + + uint32_t readStructBegin(std::string& name); + + uint32_t readStructEnd(); + + uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId); + + uint32_t readFieldEnd(); + + uint32_t readMapBegin(TType& keyType, + TType& valType, + uint32_t& size); + + uint32_t readMapEnd(); + + uint32_t readListBegin(TType& elemType, + uint32_t& size); + + uint32_t readListEnd(); + + uint32_t readSetBegin(TType& elemType, + uint32_t& size); + + uint32_t readSetEnd(); + + uint32_t readBool(bool& value); + + // Provide the default readBool() implementation for std::vector + using TVirtualProtocol::readBool; + + uint32_t readByte(int8_t& byte); + + uint32_t readI16(int16_t& i16); + + uint32_t readI32(int32_t& i32); + + uint32_t readI64(int64_t& i64); + + uint32_t readDouble(double& dub); + + uint32_t readString(std::string& str); + + uint32_t readBinary(std::string& str); + + class LookaheadReader { + + public: + + LookaheadReader(TTransport &trans) : + trans_(&trans), + hasData_(false) { + } + + uint8_t read() { + if (hasData_) { + hasData_ = false; + } + else { + trans_->readAll(&data_, 1); + } + return data_; + } + + uint8_t peek() { + if (!hasData_) { + trans_->readAll(&data_, 1); + } + hasData_ = true; + return data_; + } + + private: + TTransport *trans_; + bool hasData_; + uint8_t data_; + }; + + private: + TTransport* trans_; + + std::stack > contexts_; + boost::shared_ptr context_; + LookaheadReader reader_; +}; + +/** + * Constructs input and output protocol objects given transports. + */ +class TJSONProtocolFactory : public TProtocolFactory { + public: + TJSONProtocolFactory() {} + + virtual ~TJSONProtocolFactory() {} + + boost::shared_ptr getProtocol(boost::shared_ptr trans) { + return boost::shared_ptr(new TJSONProtocol(trans)); + } +}; + +}}} // apache::thrift::protocol + + +// TODO(dreiss): Move part of ThriftJSONString into a .cpp file and remove this. +#include + +namespace apache { namespace thrift { + +template + std::string ThriftJSONString(const ThriftStruct& ts) { + using namespace apache::thrift::transport; + using namespace apache::thrift::protocol; + TMemoryBuffer* buffer = new TMemoryBuffer; + boost::shared_ptr trans(buffer); + TJSONProtocol protocol(trans); + + ts.write(&protocol); + + uint8_t* buf; + uint32_t size; + buffer->getBuffer(&buf, &size); + return std::string((char*)buf, (unsigned int)size); +} + +}} // apache::thrift + +#endif // #define _THRIFT_PROTOCOL_TJSONPROTOCOL_H_ 1 diff --git a/sg_agent/thrid_party/thrift/include/protocol/TProtocol.h b/sg_agent/thrid_party/thrift/include/protocol/TProtocol.h new file mode 100644 index 0000000..dfd5eb5 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/protocol/TProtocol.h @@ -0,0 +1,694 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_PROTOCOL_TPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1 + +#include +#include + +#include +#include + +#ifdef HAVE_NETINET_IN_H +#include +#endif +#include +#include +#include +#include + + +// Use this to get around strict aliasing rules. +// For example, uint64_t i = bitwise_cast(returns_double()); +// The most obvious implementation is to just cast a pointer, +// but that doesn't work. +// For a pretty in-depth explanation of the problem, see +// http://www.cellperformance.com/mike_acton/2006/06/ (...) +// understanding_strict_aliasing.html +template +static inline To bitwise_cast(From from) { + BOOST_STATIC_ASSERT(sizeof(From) == sizeof(To)); + + // BAD!!! These are all broken with -O2. + //return *reinterpret_cast(&from); // BAD!!! + //return *static_cast(static_cast(&from)); // BAD!!! + //return *(To*)(void*)&from; // BAD!!! + + // Super clean and paritally blessed by section 3.9 of the standard. + //unsigned char c[sizeof(from)]; + //memcpy(c, &from, sizeof(from)); + //To to; + //memcpy(&to, c, sizeof(c)); + //return to; + + // Slightly more questionable. + // Same code emitted by GCC. + //To to; + //memcpy(&to, &from, sizeof(from)); + //return to; + + // Technically undefined, but almost universally supported, + // and the most efficient implementation. + union { + From f; + To t; + } u; + u.f = from; + return u.t; +} + + +namespace apache { namespace thrift { namespace protocol { + +using apache::thrift::transport::TTransport; + +#ifdef HAVE_SYS_PARAM_H +#include +#endif + +#ifndef __BYTE_ORDER +# if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) +# define __BYTE_ORDER BYTE_ORDER +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __BIG_ENDIAN BIG_ENDIAN +# else +# include +# include +# define __BYTE_ORDER BOOST_BYTE_ORDER +# ifdef BOOST_LITTLE_ENDIAN +# define __LITTLE_ENDIAN __BYTE_ORDER +# define __BIG_ENDIAN 0 +# else +# define __LITTLE_ENDIAN 0 +# define __BIG_ENDIAN __BYTE_ORDER +# endif +# endif +#endif + +#if __BYTE_ORDER == __BIG_ENDIAN +# define ntohll(n) (n) +# define htonll(n) (n) +# if defined(__GNUC__) && defined(__GLIBC__) +# include +# define htolell(n) bswap_64(n) +# define letohll(n) bswap_64(n) +# else /* GNUC & GLIBC */ +# define bswap_64(n) \ + ( (((n) & 0xff00000000000000ull) >> 56) \ + | (((n) & 0x00ff000000000000ull) >> 40) \ + | (((n) & 0x0000ff0000000000ull) >> 24) \ + | (((n) & 0x000000ff00000000ull) >> 8) \ + | (((n) & 0x00000000ff000000ull) << 8) \ + | (((n) & 0x0000000000ff0000ull) << 24) \ + | (((n) & 0x000000000000ff00ull) << 40) \ + | (((n) & 0x00000000000000ffull) << 56) ) +# define htolell(n) bswap_64(n) +# define letohll(n) bswap_64(n) +# endif /* GNUC & GLIBC */ +#elif __BYTE_ORDER == __LITTLE_ENDIAN +# define htolell(n) (n) +# define letohll(n) (n) +# if defined(__GNUC__) && defined(__GLIBC__) +# include +# define ntohll(n) bswap_64(n) +# define htonll(n) bswap_64(n) +# else /* GNUC & GLIBC */ +# define ntohll(n) ( (((uint64_t)ntohl(n)) << 32) + ntohl(n >> 32) ) +# define htonll(n) ( (((uint64_t)htonl(n)) << 32) + htonl(n >> 32) ) +# endif /* GNUC & GLIBC */ +#else /* __BYTE_ORDER */ +# error "Can't define htonll or ntohll!" +#endif + +/** + * Enumerated definition of the types that the Thrift protocol supports. + * Take special note of the T_END type which is used specifically to mark + * the end of a sequence of fields. + */ +enum TType { + T_STOP = 0, + T_VOID = 1, + T_BOOL = 2, + T_BYTE = 3, + T_I08 = 3, + T_I16 = 6, + T_I32 = 8, + T_U64 = 9, + T_I64 = 10, + T_DOUBLE = 4, + T_STRING = 11, + T_UTF7 = 11, + T_STRUCT = 12, + T_MAP = 13, + T_SET = 14, + T_LIST = 15, + T_UTF8 = 16, + T_UTF16 = 17 +}; + +/** + * Enumerated definition of the message types that the Thrift protocol + * supports. + */ +enum TMessageType { + T_CALL = 1, + T_REPLY = 2, + T_EXCEPTION = 3, + T_ONEWAY = 4 +}; + + +/** + * Helper template for implementing TProtocol::skip(). + * + * Templatized to avoid having to make virtual function calls. + */ +template +uint32_t skip(Protocol_& prot, TType type) { + switch (type) { + case T_BOOL: + { + bool boolv; + return prot.readBool(boolv); + } + case T_BYTE: + { + int8_t bytev; + return prot.readByte(bytev); + } + case T_I16: + { + int16_t i16; + return prot.readI16(i16); + } + case T_I32: + { + int32_t i32; + return prot.readI32(i32); + } + case T_I64: + { + int64_t i64; + return prot.readI64(i64); + } + case T_DOUBLE: + { + double dub; + return prot.readDouble(dub); + } + case T_STRING: + { + std::string str; + return prot.readBinary(str); + } + case T_STRUCT: + { + uint32_t result = 0; + std::string name; + int16_t fid; + TType ftype; + result += prot.readStructBegin(name); + while (true) { + result += prot.readFieldBegin(name, ftype, fid); + if (ftype == T_STOP) { + break; + } + result += skip(prot, ftype); + result += prot.readFieldEnd(); + } + result += prot.readStructEnd(); + return result; + } + case T_MAP: + { + uint32_t result = 0; + TType keyType; + TType valType; + uint32_t i, size; + result += prot.readMapBegin(keyType, valType, size); + for (i = 0; i < size; i++) { + result += skip(prot, keyType); + result += skip(prot, valType); + } + result += prot.readMapEnd(); + return result; + } + case T_SET: + { + uint32_t result = 0; + TType elemType; + uint32_t i, size; + result += prot.readSetBegin(elemType, size); + for (i = 0; i < size; i++) { + result += skip(prot, elemType); + } + result += prot.readSetEnd(); + return result; + } + case T_LIST: + { + uint32_t result = 0; + TType elemType; + uint32_t i, size; + result += prot.readListBegin(elemType, size); + for (i = 0; i < size; i++) { + result += skip(prot, elemType); + } + result += prot.readListEnd(); + return result; + } + case T_STOP: case T_VOID: case T_U64: case T_UTF8: case T_UTF16: + break; + } + return 0; +} + +/** + * Abstract class for a thrift protocol driver. These are all the methods that + * a protocol must implement. Essentially, there must be some way of reading + * and writing all the base types, plus a mechanism for writing out structs + * with indexed fields. + * + * TProtocol objects should not be shared across multiple encoding contexts, + * as they may need to maintain internal state in some protocols (i.e. XML). + * Note that is is acceptable for the TProtocol module to do its own internal + * buffered reads/writes to the underlying TTransport where appropriate (i.e. + * when parsing an input XML stream, reading should be batched rather than + * looking ahead character by character for a close tag). + * + */ +class TProtocol { + public: + virtual ~TProtocol() {} + + /** + * Writing functions. + */ + + virtual uint32_t writeMessageBegin_virt(const std::string& name, + const TMessageType messageType, + const int32_t seqid) = 0; + + virtual uint32_t writeMessageEnd_virt() = 0; + + + virtual uint32_t writeStructBegin_virt(const char* name) = 0; + + virtual uint32_t writeStructEnd_virt() = 0; + + virtual uint32_t writeFieldBegin_virt(const char* name, + const TType fieldType, + const int16_t fieldId) = 0; + + virtual uint32_t writeFieldEnd_virt() = 0; + + virtual uint32_t writeFieldStop_virt() = 0; + + virtual uint32_t writeMapBegin_virt(const TType keyType, + const TType valType, + const uint32_t size) = 0; + + virtual uint32_t writeMapEnd_virt() = 0; + + virtual uint32_t writeListBegin_virt(const TType elemType, + const uint32_t size) = 0; + + virtual uint32_t writeListEnd_virt() = 0; + + virtual uint32_t writeSetBegin_virt(const TType elemType, + const uint32_t size) = 0; + + virtual uint32_t writeSetEnd_virt() = 0; + + virtual uint32_t writeBool_virt(const bool value) = 0; + + virtual uint32_t writeByte_virt(const int8_t byte) = 0; + + virtual uint32_t writeI16_virt(const int16_t i16) = 0; + + virtual uint32_t writeI32_virt(const int32_t i32) = 0; + + virtual uint32_t writeI64_virt(const int64_t i64) = 0; + + virtual uint32_t writeDouble_virt(const double dub) = 0; + + virtual uint32_t writeString_virt(const std::string& str) = 0; + + virtual uint32_t writeBinary_virt(const std::string& str) = 0; + + uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid) { + T_VIRTUAL_CALL(); + return writeMessageBegin_virt(name, messageType, seqid); + } + + uint32_t writeMessageEnd() { + T_VIRTUAL_CALL(); + return writeMessageEnd_virt(); + } + + + uint32_t writeStructBegin(const char* name) { + T_VIRTUAL_CALL(); + return writeStructBegin_virt(name); + } + + uint32_t writeStructEnd() { + T_VIRTUAL_CALL(); + return writeStructEnd_virt(); + } + + uint32_t writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId) { + T_VIRTUAL_CALL(); + return writeFieldBegin_virt(name, fieldType, fieldId); + } + + uint32_t writeFieldEnd() { + T_VIRTUAL_CALL(); + return writeFieldEnd_virt(); + } + + uint32_t writeFieldStop() { + T_VIRTUAL_CALL(); + return writeFieldStop_virt(); + } + + uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size) { + T_VIRTUAL_CALL(); + return writeMapBegin_virt(keyType, valType, size); + } + + uint32_t writeMapEnd() { + T_VIRTUAL_CALL(); + return writeMapEnd_virt(); + } + + uint32_t writeListBegin(const TType elemType, const uint32_t size) { + T_VIRTUAL_CALL(); + return writeListBegin_virt(elemType, size); + } + + uint32_t writeListEnd() { + T_VIRTUAL_CALL(); + return writeListEnd_virt(); + } + + uint32_t writeSetBegin(const TType elemType, const uint32_t size) { + T_VIRTUAL_CALL(); + return writeSetBegin_virt(elemType, size); + } + + uint32_t writeSetEnd() { + T_VIRTUAL_CALL(); + return writeSetEnd_virt(); + } + + uint32_t writeBool(const bool value) { + T_VIRTUAL_CALL(); + return writeBool_virt(value); + } + + uint32_t writeByte(const int8_t byte) { + T_VIRTUAL_CALL(); + return writeByte_virt(byte); + } + + uint32_t writeI16(const int16_t i16) { + T_VIRTUAL_CALL(); + return writeI16_virt(i16); + } + + uint32_t writeI32(const int32_t i32) { + T_VIRTUAL_CALL(); + return writeI32_virt(i32); + } + + uint32_t writeI64(const int64_t i64) { + T_VIRTUAL_CALL(); + return writeI64_virt(i64); + } + + uint32_t writeDouble(const double dub) { + T_VIRTUAL_CALL(); + return writeDouble_virt(dub); + } + + uint32_t writeString(const std::string& str) { + T_VIRTUAL_CALL(); + return writeString_virt(str); + } + + uint32_t writeBinary(const std::string& str) { + T_VIRTUAL_CALL(); + return writeBinary_virt(str); + } + + /** + * Reading functions + */ + + virtual uint32_t readMessageBegin_virt(std::string& name, + TMessageType& messageType, + int32_t& seqid) = 0; + + virtual uint32_t readMessageEnd_virt() = 0; + + virtual uint32_t readStructBegin_virt(std::string& name) = 0; + + virtual uint32_t readStructEnd_virt() = 0; + + virtual uint32_t readFieldBegin_virt(std::string& name, + TType& fieldType, + int16_t& fieldId) = 0; + + virtual uint32_t readFieldEnd_virt() = 0; + + virtual uint32_t readMapBegin_virt(TType& keyType, + TType& valType, + uint32_t& size) = 0; + + virtual uint32_t readMapEnd_virt() = 0; + + virtual uint32_t readListBegin_virt(TType& elemType, + uint32_t& size) = 0; + + virtual uint32_t readListEnd_virt() = 0; + + virtual uint32_t readSetBegin_virt(TType& elemType, + uint32_t& size) = 0; + + virtual uint32_t readSetEnd_virt() = 0; + + virtual uint32_t readBool_virt(bool& value) = 0; + + virtual uint32_t readBool_virt(std::vector::reference value) = 0; + + virtual uint32_t readByte_virt(int8_t& byte) = 0; + + virtual uint32_t readI16_virt(int16_t& i16) = 0; + + virtual uint32_t readI32_virt(int32_t& i32) = 0; + + virtual uint32_t readI64_virt(int64_t& i64) = 0; + + virtual uint32_t readDouble_virt(double& dub) = 0; + + virtual uint32_t readString_virt(std::string& str) = 0; + + virtual uint32_t readBinary_virt(std::string& str) = 0; + + uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid) { + T_VIRTUAL_CALL(); + return readMessageBegin_virt(name, messageType, seqid); + } + + uint32_t readMessageEnd() { + T_VIRTUAL_CALL(); + return readMessageEnd_virt(); + } + + uint32_t readStructBegin(std::string& name) { + T_VIRTUAL_CALL(); + return readStructBegin_virt(name); + } + + uint32_t readStructEnd() { + T_VIRTUAL_CALL(); + return readStructEnd_virt(); + } + + uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId) { + T_VIRTUAL_CALL(); + return readFieldBegin_virt(name, fieldType, fieldId); + } + + uint32_t readFieldEnd() { + T_VIRTUAL_CALL(); + return readFieldEnd_virt(); + } + + uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size) { + T_VIRTUAL_CALL(); + return readMapBegin_virt(keyType, valType, size); + } + + uint32_t readMapEnd() { + T_VIRTUAL_CALL(); + return readMapEnd_virt(); + } + + uint32_t readListBegin(TType& elemType, uint32_t& size) { + T_VIRTUAL_CALL(); + return readListBegin_virt(elemType, size); + } + + uint32_t readListEnd() { + T_VIRTUAL_CALL(); + return readListEnd_virt(); + } + + uint32_t readSetBegin(TType& elemType, uint32_t& size) { + T_VIRTUAL_CALL(); + return readSetBegin_virt(elemType, size); + } + + uint32_t readSetEnd() { + T_VIRTUAL_CALL(); + return readSetEnd_virt(); + } + + uint32_t readBool(bool& value) { + T_VIRTUAL_CALL(); + return readBool_virt(value); + } + + uint32_t readByte(int8_t& byte) { + T_VIRTUAL_CALL(); + return readByte_virt(byte); + } + + uint32_t readI16(int16_t& i16) { + T_VIRTUAL_CALL(); + return readI16_virt(i16); + } + + uint32_t readI32(int32_t& i32) { + T_VIRTUAL_CALL(); + return readI32_virt(i32); + } + + uint32_t readI64(int64_t& i64) { + T_VIRTUAL_CALL(); + return readI64_virt(i64); + } + + uint32_t readDouble(double& dub) { + T_VIRTUAL_CALL(); + return readDouble_virt(dub); + } + + uint32_t readString(std::string& str) { + T_VIRTUAL_CALL(); + return readString_virt(str); + } + + uint32_t readBinary(std::string& str) { + T_VIRTUAL_CALL(); + return readBinary_virt(str); + } + + /* + * std::vector is specialized for bool, and its elements are individual bits + * rather than bools. We need to define a different version of readBool() + * to work with std::vector. + */ + uint32_t readBool(std::vector::reference value) { + T_VIRTUAL_CALL(); + return readBool_virt(value); + } + + /** + * Method to arbitrarily skip over data. + */ + uint32_t skip(TType type) { + T_VIRTUAL_CALL(); + return skip_virt(type); + } + virtual uint32_t skip_virt(TType type) { + return ::apache::thrift::protocol::skip(*this, type); + } + + inline boost::shared_ptr getTransport() { + return ptrans_; + } + + // TODO: remove these two calls, they are for backwards + // compatibility + inline boost::shared_ptr getInputTransport() { + return ptrans_; + } + inline boost::shared_ptr getOutputTransport() { + return ptrans_; + } + + protected: + TProtocol(boost::shared_ptr ptrans): + ptrans_(ptrans) { + } + + boost::shared_ptr ptrans_; + + private: + TProtocol() {} +}; + +/** + * Constructs input and output protocol objects given transports. + */ +class TProtocolFactory { + public: + TProtocolFactory() {} + + virtual ~TProtocolFactory() {} + + virtual boost::shared_ptr getProtocol(boost::shared_ptr trans) = 0; +}; + +/** + * Dummy protocol class. + * + * This class does nothing, and should never be instantiated. + * It is used only by the generator code. + */ +class TDummyProtocol : public TProtocol { +}; + +}}} // apache::thrift::protocol + +#endif // #define _THRIFT_PROTOCOL_TPROTOCOL_H_ 1 diff --git a/sg_agent/thrid_party/thrift/include/protocol/TProtocolException.h b/sg_agent/thrid_party/thrift/include/protocol/TProtocolException.h new file mode 100644 index 0000000..a03d3c8 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/protocol/TProtocolException.h @@ -0,0 +1,104 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_ +#define _THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_ 1 + +#include + +namespace apache { namespace thrift { namespace protocol { + +/** + * Class to encapsulate all the possible types of protocol errors that may + * occur in various protocol systems. This provides a sort of generic + * wrapper around the vague UNIX E_ error codes that lets a common code + * base of error handling to be used for various types of protocols, i.e. + * pipes etc. + * + */ +class TProtocolException : public apache::thrift::TException { + public: + + /** + * Error codes for the various types of exceptions. + */ + enum TProtocolExceptionType + { UNKNOWN = 0 + , INVALID_DATA = 1 + , NEGATIVE_SIZE = 2 + , SIZE_LIMIT = 3 + , BAD_VERSION = 4 + , NOT_IMPLEMENTED = 5 + }; + + TProtocolException() : + apache::thrift::TException(), + type_(UNKNOWN) {} + + TProtocolException(TProtocolExceptionType type) : + apache::thrift::TException(), + type_(type) {} + + TProtocolException(const std::string& message) : + apache::thrift::TException(message), + type_(UNKNOWN) {} + + TProtocolException(TProtocolExceptionType type, const std::string& message) : + apache::thrift::TException(message), + type_(type) {} + + virtual ~TProtocolException() throw() {} + + /** + * Returns an error code that provides information about the type of error + * that has occurred. + * + * @return Error code + */ + TProtocolExceptionType getType() { + return type_; + } + + virtual const char* what() const throw() { + if (message_.empty()) { + switch (type_) { + case UNKNOWN : return "TProtocolException: Unknown protocol exception"; + case INVALID_DATA : return "TProtocolException: Invalid data"; + case NEGATIVE_SIZE : return "TProtocolException: Negative size"; + case SIZE_LIMIT : return "TProtocolException: Exceeded size limit"; + case BAD_VERSION : return "TProtocolException: Invalid version"; + case NOT_IMPLEMENTED : return "TProtocolException: Not implemented"; + default : return "TProtocolException: (Invalid exception type)"; + } + } else { + return message_.c_str(); + } + } + + protected: + /** + * Error code + */ + TProtocolExceptionType type_; + +}; + +}}} // apache::thrift::protocol + +#endif // #ifndef _THRIFT_PROTOCOL_TPROTOCOLEXCEPTION_H_ diff --git a/sg_agent/thrid_party/thrift/include/protocol/TProtocolTap.h b/sg_agent/thrid_party/thrift/include/protocol/TProtocolTap.h new file mode 100644 index 0000000..3772bff --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/protocol/TProtocolTap.h @@ -0,0 +1,188 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_PROTOCOL_TPROTOCOLTAP_H_ +#define _THRIFT_PROTOCOL_TPROTOCOLTAP_H_ 1 + +#include + +namespace apache { namespace thrift { namespace protocol { + +using apache::thrift::transport::TTransport; + +/** + * Puts a wiretap on a protocol object. Any reads to this class are passed + * through to an enclosed protocol object, but also mirrored as write to a + * second protocol object. + * + */ +class TProtocolTap : public TVirtualProtocol { + public: + TProtocolTap(boost::shared_ptr source, + boost::shared_ptr sink) + : TVirtualProtocol(source->getTransport()) + , source_(source) + , sink_(sink) + {} + + uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid) { + uint32_t rv = source_->readMessageBegin(name, messageType, seqid); + sink_->writeMessageBegin(name, messageType, seqid); + return rv; + } + + uint32_t readMessageEnd() { + uint32_t rv = source_->readMessageEnd(); + sink_->writeMessageEnd(); + return rv; + } + + uint32_t readStructBegin(std::string& name) { + uint32_t rv = source_->readStructBegin(name); + sink_->writeStructBegin(name.c_str()); + return rv; + } + + uint32_t readStructEnd() { + uint32_t rv = source_->readStructEnd(); + sink_->writeStructEnd(); + return rv; + } + + uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId) { + uint32_t rv = source_->readFieldBegin(name, fieldType, fieldId); + if (fieldType == T_STOP) { + sink_->writeFieldStop(); + } else { + sink_->writeFieldBegin(name.c_str(), fieldType, fieldId); + } + return rv; + } + + + uint32_t readFieldEnd() { + uint32_t rv = source_->readFieldEnd(); + sink_->writeFieldEnd(); + return rv; + } + + uint32_t readMapBegin(TType& keyType, + TType& valType, + uint32_t& size) { + uint32_t rv = source_->readMapBegin(keyType, valType, size); + sink_->writeMapBegin(keyType, valType, size); + return rv; + } + + + uint32_t readMapEnd() { + uint32_t rv = source_->readMapEnd(); + sink_->writeMapEnd(); + return rv; + } + + uint32_t readListBegin(TType& elemType, uint32_t& size) { + uint32_t rv = source_->readListBegin(elemType, size); + sink_->writeListBegin(elemType, size); + return rv; + } + + + uint32_t readListEnd() { + uint32_t rv = source_->readListEnd(); + sink_->writeListEnd(); + return rv; + } + + uint32_t readSetBegin(TType& elemType, uint32_t& size) { + uint32_t rv = source_->readSetBegin(elemType, size); + sink_->writeSetBegin(elemType, size); + return rv; + } + + + uint32_t readSetEnd() { + uint32_t rv = source_->readSetEnd(); + sink_->writeSetEnd(); + return rv; + } + + uint32_t readBool(bool& value) { + uint32_t rv = source_->readBool(value); + sink_->writeBool(value); + return rv; + } + + // Provide the default readBool() implementation for std::vector + using TVirtualProtocol::readBool; + + uint32_t readByte(int8_t& byte) { + uint32_t rv = source_->readByte(byte); + sink_->writeByte(byte); + return rv; + } + + uint32_t readI16(int16_t& i16) { + uint32_t rv = source_->readI16(i16); + sink_->writeI16(i16); + return rv; + } + + uint32_t readI32(int32_t& i32) { + uint32_t rv = source_->readI32(i32); + sink_->writeI32(i32); + return rv; + } + + uint32_t readI64(int64_t& i64) { + uint32_t rv = source_->readI64(i64); + sink_->writeI64(i64); + return rv; + } + + uint32_t readDouble(double& dub) { + uint32_t rv = source_->readDouble(dub); + sink_->writeDouble(dub); + return rv; + } + + uint32_t readString(std::string& str) { + uint32_t rv = source_->readString(str); + sink_->writeString(str); + return rv; + } + + uint32_t readBinary(std::string& str) { + uint32_t rv = source_->readBinary(str); + sink_->writeBinary(str); + return rv; + } + + private: + boost::shared_ptr source_; + boost::shared_ptr sink_; +}; + +}}} // apache::thrift::protocol + +#endif // #define _THRIFT_PROTOCOL_TPROTOCOLTAP_H_ 1 diff --git a/sg_agent/thrid_party/thrift/include/protocol/TVirtualProtocol.h b/sg_agent/thrid_party/thrift/include/protocol/TVirtualProtocol.h new file mode 100644 index 0000000..6c7f519 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/protocol/TVirtualProtocol.h @@ -0,0 +1,564 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_PROTOCOL_TVIRTUALPROTOCOL_H_ +#define _THRIFT_PROTOCOL_TVIRTUALPROTOCOL_H_ 1 + +#include + +namespace apache { namespace thrift { namespace protocol { + +using apache::thrift::transport::TTransport; + +/** + * Helper class that provides default implementations of TProtocol methods. + * + * This class provides default implementations of the non-virtual TProtocol + * methods. It exists primarily so TVirtualProtocol can derive from it. It + * prevents TVirtualProtocol methods from causing infinite recursion if the + * non-virtual methods are not overridden by the TVirtualProtocol subclass. + * + * You probably don't want to use this class directly. Use TVirtualProtocol + * instead. + */ +class TProtocolDefaults : public TProtocol { + public: + uint32_t readMessageBegin(std::string& name, + TMessageType& messageType, + int32_t& seqid) { + (void) name; + (void) messageType; + (void) seqid; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readMessageEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readStructBegin(std::string& name) { + (void) name; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readStructEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readFieldBegin(std::string& name, + TType& fieldType, + int16_t& fieldId) { + (void) name; + (void) fieldType; + (void) fieldId; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readFieldEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readMapBegin(TType& keyType, TType& valType, uint32_t& size) { + (void) keyType; + (void) valType; + (void) size; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readMapEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readListBegin(TType& elemType, uint32_t& size) { + (void) elemType; + (void) size; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readListEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readSetBegin(TType& elemType, uint32_t& size) { + (void) elemType; + (void) size; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readSetEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readBool(bool& value) { + (void) value; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readBool(std::vector::reference value) { + (void) value; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readByte(int8_t& byte) { + (void) byte; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readI16(int16_t& i16) { + (void) i16; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readI32(int32_t& i32) { + (void) i32; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readI64(int64_t& i64) { + (void) i64; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readDouble(double& dub) { + (void) dub; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readString(std::string& str) { + (void) str; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t readBinary(std::string& str) { + (void) str; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support reading (yet)."); + } + + uint32_t writeMessageBegin(const std::string& name, + const TMessageType messageType, + const int32_t seqid) { + (void) name; + (void) messageType; + (void) seqid; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeMessageEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + + uint32_t writeStructBegin(const char* name) { + (void) name; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeStructEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeFieldBegin(const char* name, + const TType fieldType, + const int16_t fieldId) { + (void) name; + (void) fieldType; + (void) fieldId; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeFieldEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeFieldStop() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeMapBegin(const TType keyType, + const TType valType, + const uint32_t size) { + (void) keyType; + (void) valType; + (void) size; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeMapEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeListBegin(const TType elemType, const uint32_t size) { + (void) elemType; + (void) size; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeListEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeSetBegin(const TType elemType, const uint32_t size) { + (void) elemType; + (void) size; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeSetEnd() { + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeBool(const bool value) { + (void) value; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeByte(const int8_t byte) { + (void) byte; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeI16(const int16_t i16) { + (void) i16; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeI32(const int32_t i32) { + (void) i32; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeI64(const int64_t i64) { + (void) i64; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeDouble(const double dub) { + (void) dub; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeString(const std::string& str) { + (void) str; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t writeBinary(const std::string& str) { + (void) str; + throw TProtocolException(TProtocolException::NOT_IMPLEMENTED, + "this protocol does not support writing (yet)."); + } + + uint32_t skip(TType type) { + return ::apache::thrift::protocol::skip(*this, type); + } + + protected: + TProtocolDefaults(boost::shared_ptr ptrans) + : TProtocol(ptrans) + {} +}; + +/** + * Concrete TProtocol classes should inherit from TVirtualProtocol + * so they don't have to manually override virtual methods. + */ +template +class TVirtualProtocol : public Super_ { + public: + /** + * Writing functions. + */ + + virtual uint32_t writeMessageBegin_virt(const std::string& name, + const TMessageType messageType, + const int32_t seqid) { + return static_cast(this)->writeMessageBegin(name, messageType, + seqid); + } + + virtual uint32_t writeMessageEnd_virt() { + return static_cast(this)->writeMessageEnd(); + } + + + virtual uint32_t writeStructBegin_virt(const char* name) { + return static_cast(this)->writeStructBegin(name); + } + + virtual uint32_t writeStructEnd_virt() { + return static_cast(this)->writeStructEnd(); + } + + virtual uint32_t writeFieldBegin_virt(const char* name, + const TType fieldType, + const int16_t fieldId) { + return static_cast(this)->writeFieldBegin(name, fieldType, + fieldId); + } + + virtual uint32_t writeFieldEnd_virt() { + return static_cast(this)->writeFieldEnd(); + } + + virtual uint32_t writeFieldStop_virt() { + return static_cast(this)->writeFieldStop(); + } + + virtual uint32_t writeMapBegin_virt(const TType keyType, + const TType valType, + const uint32_t size) { + return static_cast(this)->writeMapBegin(keyType, valType, size); + } + + virtual uint32_t writeMapEnd_virt() { + return static_cast(this)->writeMapEnd(); + } + + virtual uint32_t writeListBegin_virt(const TType elemType, + const uint32_t size) { + return static_cast(this)->writeListBegin(elemType, size); + } + + virtual uint32_t writeListEnd_virt() { + return static_cast(this)->writeListEnd(); + } + + virtual uint32_t writeSetBegin_virt(const TType elemType, + const uint32_t size) { + return static_cast(this)->writeSetBegin(elemType, size); + } + + virtual uint32_t writeSetEnd_virt() { + return static_cast(this)->writeSetEnd(); + } + + virtual uint32_t writeBool_virt(const bool value) { + return static_cast(this)->writeBool(value); + } + + virtual uint32_t writeByte_virt(const int8_t byte) { + return static_cast(this)->writeByte(byte); + } + + virtual uint32_t writeI16_virt(const int16_t i16) { + return static_cast(this)->writeI16(i16); + } + + virtual uint32_t writeI32_virt(const int32_t i32) { + return static_cast(this)->writeI32(i32); + } + + virtual uint32_t writeI64_virt(const int64_t i64) { + return static_cast(this)->writeI64(i64); + } + + virtual uint32_t writeDouble_virt(const double dub) { + return static_cast(this)->writeDouble(dub); + } + + virtual uint32_t writeString_virt(const std::string& str) { + return static_cast(this)->writeString(str); + } + + virtual uint32_t writeBinary_virt(const std::string& str) { + return static_cast(this)->writeBinary(str); + } + + /** + * Reading functions + */ + + virtual uint32_t readMessageBegin_virt(std::string& name, + TMessageType& messageType, + int32_t& seqid) { + return static_cast(this)->readMessageBegin(name, messageType, + seqid); + } + + virtual uint32_t readMessageEnd_virt() { + return static_cast(this)->readMessageEnd(); + } + + virtual uint32_t readStructBegin_virt(std::string& name) { + return static_cast(this)->readStructBegin(name); + } + + virtual uint32_t readStructEnd_virt() { + return static_cast(this)->readStructEnd(); + } + + virtual uint32_t readFieldBegin_virt(std::string& name, + TType& fieldType, + int16_t& fieldId) { + return static_cast(this)->readFieldBegin(name, fieldType, + fieldId); + } + + virtual uint32_t readFieldEnd_virt() { + return static_cast(this)->readFieldEnd(); + } + + virtual uint32_t readMapBegin_virt(TType& keyType, + TType& valType, + uint32_t& size) { + return static_cast(this)->readMapBegin(keyType, valType, size); + } + + virtual uint32_t readMapEnd_virt() { + return static_cast(this)->readMapEnd(); + } + + virtual uint32_t readListBegin_virt(TType& elemType, + uint32_t& size) { + return static_cast(this)->readListBegin(elemType, size); + } + + virtual uint32_t readListEnd_virt() { + return static_cast(this)->readListEnd(); + } + + virtual uint32_t readSetBegin_virt(TType& elemType, + uint32_t& size) { + return static_cast(this)->readSetBegin(elemType, size); + } + + virtual uint32_t readSetEnd_virt() { + return static_cast(this)->readSetEnd(); + } + + virtual uint32_t readBool_virt(bool& value) { + return static_cast(this)->readBool(value); + } + + virtual uint32_t readBool_virt(std::vector::reference value) { + return static_cast(this)->readBool(value); + } + + virtual uint32_t readByte_virt(int8_t& byte) { + return static_cast(this)->readByte(byte); + } + + virtual uint32_t readI16_virt(int16_t& i16) { + return static_cast(this)->readI16(i16); + } + + virtual uint32_t readI32_virt(int32_t& i32) { + return static_cast(this)->readI32(i32); + } + + virtual uint32_t readI64_virt(int64_t& i64) { + return static_cast(this)->readI64(i64); + } + + virtual uint32_t readDouble_virt(double& dub) { + return static_cast(this)->readDouble(dub); + } + + virtual uint32_t readString_virt(std::string& str) { + return static_cast(this)->readString(str); + } + + virtual uint32_t readBinary_virt(std::string& str) { + return static_cast(this)->readBinary(str); + } + + virtual uint32_t skip_virt(TType type) { + return static_cast(this)->skip(type); + } + + /* + * Provide a default skip() implementation that uses non-virtual read + * methods. + * + * Note: subclasses that use TVirtualProtocol to derive from another protocol + * implementation (i.e., not TProtocolDefaults) should beware that this may + * override any non-default skip() implementation provided by the parent + * transport class. They may need to explicitly redefine skip() to call the + * correct parent implementation, if desired. + */ + uint32_t skip(TType type) { + Protocol_* const prot = static_cast(this); + return ::apache::thrift::protocol::skip(*prot, type); + } + + /* + * Provide a default readBool() implementation for use with + * std::vector, that behaves the same as reading into a normal bool. + * + * Subclasses can override this if desired, but there normally shouldn't + * be a need to. + */ + uint32_t readBool(std::vector::reference value) { + bool b = false; + uint32_t ret = static_cast(this)->readBool(b); + value = b; + return ret; + } + using Super_::readBool; // so we don't hide readBool(bool&) + + protected: + TVirtualProtocol(boost::shared_ptr ptrans) + : Super_(ptrans) + {} +}; + +}}} // apache::thrift::protocol + +#endif // #define _THRIFT_PROTOCOL_TVIRTUALPROTOCOL_H_ 1 diff --git a/sg_agent/thrid_party/thrift/include/server/TNonblockingServer.cpp b/sg_agent/thrid_party/thrift/include/server/TNonblockingServer.cpp new file mode 100644 index 0000000..d772dfe --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/server/TNonblockingServer.cpp @@ -0,0 +1,1271 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "TNonblockingServer.h" +#include +#include + +#include + +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +#ifdef HAVE_NETINET_IN_H +#include +#include +#endif + +#ifdef HAVE_ARPA_INET_H +#include +#endif + +#ifdef HAVE_NETDB_H +#include +#endif + +#ifdef HAVE_FCNTL_H +#include +#endif + +#include +#include + +#ifndef AF_LOCAL +#define AF_LOCAL AF_UNIX +#endif + +namespace apache { namespace thrift { namespace server { + +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; +using namespace apache::thrift::concurrency; +using namespace std; +using apache::thrift::transport::TSocket; +using apache::thrift::transport::TTransportException; + +/// Three states for sockets: recv frame size, recv data, and send mode +enum TSocketState { + SOCKET_RECV_FRAMING, + SOCKET_RECV, + SOCKET_SEND +}; + +/** + * Five states for the nonblocking server: + * 1) initialize + * 2) read 4 byte frame size + * 3) read frame of data + * 4) send back data (if any) + * 5) force immediate connection close + */ +enum TAppState { + APP_INIT, + APP_READ_FRAME_SIZE, + APP_READ_REQUEST, + APP_WAIT_TASK, + APP_SEND_RESULT, + APP_CLOSE_CONNECTION +}; + +/** + * Represents a connection that is handled via libevent. This connection + * essentially encapsulates a socket that has some associated libevent state. + */ +class TNonblockingServer::TConnection { + private: + + /// Server handle + TNonblockingServer* server_; + + /// TProcessor + boost::shared_ptr processor_; + + /// Object wrapping network socket + boost::shared_ptr tSocket_; + + /// Libevent object + struct event event_; + + /// Libevent flags + short eventFlags_; + + /// Socket mode + TSocketState socketState_; + + /// Application state + TAppState appState_; + + /// How much data needed to read + uint32_t readWant_; + + /// Which sgagent is used + int sgagentIndex_; + + /// Where in the read buffer are we + uint32_t readBufferPos_; + + /// Read buffer + uint8_t* readBuffer_; + + /// Read buffer size + uint32_t readBufferSize_; + + /// Write buffer + uint8_t* writeBuffer_; + + /// Write buffer size + uint32_t writeBufferSize_; + + /// How far through writing are we? + uint32_t writeBufferPos_; + + /// Largest size of write buffer seen since buffer was constructed + size_t largestWriteBufferSize_; + + /// Count of the number of calls for use with getResizeBufferEveryN(). + int32_t callsForResize_; + + /// Task handle + int taskHandle_; + + /// Task event + struct event taskEvent_; + + /// Transport to read from + boost::shared_ptr inputTransport_; + + /// Transport that processor writes to + boost::shared_ptr outputTransport_; + + /// extra transport generated by transport factory (e.g. BufferedRouterTransport) + boost::shared_ptr factoryInputTransport_; + boost::shared_ptr factoryOutputTransport_; + + /// Protocol decoder + boost::shared_ptr inputProtocol_; + + /// Protocol encoder + boost::shared_ptr outputProtocol_; + + /// Server event handler, if any + boost::shared_ptr serverEventHandler_; + + /// Thrift call context, if any + void *connectionContext_; + + /// Go into read mode + void setRead() { + setFlags(EV_READ | EV_PERSIST); + } + + /// Go into write mode + void setWrite() { + setFlags(EV_WRITE | EV_PERSIST); + } + + /// Set socket idle + void setIdle() { + setFlags(0); + } + + /** + * Set event flags for this connection. + * + * @param eventFlags flags we pass to libevent for the connection. + */ + void setFlags(short eventFlags); + + /** + * Libevent handler called (via our static wrapper) when the connection + * socket had something happen. Rather than use the flags libevent passed, + * we use the connection state to determine whether we need to read or + * write the socket. + */ + void workSocket(); + + /// Close this connection and free or reset its resources. + void close(); + + public: + + class Task; + + /// Constructor + TConnection(int socket, short eventFlags, TNonblockingServer *s, + const sockaddr* addr, socklen_t addrLen, int sgagentIndex) { + readBuffer_ = NULL; + readBufferSize_ = 0; + sgagentIndex_ = sgagentIndex; + + // Allocate input and output transports + // these only need to be allocated once per TConnection (they don't need to be + // reallocated on init() call) + inputTransport_ = boost::shared_ptr(new TMemoryBuffer(readBuffer_, readBufferSize_)); + outputTransport_ = boost::shared_ptr(new TMemoryBuffer(s->getWriteBufferDefaultSize())); + tSocket_.reset(new TSocket()); + + init(socket, eventFlags, s, addr, addrLen); + server_->incrementNumConnections(); + } + + ~TConnection() { + std::free(readBuffer_); + server_->decrementNumConnections(); + } + + /** + * Check buffers against any size limits and shrink it if exceeded. + * + * @param readLimit we reduce read buffer size to this (if nonzero). + * @param writeLimit if nonzero and write buffer is larger, replace it. + */ + void checkIdleBufferMemLimit(size_t readLimit, size_t writeLimit); + + /// Initialize + void init(int socket, short eventFlags, TNonblockingServer *s, + const sockaddr* addr, socklen_t addrLen); + + /** + * This is called when the application transitions from one state into + * another. This means that it has finished writing the data that it needed + * to, or finished receiving the data that it needed to. + */ + void transition(); + + /** + * C-callable event handler for connection events. Provides a callback + * that libevent can understand which invokes connection_->workSocket(). + * + * @param fd the descriptor the event occurred on. + * @param which the flags associated with the event. + * @param v void* callback arg where we placed TConnection's "this". + */ + static void eventHandler(evutil_socket_t fd, short /* which */, void* v) { + assert(fd == ((TConnection*)v)->getTSocket()->getSocketFD()); + ((TConnection*)v)->workSocket(); + } + + /** + * C-callable event handler for signaling task completion. Provides a + * callback that libevent can understand that will read a connection + * object's address from a pipe and call connection->transition() for + * that object. + * + * @param fd the descriptor the event occurred on. + */ + static void taskHandler(evutil_socket_t fd, short /* which */, void* /* v */) { + TConnection* connection; + ssize_t nBytes; + while ((nBytes = recv(fd, cast_sockopt(&connection), sizeof(TConnection*), 0)) + == sizeof(TConnection*)) { + connection->transition(); + } + if (nBytes > 0) { + throw TException("TConnection::taskHandler unexpected partial read"); + } + if (errno != EWOULDBLOCK && errno != EAGAIN) { + GlobalOutput.perror("TConnection::taskHandler read failed, resource leak", errno); + } + } + + /** + * Notification to server that processing has ended on this request. + * Can be called either when processing is completed or when a waiting + * task has been preemptively terminated (on overload). + * + * @return true if successful, false if unable to notify (check errno). + */ + bool notifyServer() { + TConnection* connection = this; + if (send(server_->getNotificationSendFD(), const_cast_sockopt(&connection), + sizeof(TConnection*), 0) != sizeof(TConnection*)) { + return false; + } + + return true; + } + + /// Force connection shutdown for this connection. + void forceClose() { + appState_ = APP_CLOSE_CONNECTION; + if (!notifyServer()) { + throw TException("TConnection::forceClose: failed write on notify pipe"); + } + } + + /// return the server this connection was initialized for. + TNonblockingServer* getServer() { + return server_; + } + + /// get state of connection. + TAppState getState() { + return appState_; + } + + /// return the TSocket transport wrapping this network connection + boost::shared_ptr getTSocket() const { + return tSocket_; + } + + /// return the server event handler if any + boost::shared_ptr getServerEventHandler() { + return serverEventHandler_; + } + + /// return the Thrift connection context if any + void* getConnectionContext() { + return connectionContext_; + } +}; + +class TNonblockingServer::TConnection::Task: public Runnable { + public: + Task(boost::shared_ptr processor, + boost::shared_ptr input, + boost::shared_ptr output, + TConnection* connection) : + processor_(processor), + input_(input), + output_(output), + connection_(connection), + serverEventHandler_(connection_->getServerEventHandler()), + connectionContext_(connection_->getConnectionContext()) {} + + void run() { + try { + for (;;) { + if (serverEventHandler_ != NULL) { + serverEventHandler_->processContext(connectionContext_, connection_->getTSocket()); + } + if (!processor_->process(input_, output_, connectionContext_) || + !input_->getTransport()->peek()) { + break; + } + } + } catch (const TTransportException& ttx) { + GlobalOutput.printf("TNonblockingServer client died: %s", ttx.what()); + } catch (const bad_alloc&) { + GlobalOutput("TNonblockingServer caught bad_alloc exception."); + exit(-1); + } catch (const std::exception& x) { + GlobalOutput.printf("TNonblockingServer process() exception: %s: %s", + typeid(x).name(), x.what()); + } catch (...) { + GlobalOutput("TNonblockingServer uncaught exception."); + } + + // Signal completion back to the libevent thread via a pipe + if (!connection_->notifyServer()) { + throw TException("TNonblockingServer::Task::run: failed write on notify pipe"); + } + } + + TConnection* getTConnection() { + return connection_; + } + + private: + boost::shared_ptr processor_; + boost::shared_ptr input_; + boost::shared_ptr output_; + TConnection* connection_; + boost::shared_ptr serverEventHandler_; + void* connectionContext_; +}; + +void TNonblockingServer::TConnection::init(int socket, short eventFlags, + TNonblockingServer* s, + const sockaddr* addr, + socklen_t addrLen) { + tSocket_->setSocketFD(socket); + tSocket_->setCachedAddress(addr, addrLen); + + server_ = s; + appState_ = APP_INIT; + eventFlags_ = 0; + + readBufferPos_ = 0; + readWant_ = 0; + + writeBuffer_ = NULL; + writeBufferSize_ = 0; + writeBufferPos_ = 0; + largestWriteBufferSize_ = 0; + + socketState_ = SOCKET_RECV_FRAMING; + appState_ = APP_INIT; + callsForResize_ = 0; + + // Set flags, which also registers the event + setFlags(eventFlags); + + // get input/transports + factoryInputTransport_ = s->getInputTransportFactory()->getTransport(inputTransport_); + factoryOutputTransport_ = s->getOutputTransportFactory()->getTransport(outputTransport_); + + // Create protocol + inputProtocol_ = s->getInputProtocolFactory()->getProtocol(factoryInputTransport_); + outputProtocol_ = s->getOutputProtocolFactory()->getProtocol(factoryOutputTransport_); + + // Set up for any server event handler + serverEventHandler_ = server_->getEventHandler(); + if (serverEventHandler_ != NULL) { + connectionContext_ = serverEventHandler_->createContext(inputProtocol_, outputProtocol_); + } else { + connectionContext_ = NULL; + } + + // Get the processor + processor_ = s->getProcessor(inputProtocol_, outputProtocol_, tSocket_); +} + +void TNonblockingServer::TConnection::workSocket() { + int got=0, left=0, sent=0; + uint32_t fetch = 0; + + switch (socketState_) { + case SOCKET_RECV_FRAMING: + union { + uint8_t buf[sizeof(uint32_t)]; + int32_t size; + } framing; + + // if we've already received some bytes we kept them here + framing.size = readWant_; + // determine size of this frame + try { + // Read from the socket + fetch = tSocket_->read(&framing.buf[readBufferPos_], + uint32_t(sizeof(framing.size) - readBufferPos_)); + if (fetch == 0) { + // Whenever we get here it means a remote disconnect + close(); + return; + } + readBufferPos_ += fetch; + } catch (TTransportException& te) { + GlobalOutput.printf("TConnection::workSocket(): %s", te.what()); + close(); + + return; + } + + if (readBufferPos_ < sizeof(framing.size)) { + // more needed before frame size is known -- save what we have so far + readWant_ = framing.size; + return; + } + + readWant_ = ntohl(framing.size); + if (static_cast(readWant_) <= 0) { + GlobalOutput.printf("TConnection:workSocket() Negative frame size %d, remote side not using TFramedTransport?", static_cast(readWant_)); + close(); + return; + } + // size known; now get the rest of the frame + transition(); + return; + + case SOCKET_RECV: + // It is an error to be in this state if we already have all the data + assert(readBufferPos_ < readWant_); + + try { + // Read from the socket + fetch = readWant_ - readBufferPos_; + got = tSocket_->read(readBuffer_ + readBufferPos_, fetch); + } + catch (TTransportException& te) { + GlobalOutput.printf("TConnection::workSocket(): %s", te.what()); + close(); + + return; + } + + if (got > 0) { + // Move along in the buffer + readBufferPos_ += got; + + // Check that we did not overdo it + assert(readBufferPos_ <= readWant_); + + // We are done reading, move onto the next state + if (readBufferPos_ == readWant_) { + transition(); + } + return; + } + + // Whenever we get down here it means a remote disconnect + close(); + + return; + + case SOCKET_SEND: + // Should never have position past size + assert(writeBufferPos_ <= writeBufferSize_); + + // If there is no data to send, then let us move on + if (writeBufferPos_ == writeBufferSize_) { + GlobalOutput("WARNING: Send state with no data to send\n"); + transition(); + return; + } + + try { + left = writeBufferSize_ - writeBufferPos_; + sent = tSocket_->write_partial(writeBuffer_ + writeBufferPos_, left); + } + catch (TTransportException& te) { + GlobalOutput.printf("TConnection::workSocket(): %s ", te.what()); + close(); + return; + } + + writeBufferPos_ += sent; + + // Did we overdo it? + assert(writeBufferPos_ <= writeBufferSize_); + + // We are done! + if (writeBufferPos_ == writeBufferSize_) { + transition(); + } + + return; + + default: + GlobalOutput.printf("Unexpected Socket State %d", socketState_); + assert(0); + } +} + +/** + * This is called when the application transitions from one state into + * another. This means that it has finished writing the data that it needed + * to, or finished receiving the data that it needed to. + */ +void TNonblockingServer::TConnection::transition() { + + // Switch upon the state that we are currently in and move to a new state + switch (appState_) { + + case APP_READ_REQUEST: + // We are done reading the request, package the read buffer into transport + // and get back some data from the dispatch function + inputTransport_->resetBuffer(readBuffer_, readBufferPos_); + outputTransport_->resetBuffer(); + // Prepend four bytes of blank space to the buffer so we can + // write the frame size there later. + outputTransport_->getWritePtr(4); + outputTransport_->wroteBytes(4); + + server_->incrementActiveProcessors(); + server_->incrementSgagentHandlers(sgagentIndex_); + + if (server_->isThreadPoolProcessing()) { + // We are setting up a Task to do this work and we will wait on it + + // Create task and dispatch to the thread manager + boost::shared_ptr task = + boost::shared_ptr(new Task(processor_, + inputProtocol_, + outputProtocol_, + this)); + // The application is now waiting on the task to finish + appState_ = APP_WAIT_TASK; + + try { + server_->addTask(task); + } catch (IllegalStateException & ise) { + // The ThreadManager is not ready to handle any more tasks (it's probably shutting down). + GlobalOutput.printf("IllegalStateException: Server::process() %s", ise.what()); + close(); + } + + // Set this connection idle so that libevent doesn't process more + // data on it while we're still waiting for the threadmanager to + // finish this task + setIdle(); + return; + } else { + try { + // Invoke the processor + processor_->process(inputProtocol_, outputProtocol_, + connectionContext_); + } catch (const TTransportException &ttx) { + GlobalOutput.printf("TNonblockingServer transport error in " + "process(): %s", ttx.what()); + server_->decrementActiveProcessors(); + server_->decrementSgagentHandlers(sgagentIndex_); + + close(); + return; + } catch (const std::exception &x) { + GlobalOutput.printf("Server::process() uncaught exception: %s: %s", + typeid(x).name(), x.what()); + server_->decrementActiveProcessors(); + server_->decrementSgagentHandlers(sgagentIndex_); + close(); + return; + } catch (...) { + GlobalOutput.printf("Server::process() unknown exception"); + server_->decrementActiveProcessors(); + server_->decrementSgagentHandlers(sgagentIndex_); + close(); + return; + } + } + + // Intentionally fall through here, the call to process has written into + // the writeBuffer_ + + case APP_WAIT_TASK: + // We have now finished processing a task and the result has been written + // into the outputTransport_, so we grab its contents and place them into + // the writeBuffer_ for actual writing by the libevent thread + + server_->decrementActiveProcessors(); + server_->decrementSgagentHandlers(sgagentIndex_); + // Get the result of the operation + outputTransport_->getBuffer(&writeBuffer_, &writeBufferSize_); + + // If the function call generated return data, then move into the send + // state and get going + // 4 bytes were reserved for frame size + if (writeBufferSize_ > 4) { + + // Move into write state + writeBufferPos_ = 0; + socketState_ = SOCKET_SEND; + + // Put the frame size into the write buffer + int32_t frameSize = (int32_t)htonl(writeBufferSize_ - 4); + memcpy(writeBuffer_, &frameSize, 4); + + // Socket into write mode + appState_ = APP_SEND_RESULT; + setWrite(); + + // Try to work the socket immediately + // workSocket(); + + return; + } + + // In this case, the request was oneway and we should fall through + // right back into the read frame header state + goto LABEL_APP_INIT; + + case APP_SEND_RESULT: + // it's now safe to perform buffer size housekeeping. + if (writeBufferSize_ > largestWriteBufferSize_) { + largestWriteBufferSize_ = writeBufferSize_; + } + if (server_->getResizeBufferEveryN() > 0 + && ++callsForResize_ >= server_->getResizeBufferEveryN()) { + checkIdleBufferMemLimit(server_->getIdleReadBufferLimit(), + server_->getIdleWriteBufferLimit()); + callsForResize_ = 0; + } + + // N.B.: We also intentionally fall through here into the INIT state! + + LABEL_APP_INIT: + case APP_INIT: + + // Clear write buffer variables + writeBuffer_ = NULL; + writeBufferPos_ = 0; + writeBufferSize_ = 0; + + // Into read4 state we go + socketState_ = SOCKET_RECV_FRAMING; + appState_ = APP_READ_FRAME_SIZE; + + readBufferPos_ = 0; + + // Register read event + setRead(); + + // Try to work the socket right away + // workSocket(); + + return; + + case APP_READ_FRAME_SIZE: + // We just read the request length + // Double the buffer size until it is big enough + if (readWant_ > readBufferSize_) { + if (readBufferSize_ == 0) { + readBufferSize_ = 1; + } + uint32_t newSize = readBufferSize_; + while (readWant_ > newSize) { + newSize *= 2; + } + + uint8_t* newBuffer = (uint8_t*)std::realloc(readBuffer_, newSize); + if (newBuffer == NULL) { + // nothing else to be done... + throw std::bad_alloc(); + } + readBuffer_ = newBuffer; + readBufferSize_ = newSize; + } + + readBufferPos_= 0; + + // Move into read request state + socketState_ = SOCKET_RECV; + appState_ = APP_READ_REQUEST; + + // Work the socket right away + // workSocket(); + + return; + + case APP_CLOSE_CONNECTION: + server_->decrementActiveProcessors(); + server_->decrementSgagentHandlers(sgagentIndex_); + close(); + return; + + default: + GlobalOutput.printf("Unexpected Application State %d", appState_); + assert(0); + } +} + +void TNonblockingServer::TConnection::setFlags(short eventFlags) { + // Catch the do nothing case + if (eventFlags_ == eventFlags) { + return; + } + + // Delete a previously existing event + if (eventFlags_ != 0) { + if (event_del(&event_) == -1) { + GlobalOutput("TConnection::setFlags event_del"); + return; + } + } + + // Update in memory structure + eventFlags_ = eventFlags; + + // Do not call event_set if there are no flags + if (!eventFlags_) { + return; + } + + /* + * event_set: + * + * Prepares the event structure &event to be used in future calls to + * event_add() and event_del(). The event will be prepared to call the + * eventHandler using the 'sock' file descriptor to monitor events. + * + * The events can be either EV_READ, EV_WRITE, or both, indicating + * that an application can read or write from the file respectively without + * blocking. + * + * The eventHandler will be called with the file descriptor that triggered + * the event and the type of event which will be one of: EV_TIMEOUT, + * EV_SIGNAL, EV_READ, EV_WRITE. + * + * The additional flag EV_PERSIST makes an event_add() persistent until + * event_del() has been called. + * + * Once initialized, the &event struct can be used repeatedly with + * event_add() and event_del() and does not need to be reinitialized unless + * the eventHandler and/or the argument to it are to be changed. However, + * when an ev structure has been added to libevent using event_add() the + * structure must persist until the event occurs (assuming EV_PERSIST + * is not set) or is removed using event_del(). You may not reuse the same + * ev structure for multiple monitored descriptors; each descriptor needs + * its own ev. + */ + event_set(&event_, tSocket_->getSocketFD(), eventFlags_, + TConnection::eventHandler, this); + event_base_set(server_->getEventBase(), &event_); + + // Add the event + if (event_add(&event_, 0) == -1) { + GlobalOutput("TConnection::setFlags(): could not event_add"); + } +} + +/** + * Closes a connection + */ +void TNonblockingServer::TConnection::close() { + // Delete the registered libevent + if (event_del(&event_) == -1) { + GlobalOutput.perror("TConnection::close() event_del", errno); + } + + if (serverEventHandler_ != NULL) { + serverEventHandler_->deleteContext(connectionContext_, inputProtocol_, outputProtocol_); + } + + // Close the socket + tSocket_->close(); + + // close any factory produced transports + factoryInputTransport_->close(); + factoryOutputTransport_->close(); + + // Give this object back to the server that owns it + server_->returnConnection(this); +} + +void TNonblockingServer::TConnection::checkIdleBufferMemLimit( + size_t readLimit, + size_t writeLimit) { + if (readLimit > 0 && readBufferSize_ > readLimit) { + free(readBuffer_); + readBuffer_ = NULL; + readBufferSize_ = 0; + } + + if (writeLimit > 0 && largestWriteBufferSize_ > writeLimit) { + // just start over + outputTransport_->resetBuffer(server_->getWriteBufferDefaultSize()); + largestWriteBufferSize_ = 0; + } +} + +TNonblockingServer::~TNonblockingServer() { + // TODO: We currently leak any active TConnection objects. + // Since we're shutting down and destroying the event_base, the TConnection + // objects will never receive any additional callbacks. (And even if they + // did, it would be bad, since they keep a pointer around to the server, + // which is being destroyed.) + + // Clean up unused TConnection objects in connectionStack_ + while (!connectionStack_.empty()) { + TConnection* connection = connectionStack_.top(); + connectionStack_.pop(); + delete connection; + } + + if (eventBase_ && ownEventBase_) { + event_base_free(eventBase_); + } + + if (serverSocket_ >= 0) { + close(serverSocket_); + } +} + +/** + * Creates a new connection either by reusing an object off the stack or + * by allocating a new one entirely + */ +TNonblockingServer::TConnection* TNonblockingServer::createConnection( + int socket, short flags, + const sockaddr* addr, + socklen_t addrLen) { + // Check the stack + if (connectionStack_.empty()) { + return new TConnection(socket, flags, this, addr, addrLen, curSgagentIndex_); + } else { + TConnection* result = connectionStack_.top(); + connectionStack_.pop(); + result->init(socket, flags, this, addr, addrLen); + return result; + } +} + +/** + * Returns a connection to the stack + */ +void TNonblockingServer::returnConnection(TConnection* connection) { + if (connectionStackLimit_ && + (connectionStack_.size() >= connectionStackLimit_)) { + delete connection; + } else { + connection->checkIdleBufferMemLimit(idleReadBufferLimit_, idleWriteBufferLimit_); + connectionStack_.push(connection); + } +} + +/** + * Server socket had something happen. We accept all waiting client + * connections on fd and assign TConnection objects to handle those requests. + */ +void TNonblockingServer::handleEvent(int fd, short which) { + (void) which; + // Make sure that libevent didn't mess up the socket handles + assert(fd == serverSocket_); + + // Server socket accepted a new connection + socklen_t addrLen; + sockaddr_storage addrStorage; + sockaddr* addrp = (sockaddr*)&addrStorage; + addrLen = sizeof(addrStorage); + + // Going to accept a new client socket + int clientSocket; + + // Accept as many new clients as possible, even though libevent signaled only + // one, this helps us to avoid having to go back into the libevent engine so + // many times + while ((clientSocket = ::accept(fd, addrp, &addrLen)) != -1) { + // If we're overloaded, take action here + if (overloadAction_ != T_OVERLOAD_NO_ACTION && serverOverloaded()) { + nConnectionsDropped_++; + nTotalConnectionsDropped_++; + if (overloadAction_ == T_OVERLOAD_CLOSE_ON_ACCEPT) { + close(clientSocket); + return; + } else if (overloadAction_ == T_OVERLOAD_DRAIN_TASK_QUEUE) { + if (!drainPendingTask()) { + // Nothing left to discard, so we drop connection instead. + close(clientSocket); + return; + } + } + } + // Explicitly set this socket to NONBLOCK mode + int flags; + if ((flags = fcntl(clientSocket, F_GETFL, 0)) < 0 || + fcntl(clientSocket, F_SETFL, flags | O_NONBLOCK) < 0) { + GlobalOutput.perror("thriftServerEventHandler: set O_NONBLOCK (fcntl) ", errno); + close(clientSocket); + return; + } + + // Create a new TConnection for this client socket. + TConnection* clientConnection = + createConnection(clientSocket, EV_READ | EV_PERSIST, addrp, addrLen); + + // Fail fast if we could not create a TConnection object + if (clientConnection == NULL) { + GlobalOutput.printf("thriftServerEventHandler: failed TConnection factory"); + close(clientSocket); + return; + } + + // Put this client connection into the proper state + clientConnection->transition(); + + // addrLen is written by the accept() call, so needs to be set before the next call. + addrLen = sizeof(addrStorage); + } + + // Done looping accept, now we have to make sure the error is due to + // blocking. Any other error is a problem + if (errno != EAGAIN && errno != EWOULDBLOCK) { + GlobalOutput.perror("thriftServerEventHandler: accept() ", errno); + } +} + +/** + * Creates a socket to listen on and binds it to the local port. + */ +void TNonblockingServer::listenSocket() { + int s; + struct addrinfo hints, *res, *res0; + int error; + + char port[sizeof("65536") + 1]; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + sprintf(port, "%d", port_); + + // Wildcard address + error = getaddrinfo(NULL, port, &hints, &res0); + if (error) { + string errStr = "TNonblockingServer::serve() getaddrinfo " + string(gai_strerror(error)); + GlobalOutput(errStr.c_str()); + return; + } + + // Pick the ipv6 address first since ipv4 addresses can be mapped + // into ipv6 space. + for (res = res0; res; res = res->ai_next) { + if (res->ai_family == AF_INET6 || res->ai_next == NULL) + break; + } + + // Create the server socket + s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (s == -1) { + freeaddrinfo(res0); + throw TException("TNonblockingServer::serve() socket() -1"); + } + + #ifdef IPV6_V6ONLY + if (res->ai_family == AF_INET6) { + int zero = 0; + if (-1 == setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, const_cast_sockopt(&zero), sizeof(zero))) { + GlobalOutput("TServerSocket::listen() IPV6_V6ONLY"); + } + } + #endif // #ifdef IPV6_V6ONLY + + + int one = 1; + + // Set reuseaddr to avoid 2MSL delay on server restart + setsockopt(s, SOL_SOCKET, SO_REUSEADDR, const_cast_sockopt(&one), sizeof(one)); + + if (::bind(s, res->ai_addr, res->ai_addrlen) == -1) { + close(s); + freeaddrinfo(res0); + throw TException("TNonblockingServer::serve() bind"); + } + + // Done with the addr info + freeaddrinfo(res0); + + // Set up this file descriptor for listening + listenSocket(s); +} + +/** + * Takes a socket created by listenSocket() and sets various options on it + * to prepare for use in the server. + */ +void TNonblockingServer::listenSocket(int s) { + // Set socket to nonblocking mode + int flags; + if ((flags = fcntl(s, F_GETFL, 0)) < 0 || + fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) { + close(s); + throw TException("TNonblockingServer::serve() O_NONBLOCK"); + } + + int one = 1; + struct linger ling = {0, 0}; + + // Keepalive to ensure full result flushing + setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, const_cast_sockopt(&one), sizeof(one)); + + // Turn linger off to avoid hung sockets + setsockopt(s, SOL_SOCKET, SO_LINGER, const_cast_sockopt(&ling), sizeof(ling)); + + // Set TCP nodelay if available, MAC OS X Hack + // See http://lists.danga.com/pipermail/memcached/2005-March/001240.html + #ifndef TCP_NOPUSH + setsockopt(s, IPPROTO_TCP, TCP_NODELAY, const_cast_sockopt(&one), sizeof(one)); + #endif + + #ifdef TCP_LOW_MIN_RTO + if (TSocket::getUseLowMinRto()) { + setsockopt(s, IPPROTO_TCP, TCP_LOW_MIN_RTO, const_cast_sockopt(&one), sizeof(one)); + } + #endif + + if (listen(s, LISTEN_BACKLOG) == -1) { + close(s); + throw TException("TNonblockingServer::serve() listen"); + } + + // Cool, this socket is good to go, set it as the serverSocket_ + serverSocket_ = s; +} + +void TNonblockingServer::createNotificationPipe() { + if(evutil_socketpair(AF_LOCAL, SOCK_STREAM, 0, notificationPipeFDs_) == -1) { + GlobalOutput.perror("TNonblockingServer::createNotificationPipe ", EVUTIL_SOCKET_ERROR()); + throw TException("can't create notification pipe"); + } + if(evutil_make_socket_nonblocking(notificationPipeFDs_[0])<0 || + evutil_make_socket_nonblocking(notificationPipeFDs_[1])<0) { + close(notificationPipeFDs_[0]); + close(notificationPipeFDs_[1]); + throw TException("TNonblockingServer::createNotificationPipe() O_NONBLOCK"); + } +} + +/** + * Register the core libevent events onto the proper base. + */ +void TNonblockingServer::registerEvents(event_base* base, bool ownEventBase) { + assert(serverSocket_ != -1); + assert(!eventBase_); + eventBase_ = base; + ownEventBase_ = ownEventBase; + + // Print some libevent stats + GlobalOutput.printf("libevent %s method %s", + event_get_version(), + event_base_get_method(eventBase_)); + + // Register the server event + event_set(&serverEvent_, + serverSocket_, + EV_READ | EV_PERSIST, + TNonblockingServer::eventHandler, + this); + event_base_set(eventBase_, &serverEvent_); + + // Add the event and start up the server + if (-1 == event_add(&serverEvent_, 0)) { + throw TException("TNonblockingServer::serve(): coult not event_add"); + } + if (threadPoolProcessing_) { + // Create an event to be notified when a task finishes + event_set(¬ificationEvent_, + getNotificationRecvFD(), + EV_READ | EV_PERSIST, + TConnection::taskHandler, + this); + + // Attach to the base + event_base_set(eventBase_, ¬ificationEvent_); + + // Add the event and start up the server + if (-1 == event_add(¬ificationEvent_, 0)) { + throw TException("TNonblockingServer::serve(): notification event_add fail"); + } + } +} + +void TNonblockingServer::setThreadManager(boost::shared_ptr threadManager) { + threadManager_ = threadManager; + if (threadManager != NULL) { + threadManager->setExpireCallback(std::tr1::bind(&TNonblockingServer::expireClose, this, std::tr1::placeholders::_1)); + threadPoolProcessing_ = true; + } else { + threadPoolProcessing_ = false; + } +} + +bool TNonblockingServer::serverOverloaded() { + size_t activeConnections = numTConnections_ - connectionStack_.size(); + if (numActiveProcessors_ > maxActiveProcessors_ || + activeConnections > maxConnections_) { + if (!overloaded_) { + GlobalOutput.printf("thrift non-blocking server overload condition"); + overloaded_ = true; + } + } else { + if (overloaded_ && + (numActiveProcessors_ <= overloadHysteresis_ * maxActiveProcessors_) && + (activeConnections <= overloadHysteresis_ * maxConnections_)) { + GlobalOutput.printf("thrift non-blocking server overload ended; %u dropped (%llu total)", + nConnectionsDropped_, nTotalConnectionsDropped_); + nConnectionsDropped_ = 0; + overloaded_ = false; + } + } + + return overloaded_; +} + +bool TNonblockingServer::drainPendingTask() { + if (threadManager_) { + boost::shared_ptr task = threadManager_->removeNextPending(); + if (task) { + TConnection* connection = + static_cast(task.get())->getTConnection(); + assert(connection && connection->getServer() + && connection->getState() == APP_WAIT_TASK); + connection->forceClose(); + return true; + } + } + return false; +} + +void TNonblockingServer::expireClose(boost::shared_ptr task) { + TConnection* connection = + static_cast(task.get())->getTConnection(); + assert(connection && connection->getServer() + && connection->getState() == APP_WAIT_TASK); + connection->forceClose(); +} + +/** + * Main workhorse function, starts up the server listening on a port and + * loops over the libevent handler. + */ +void TNonblockingServer::serve() { + // Init socket + listenSocket(); + + if (threadPoolProcessing_) { + // Init task completion notification pipe + createNotificationPipe(); + } + + // Initialize libevent core + registerEvents(static_cast(event_base_new()), true); + + // Run the preServe event + if (eventHandler_ != NULL) { + eventHandler_->preServe(); + } + + // Run libevent engine, invokes calls to eventHandler + // Only returns if stop() is called. + event_base_loop(eventBase_, 0); +} + +void TNonblockingServer::stop() { + if (!eventBase_) { + return; + } + + // Call event_base_loopbreak() to tell libevent to exit the loop + // + // (The libevent documentation doesn't explicitly state that this function is + // safe to call from another thread. However, all it does is set a variable, + // in the event_base, so it should be fine.) + event_base_loopbreak(eventBase_); + + // event_base_loopbreak() only causes the loop to exit the next time it wakes + // up. We need to force it to wake up, in case there are no real events + // it needs to process. + // + // Attempt to connect to the server socket. If anything fails, + // we'll just have to wait until libevent wakes up on its own. + // + // First create a socket + int fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (fd < 0) { + return; + } + + // Set up the address + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(0x7f000001); // 127.0.0.1 + addr.sin_port = htons(port_); + + // Finally do the connect(). + // We don't care about the return value; + // we're just going to close the socket either way. + connect(fd, reinterpret_cast(&addr), sizeof(addr)); + close(fd); +} + +}}} // apache::thrift::server diff --git a/sg_agent/thrid_party/thrift/include/server/TNonblockingServer.h b/sg_agent/thrid_party/thrift/include/server/TNonblockingServer.h new file mode 100644 index 0000000..cd3fa42 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/server/TNonblockingServer.h @@ -0,0 +1,795 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_SERVER_TNONBLOCKINGSERVER_H_ +#define _THRIFT_SERVER_TNONBLOCKINGSERVER_H_ 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#include + +namespace apache { namespace thrift { namespace server { + +using apache::thrift::transport::TMemoryBuffer; +using apache::thrift::transport::TSocket; +using apache::thrift::protocol::TProtocol; +using apache::thrift::concurrency::Runnable; +using apache::thrift::concurrency::ThreadManager; + +#ifdef LIBEVENT_VERSION_NUMBER +#define LIBEVENT_VERSION_MAJOR (LIBEVENT_VERSION_NUMBER >> 24) +#define LIBEVENT_VERSION_MINOR ((LIBEVENT_VERSION_NUMBER >> 16) & 0xFF) +#define LIBEVENT_VERSION_REL ((LIBEVENT_VERSION_NUMBER >> 8) & 0xFF) +#else +// assume latest version 1 series +#define LIBEVENT_VERSION_MAJOR 1 +#define LIBEVENT_VERSION_MINOR 14 +#define LIBEVENT_VERSION_REL 13 +#define LIBEVENT_VERSION_NUMBER ((LIBEVENT_VERSION_MAJOR << 24) | (LIBEVENT_VERSION_MINOR << 16) | (LIBEVENT_VERSION_REL << 8)) +#endif + +#if LIBEVENT_VERSION_NUMBER < 0x02000000 + typedef int evutil_socket_t; +#endif + +#ifndef SOCKOPT_CAST_T +# ifndef _WIN32 +# define SOCKOPT_CAST_T void +# else +# define SOCKOPT_CAST_T char +# endif // _WIN32 +#endif + +template +inline const SOCKOPT_CAST_T* const_cast_sockopt(const T* v) { + return reinterpret_cast(v); +} + +template +inline SOCKOPT_CAST_T* cast_sockopt(T* v) { + return reinterpret_cast(v); +} + +/** + * This is a non-blocking server in C++ for high performance that operates a + * single IO thread. It assumes that all incoming requests are framed with a + * 4 byte length indicator and writes out responses using the same framing. + * + * It does not use the TServerTransport framework, but rather has socket + * operations hardcoded for use with select. + * + */ + + +/// Overload condition actions. +enum TOverloadAction { + T_OVERLOAD_NO_ACTION, ///< Don't handle overload */ + T_OVERLOAD_CLOSE_ON_ACCEPT, ///< Drop new connections immediately */ + T_OVERLOAD_DRAIN_TASK_QUEUE ///< Drop some tasks from head of task queue */ +}; + +class TNonblockingServer : public TServer { + private: + class TConnection; + + /// Listen backlog + static const int LISTEN_BACKLOG = 1024; + + /// Default limit on size of idle connection pool + static const size_t CONNECTION_STACK_LIMIT = 1024; + + /// Default limit on total number of connected sockets + static const int MAX_CONNECTIONS = INT_MAX; + + /// Default limit on connections in handler/task processing + static const int MAX_ACTIVE_PROCESSORS = INT_MAX; + + /// Default size of write buffer + static const int WRITE_BUFFER_DEFAULT_SIZE = 1024; + + /// Maximum size of read buffer allocated to idle connection (0 = unlimited) + static const int IDLE_READ_BUFFER_LIMIT = 1024; + + /// Maximum size of write buffer allocated to idle connection (0 = unlimited) + static const int IDLE_WRITE_BUFFER_LIMIT = 1024; + + /// # of calls before resizing oversized buffers (0 = check only on close) + static const int RESIZE_BUFFER_EVERY_N = 512; + + /// Server socket file descriptor + int serverSocket_; + + /// Port server runs on + int port_; + + /// For processing via thread pool, may be NULL + boost::shared_ptr threadManager_; + + /// Is thread pool processing? + bool threadPoolProcessing_; + + /// The event base for libevent + event_base* eventBase_; + bool ownEventBase_; + + /// Event struct, used with eventBase_ for connection events + struct event serverEvent_; + + /// Event struct, used with eventBase_ for task completion notification + struct event notificationEvent_; + + /// Number of sgagent connection object we've created + size_t numSgagentHandlers_[2]; + + /// The sgagent is used + int curSgagentIndex_; + + /// Number of TConnection object we've created + size_t numTConnections_; + + /// Number of Connections processing or waiting to process + size_t numActiveProcessors_; + + /// Limit for how many TConnection objects to cache + size_t connectionStackLimit_; + + /// Limit for number of connections processing or waiting to process + size_t maxActiveProcessors_; + + /// Limit for number of open connections + size_t maxConnections_; + + /// Time in milliseconds before an unperformed task expires (0 == infinite). + int64_t taskExpireTime_; + + /** + * Hysteresis for overload state. This is the fraction of the overload + * value that needs to be reached before the overload state is cleared; + * must be <= 1.0. + */ + double overloadHysteresis_; + + /// Action to take when we're overloaded. + TOverloadAction overloadAction_; + + /** + * The write buffer is initialized (and when idleWriteBufferLimit_ is checked + * and found to be exceeded, reinitialized) to this size. + */ + size_t writeBufferDefaultSize_; + + /** + * Max read buffer size for an idle TConnection. When we place an idle + * TConnection into connectionStack_ or on every resizeBufferEveryN_ calls, + * we will free the buffer (such that it will be reinitialized by the next + * received frame) if it has exceeded this limit. 0 disables this check. + */ + size_t idleReadBufferLimit_; + + /** + * Max write buffer size for an idle connection. When we place an idle + * TConnection into connectionStack_ or on every resizeBufferEveryN_ calls, + * we insure that its write buffer is <= to this size; otherwise we + * replace it with a new one of writeBufferDefaultSize_ bytes to insure that + * idle connections don't hog memory. 0 disables this check. + */ + size_t idleWriteBufferLimit_; + + /** + * Every N calls we check the buffer size limits on a connected TConnection. + * 0 disables (i.e. the checks are only done when a connection closes). + */ + int32_t resizeBufferEveryN_; + + /// Set if we are currently in an overloaded state. + bool overloaded_; + + /// Count of connections dropped since overload started + uint32_t nConnectionsDropped_; + + /// Count of connections dropped on overload since server started + uint64_t nTotalConnectionsDropped_; + + /// File descriptors for pipe used for task completion notification. + evutil_socket_t notificationPipeFDs_[2]; + + /** + * This is a stack of all the objects that have been created but that + * are NOT currently in use. When we close a connection, we place it on this + * stack so that the object can be reused later, rather than freeing the + * memory and reallocating a new object later. + */ + std::stack connectionStack_; + + /** + * Called when server socket had something happen. We accept all waiting + * client connections on listen socket fd and assign TConnection objects + * to handle those requests. + * + * @param fd the listen socket. + * @param which the event flag that triggered the handler. + */ + void handleEvent(int fd, short which); + + void init(int port) { + serverSocket_ = -1; + port_ = port; + threadPoolProcessing_ = false; + eventBase_ = NULL; + ownEventBase_ = false; + numSgagentHandlers_[0] = 0; + numSgagentHandlers_[1] = 0; + curSgagentIndex_ = 0; + numTConnections_ = 0; + numActiveProcessors_ = 0; + connectionStackLimit_ = CONNECTION_STACK_LIMIT; + maxActiveProcessors_ = MAX_ACTIVE_PROCESSORS; + maxConnections_ = MAX_CONNECTIONS; + taskExpireTime_ = 0; + overloadHysteresis_ = 0.8; + overloadAction_ = T_OVERLOAD_NO_ACTION; + writeBufferDefaultSize_ = WRITE_BUFFER_DEFAULT_SIZE; + idleReadBufferLimit_ = IDLE_READ_BUFFER_LIMIT; + idleWriteBufferLimit_ = IDLE_WRITE_BUFFER_LIMIT; + resizeBufferEveryN_ = RESIZE_BUFFER_EVERY_N; + overloaded_ = false; + nConnectionsDropped_ = 0; + nTotalConnectionsDropped_ = 0; + } + + public: + template + TNonblockingServer( + const boost::shared_ptr& processorFactory, + int port, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)) : + TServer(processorFactory) { + init(port); + } + + template + TNonblockingServer(const boost::shared_ptr& processor, + int port, + THRIFT_OVERLOAD_IF(Processor, TProcessor)) : + TServer(processor) { + init(port); + } + + template + TNonblockingServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& protocolFactory, + int port, + const boost::shared_ptr& threadManager = + boost::shared_ptr(), + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)) : + TServer(processorFactory) { + + init(port); + + setInputProtocolFactory(protocolFactory); + setOutputProtocolFactory(protocolFactory); + setThreadManager(threadManager); + } + + template + TNonblockingServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& protocolFactory, + int port, + const boost::shared_ptr& threadManager = + boost::shared_ptr(), + THRIFT_OVERLOAD_IF(Processor, TProcessor)) : + TServer(processor) { + + init(port); + + setInputProtocolFactory(protocolFactory); + setOutputProtocolFactory(protocolFactory); + setThreadManager(threadManager); + } + + template + TNonblockingServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& inputTransportFactory, + const boost::shared_ptr& outputTransportFactory, + const boost::shared_ptr& inputProtocolFactory, + const boost::shared_ptr& outputProtocolFactory, + int port, + const boost::shared_ptr& threadManager = + boost::shared_ptr(), + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)) : + TServer(processorFactory) { + + init(port); + + setInputTransportFactory(inputTransportFactory); + setOutputTransportFactory(outputTransportFactory); + setInputProtocolFactory(inputProtocolFactory); + setOutputProtocolFactory(outputProtocolFactory); + setThreadManager(threadManager); + } + + template + TNonblockingServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& inputTransportFactory, + const boost::shared_ptr& outputTransportFactory, + const boost::shared_ptr& inputProtocolFactory, + const boost::shared_ptr& outputProtocolFactory, + int port, + const boost::shared_ptr& threadManager = + boost::shared_ptr(), + THRIFT_OVERLOAD_IF(Processor, TProcessor)) : + TServer(processor) { + + init(port); + + setInputTransportFactory(inputTransportFactory); + setOutputTransportFactory(outputTransportFactory); + setInputProtocolFactory(inputProtocolFactory); + setOutputProtocolFactory(outputProtocolFactory); + setThreadManager(threadManager); + } + + ~TNonblockingServer(); + + void setThreadManager(boost::shared_ptr threadManager); + + boost::shared_ptr getThreadManager() { + return threadManager_; + } + + /** + * Get the maximum number of unused TConnection we will hold in reserve. + * + * @return the current limit on TConnection pool size. + */ + size_t getConnectionStackLimit() const { + return connectionStackLimit_; + } + + /** + * Set the maximum number of unused TConnection we will hold in reserve. + * + * @param sz the new limit for TConnection pool size. + */ + void setConnectionStackLimit(size_t sz) { + connectionStackLimit_ = sz; + } + + bool isThreadPoolProcessing() const { + return threadPoolProcessing_; + } + + void addTask(boost::shared_ptr task) { + threadManager_->add(task, 0LL, taskExpireTime_); + } + + event_base* getEventBase() const { + return eventBase_; + } + + void switchSgagentIndex() { + if (!curSgagentIndex_) { + curSgagentIndex_ = 1; + } else { + curSgagentIndex_ = 0; + } + } + + size_t getOldSgagentHandlers() { + if (!curSgagentIndex_) { + return numSgagentHandlers_[1]; + } else { + return numSgagentHandlers_[0]; + } + } + + void incrementSgagentHandlers(int sgagentIndex) { + ++numSgagentHandlers_[sgagentIndex]; + } + + void decrementSgagentHandlers(int sgagentIndex) { + --numSgagentHandlers_[sgagentIndex]; + } + + /// Increment our count of the number of connected sockets. + void incrementNumConnections() { + ++numTConnections_; + } + + /// Decrement our count of the number of connected sockets. + void decrementNumConnections() { + --numTConnections_; + } + + /** + * Return the count of sockets currently connected to. + * + * @return count of connected sockets. + */ + size_t getNumConnections() const { + return numTConnections_; + } + + /** + * Return the count of connection objects allocated but not in use. + * + * @return count of idle connection objects. + */ + size_t getNumIdleConnections() const { + return connectionStack_.size(); + } + + /** + * Return count of number of connections which are currently processing. + * This is defined as a connection where all data has been received and + * either assigned a task (when threading) or passed to a handler (when + * not threading), and where the handler has not yet returned. + * + * @return # of connections currently processing. + */ + size_t getNumActiveProcessors() const { + return numActiveProcessors_; + } + + /// Increment the count of connections currently processing. + void incrementActiveProcessors() { + ++numActiveProcessors_; + } + + /// Decrement the count of connections currently processing. + void decrementActiveProcessors() { + if (numActiveProcessors_ > 0) { + --numActiveProcessors_; + } + } + + /** + * Get the maximum # of connections allowed before overload. + * + * @return current setting. + */ + size_t getMaxConnections() const { + return maxConnections_; + } + + /** + * Set the maximum # of connections allowed before overload. + * + * @param maxConnections new setting for maximum # of connections. + */ + void setMaxConnections(size_t maxConnections) { + maxConnections_ = maxConnections; + } + + /** + * Get the maximum # of connections waiting in handler/task before overload. + * + * @return current setting. + */ + size_t getMaxActiveProcessors() const { + return maxActiveProcessors_; + } + + /** + * Set the maximum # of connections waiting in handler/task before overload. + * + * @param maxActiveProcessors new setting for maximum # of active processes. + */ + void setMaxActiveProcessors(size_t maxActiveProcessors) { + maxActiveProcessors_ = maxActiveProcessors; + } + + /** + * Get fraction of maximum limits before an overload condition is cleared. + * + * @return hysteresis fraction + */ + double getOverloadHysteresis() const { + return overloadHysteresis_; + } + + /** + * Set fraction of maximum limits before an overload condition is cleared. + * A good value would probably be between 0.5 and 0.9. + * + * @param hysteresisFraction fraction <= 1.0. + */ + void setOverloadHysteresis(double hysteresisFraction) { + if (hysteresisFraction <= 1.0 && hysteresisFraction > 0.0) { + overloadHysteresis_ = hysteresisFraction; + } + } + + /** + * Get the action the server will take on overload. + * + * @return a TOverloadAction enum value for the currently set action. + */ + TOverloadAction getOverloadAction() const { + return overloadAction_; + } + + /** + * Set the action the server is to take on overload. + * + * @param overloadAction a TOverloadAction enum value for the action. + */ + void setOverloadAction(TOverloadAction overloadAction) { + overloadAction_ = overloadAction; + } + + /** + * Get the time in milliseconds after which a task expires (0 == infinite). + * + * @return a 64-bit time in milliseconds. + */ + int64_t getTaskExpireTime() const { + return taskExpireTime_; + } + + /** + * Set the time in milliseconds after which a task expires (0 == infinite). + * + * @param taskExpireTime a 64-bit time in milliseconds. + */ + void setTaskExpireTime(int64_t taskExpireTime) { + taskExpireTime_ = taskExpireTime; + } + + /** + * Determine if the server is currently overloaded. + * This function checks the maximums for open connections and connections + * currently in processing, and sets an overload condition if they are + * exceeded. The overload will persist until both values are below the + * current hysteresis fraction of their maximums. + * + * @return true if an overload condition exists, false if not. + */ + bool serverOverloaded(); + + /** Pop and discard next task on threadpool wait queue. + * + * @return true if a task was discarded, false if the wait queue was empty. + */ + bool drainPendingTask(); + + /** + * Get the starting size of a TConnection object's write buffer. + * + * @return # bytes we initialize a TConnection object's write buffer to. + */ + size_t getWriteBufferDefaultSize() const { + return writeBufferDefaultSize_; + } + + /** + * Set the starting size of a TConnection object's write buffer. + * + * @param size # bytes we initialize a TConnection object's write buffer to. + */ + void setWriteBufferDefaultSize(size_t size) { + writeBufferDefaultSize_ = size; + } + + /** + * Get the maximum size of read buffer allocated to idle TConnection objects. + * + * @return # bytes beyond which we will dealloc idle buffer. + */ + size_t getIdleReadBufferLimit() const { + return idleReadBufferLimit_; + } + + /** + * [NOTE: This is for backwards compatibility, use getIdleReadBufferLimit().] + * Get the maximum size of read buffer allocated to idle TConnection objects. + * + * @return # bytes beyond which we will dealloc idle buffer. + */ + size_t getIdleBufferMemLimit() const { + return idleReadBufferLimit_; + } + + /** + * Set the maximum size read buffer allocated to idle TConnection objects. + * If a TConnection object is found (either on connection close or between + * calls when resizeBufferEveryN_ is set) with more than this much memory + * allocated to its read buffer, we free it and allow it to be reinitialized + * on the next received frame. + * + * @param limit of bytes beyond which we will shrink buffers when checked. + */ + void setIdleReadBufferLimit(size_t limit) { + idleReadBufferLimit_ = limit; + } + + /** + * [NOTE: This is for backwards compatibility, use setIdleReadBufferLimit().] + * Set the maximum size read buffer allocated to idle TConnection objects. + * If a TConnection object is found (either on connection close or between + * calls when resizeBufferEveryN_ is set) with more than this much memory + * allocated to its read buffer, we free it and allow it to be reinitialized + * on the next received frame. + * + * @param limit of bytes beyond which we will shrink buffers when checked. + */ + void setIdleBufferMemLimit(size_t limit) { + idleReadBufferLimit_ = limit; + } + + + + /** + * Get the maximum size of write buffer allocated to idle TConnection objects. + * + * @return # bytes beyond which we will reallocate buffers when checked. + */ + size_t getIdleWriteBufferLimit() const { + return idleWriteBufferLimit_; + } + + /** + * Set the maximum size write buffer allocated to idle TConnection objects. + * If a TConnection object is found (either on connection close or between + * calls when resizeBufferEveryN_ is set) with more than this much memory + * allocated to its write buffer, we destroy and construct that buffer with + * writeBufferDefaultSize_ bytes. + * + * @param limit of bytes beyond which we will shrink buffers when idle. + */ + void setIdleWriteBufferLimit(size_t limit) { + idleWriteBufferLimit_ = limit; + } + + /** + * Get # of calls made between buffer size checks. 0 means disabled. + * + * @return # of calls between buffer size checks. + */ + int32_t getResizeBufferEveryN() const { + return resizeBufferEveryN_; + } + + /** + * Check buffer sizes every "count" calls. This allows buffer limits + * to be enforced for persistant connections with a controllable degree + * of overhead. 0 disables checks except at connection close. + * + * @param count the number of calls between checks, or 0 to disable + */ + void setResizeBufferEveryN(int32_t count) { + resizeBufferEveryN_ = count; + } + + + + /** + * Return an initialized connection object. Creates or recovers from + * pool a TConnection and initializes it with the provided socket FD + * and flags. + * + * @param socket FD of socket associated with this connection. + * @param flags initial lib_event flags for this connection. + * @param addr the sockaddr of the client + * @param addrLen the length of addr + * @return pointer to initialized TConnection object. + */ + TConnection* createConnection(int socket, short flags, + const sockaddr* addr, socklen_t addrLen); + + /** + * Returns a connection to pool or deletion. If the connection pool + * (a stack) isn't full, place the connection object on it, otherwise + * just delete it. + * + * @param connection the TConection being returned. + */ + void returnConnection(TConnection* connection); + + /** + * Callback function that the threadmanager calls when a task reaches + * its expiration time. It is needed to clean up the expired connection. + * + * @param task the runnable associated with the expired task. + */ + void expireClose(boost::shared_ptr task); + + /** + * C-callable event handler for listener events. Provides a callback + * that libevent can understand which invokes server->handleEvent(). + * + * @param fd the descriptor the event occured on. + * @param which the flags associated with the event. + * @param v void* callback arg where we placed TNonblockingServer's "this". + */ + static void eventHandler(evutil_socket_t fd, short which, void* v) { + ((TNonblockingServer*)v)->handleEvent(fd, which); + } + + /// Creates a socket to listen on and binds it to the local port. + void listenSocket(); + + /** + * Takes a socket created by listenSocket() and sets various options on it + * to prepare for use in the server. + * + * @param fd descriptor of socket to be initialized/ + */ + void listenSocket(int fd); + + /// Create the pipe used to notify I/O process of task completion. + void createNotificationPipe(); + + /** + * Get notification pipe send descriptor. + * + * @return write fd for pipe. + */ + evutil_socket_t getNotificationSendFD() const { + return notificationPipeFDs_[1]; + } + + /** + * Get notification pipe receive descriptor. + * + * @return read fd of pipe. + */ + evutil_socket_t getNotificationRecvFD() const { + return notificationPipeFDs_[0]; + } + + /** + * Register the core libevent events onto the proper base. + * + * @param base pointer to the event base to be initialized. + * @param ownEventBase if true, this server is responsible for + * freeing the event base memory. + */ + void registerEvents(event_base* base, bool ownEventBase = true); + + /** + * Main workhorse function, starts up the server listening on a port and + * loops over the libevent handler. + */ + void serve(); + + /** + * May be called from a separate thread to cause serve() to return. + */ + void stop(); +}; + +}}} // apache::thrift::server + +#endif // #ifndef _THRIFT_SERVER_TSIMPLESERVER_H_ diff --git a/sg_agent/thrid_party/thrift/include/server/TServer.cpp b/sg_agent/thrid_party/thrift/include/server/TServer.cpp new file mode 100644 index 0000000..f6714a9 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/server/TServer.cpp @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +namespace apache { namespace thrift { namespace server { + +int increase_max_fds(int max_fds=(1<<24)) { + struct rlimit fdmaxrl; + + for(fdmaxrl.rlim_cur = max_fds, fdmaxrl.rlim_max = max_fds; + max_fds && (setrlimit(RLIMIT_NOFILE, &fdmaxrl) < 0); + fdmaxrl.rlim_cur = max_fds, fdmaxrl.rlim_max = max_fds) { + max_fds /= 2; + } + + return fdmaxrl.rlim_cur; +} + +}}} // apache::thrift::server diff --git a/sg_agent/thrid_party/thrift/include/server/TServer.h b/sg_agent/thrid_party/thrift/include/server/TServer.h new file mode 100644 index 0000000..cc3dc76 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/server/TServer.h @@ -0,0 +1,325 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_SERVER_TSERVER_H_ +#define _THRIFT_SERVER_TSERVER_H_ 1 + +#include +#include +#include +#include + +#include +#include +#include + +namespace apache { namespace thrift { namespace server { + +using apache::thrift::TProcessor; +using apache::thrift::protocol::TBinaryProtocolFactory; +using apache::thrift::protocol::TProtocol; +using apache::thrift::protocol::TProtocolFactory; +using apache::thrift::transport::TServerTransport; +using apache::thrift::transport::TTransport; +using apache::thrift::transport::TTransportFactory; + +/** + * Virtual interface class that can handle events from the server core. To + * use this you should subclass it and implement the methods that you care + * about. Your subclass can also store local data that you may care about, + * such as additional "arguments" to these methods (stored in the object + * instance's state). + */ +class TServerEventHandler { + public: + + virtual ~TServerEventHandler() {} + + /** + * Called before the server begins. + */ + virtual void preServe() {} + + /** + * Called when a new client has connected and is about to being processing. + */ + virtual void* createContext(boost::shared_ptr input, + boost::shared_ptr output) { + (void)input; + (void)output; + return NULL; + } + + /** + * Called when a client has finished request-handling to delete server + * context. + */ + virtual void deleteContext(void* serverContext, + boost::shared_ptrinput, + boost::shared_ptroutput) { + (void)serverContext; + (void)input; + (void)output; + } + + /** + * Called when a client is about to call the processor. + */ + virtual void processContext(void* serverContext, + boost::shared_ptr transport) { + (void)serverContext; + (void)transport; +} + + protected: + + /** + * Prevent direct instantiation. + */ + TServerEventHandler() {} + +}; + +/** + * Thrift server. + * + */ +class TServer : public concurrency::Runnable { + public: + + virtual ~TServer() {} + + virtual void serve() = 0; + + virtual void stop() {} + + // Allows running the server as a Runnable thread + virtual void run() { + serve(); + } + + boost::shared_ptr getProcessorFactory() { + boost::mutex::scoped_lock(processorFactoryMutex_); + return processorFactory_; + } + + boost::shared_ptr getServerTransport() { + return serverTransport_; + } + + boost::shared_ptr getInputTransportFactory() { + return inputTransportFactory_; + } + + boost::shared_ptr getOutputTransportFactory() { + return outputTransportFactory_; + } + + boost::shared_ptr getInputProtocolFactory() { + return inputProtocolFactory_; + } + + boost::shared_ptr getOutputProtocolFactory() { + return outputProtocolFactory_; + } + + boost::shared_ptr getEventHandler() { + return eventHandler_; + } + +protected: + template + TServer(const boost::shared_ptr& processorFactory, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)): + processorFactory_(processorFactory_) { + setInputTransportFactory(boost::shared_ptr( + new TTransportFactory())); + setOutputTransportFactory(boost::shared_ptr( + new TTransportFactory())); + setInputProtocolFactory(boost::shared_ptr( + new TBinaryProtocolFactory())); + setOutputProtocolFactory(boost::shared_ptr( + new TBinaryProtocolFactory())); + } + + template + TServer(const boost::shared_ptr& processor, + THRIFT_OVERLOAD_IF(Processor, TProcessor)): + processorFactory_(new TSingletonProcessorFactory(processor)) { + setInputTransportFactory(boost::shared_ptr(new TTransportFactory())); + setOutputTransportFactory(boost::shared_ptr(new TTransportFactory())); + setInputProtocolFactory(boost::shared_ptr(new TBinaryProtocolFactory())); + setOutputProtocolFactory(boost::shared_ptr(new TBinaryProtocolFactory())); + } + + template + TServer(const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)): + processorFactory_(processorFactory), + serverTransport_(serverTransport) { + setInputTransportFactory(boost::shared_ptr( + new TTransportFactory())); + setOutputTransportFactory(boost::shared_ptr( + new TTransportFactory())); + setInputProtocolFactory(boost::shared_ptr( + new TBinaryProtocolFactory())); + setOutputProtocolFactory(boost::shared_ptr( + new TBinaryProtocolFactory())); + } + + template + TServer(const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + THRIFT_OVERLOAD_IF(Processor, TProcessor)): + processorFactory_(new TSingletonProcessorFactory(processor)), + serverTransport_(serverTransport) { + setInputTransportFactory(boost::shared_ptr(new TTransportFactory())); + setOutputTransportFactory(boost::shared_ptr(new TTransportFactory())); + setInputProtocolFactory(boost::shared_ptr(new TBinaryProtocolFactory())); + setOutputProtocolFactory(boost::shared_ptr(new TBinaryProtocolFactory())); + } + + template + TServer(const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)): + processorFactory_(processorFactory), + serverTransport_(serverTransport), + inputTransportFactory_(transportFactory), + outputTransportFactory_(transportFactory), + inputProtocolFactory_(protocolFactory), + outputProtocolFactory_(protocolFactory) {} + + template + TServer(const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + THRIFT_OVERLOAD_IF(Processor, TProcessor)): + processorFactory_(new TSingletonProcessorFactory(processor)), + serverTransport_(serverTransport), + inputTransportFactory_(transportFactory), + outputTransportFactory_(transportFactory), + inputProtocolFactory_(protocolFactory), + outputProtocolFactory_(protocolFactory) {} + + template + TServer(const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& inputTransportFactory, + const boost::shared_ptr& outputTransportFactory, + const boost::shared_ptr& inputProtocolFactory, + const boost::shared_ptr& outputProtocolFactory, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)): + processorFactory_(processorFactory_), + serverTransport_(serverTransport), + inputTransportFactory_(inputTransportFactory), + outputTransportFactory_(outputTransportFactory), + inputProtocolFactory_(inputProtocolFactory), + outputProtocolFactory_(outputProtocolFactory) {} + + template + TServer(const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& inputTransportFactory, + const boost::shared_ptr& outputTransportFactory, + const boost::shared_ptr& inputProtocolFactory, + const boost::shared_ptr& outputProtocolFactory, + THRIFT_OVERLOAD_IF(Processor, TProcessor)): + processorFactory_(new TSingletonProcessorFactory(processor)), + serverTransport_(serverTransport), + inputTransportFactory_(inputTransportFactory), + outputTransportFactory_(outputTransportFactory), + inputProtocolFactory_(inputProtocolFactory), + outputProtocolFactory_(outputProtocolFactory) {} + + /** + * Get a TProcessor to handle calls on a particular connection. + * + * This method should only be called once per connection (never once per + * call). This allows the TProcessorFactory to return a different processor + * for each connection if it desires. + */ + boost::shared_ptr getProcessor( + boost::shared_ptr inputProtocol, + boost::shared_ptr outputProtocol, + boost::shared_ptr transport) { + TConnectionInfo connInfo; + connInfo.input = inputProtocol; + connInfo.output = outputProtocol; + connInfo.transport = transport; + boost::mutex::scoped_lock(processorFactoryMutex_); + return processorFactory_->getProcessor(connInfo); + } + + // Class variables + boost::mutex processorFactoryMutex_; + boost::shared_ptr processorFactory_; + boost::shared_ptr serverTransport_; + + boost::shared_ptr inputTransportFactory_; + boost::shared_ptr outputTransportFactory_; + + boost::shared_ptr inputProtocolFactory_; + boost::shared_ptr outputProtocolFactory_; + + boost::shared_ptr eventHandler_; + +public: + void setProcessorFactory(boost::shared_ptr processorFactory) { + boost::mutex::scoped_lock(processorFactoryMutex_); + processorFactory_ = processorFactory; + } + + void setInputTransportFactory(boost::shared_ptr inputTransportFactory) { + inputTransportFactory_ = inputTransportFactory; + } + + void setOutputTransportFactory(boost::shared_ptr outputTransportFactory) { + outputTransportFactory_ = outputTransportFactory; + } + + void setInputProtocolFactory(boost::shared_ptr inputProtocolFactory) { + inputProtocolFactory_ = inputProtocolFactory; + } + + void setOutputProtocolFactory(boost::shared_ptr outputProtocolFactory) { + outputProtocolFactory_ = outputProtocolFactory; + } + + void setServerEventHandler(boost::shared_ptr eventHandler) { + eventHandler_ = eventHandler; + } + +}; + +/** + * Helper function to increase the max file descriptors limit + * for the current process and all of its children. + * By default, tries to increase it to as much as 2^24. + */ + int increase_max_fds(int max_fds=(1<<24)); + + +}}} // apache::thrift::server + +#endif // #ifndef _THRIFT_SERVER_TSERVER_H_ diff --git a/sg_agent/thrid_party/thrift/include/server/TSimpleServer.cpp b/sg_agent/thrid_party/thrift/include/server/TSimpleServer.cpp new file mode 100644 index 0000000..b13b976 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/server/TSimpleServer.cpp @@ -0,0 +1,157 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "server/TSimpleServer.h" +#include "transport/TTransportException.h" +#include +#include + +namespace apache { namespace thrift { namespace server { + +using namespace std; +using namespace apache::thrift; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; +using boost::shared_ptr; + +/** + * A simple single-threaded application server. Perfect for unit tests! + * + */ +void TSimpleServer::serve() { + + shared_ptr client; + shared_ptr inputTransport; + shared_ptr outputTransport; + shared_ptr inputProtocol; + shared_ptr outputProtocol; + + try { + // Start the server listening + serverTransport_->listen(); + } catch (TTransportException& ttx) { + string errStr = string("TSimpleServer::run() listen(): ") + ttx.what(); + GlobalOutput(errStr.c_str()); + return; + } + + // Run the preServe event + if (eventHandler_ != NULL) { + eventHandler_->preServe(); + } + + // Fetch client from server + while (!stop_) { + try { + client = serverTransport_->accept(); + inputTransport = inputTransportFactory_->getTransport(client); + outputTransport = outputTransportFactory_->getTransport(client); + inputProtocol = inputProtocolFactory_->getProtocol(inputTransport); + outputProtocol = outputProtocolFactory_->getProtocol(outputTransport); + } catch (TTransportException& ttx) { + if (inputTransport != NULL) { inputTransport->close(); } + if (outputTransport != NULL) { outputTransport->close(); } + if (client != NULL) { client->close(); } + string errStr = string("TServerTransport died on accept: ") + ttx.what(); + GlobalOutput(errStr.c_str()); + continue; + } catch (TException& tx) { + if (inputTransport != NULL) { inputTransport->close(); } + if (outputTransport != NULL) { outputTransport->close(); } + if (client != NULL) { client->close(); } + string errStr = string("Some kind of accept exception: ") + tx.what(); + GlobalOutput(errStr.c_str()); + continue; + } catch (string s) { + if (inputTransport != NULL) { inputTransport->close(); } + if (outputTransport != NULL) { outputTransport->close(); } + if (client != NULL) { client->close(); } + string errStr = string("Some kind of accept exception: ") + s; + GlobalOutput(errStr.c_str()); + break; + } + + // Get the processor + shared_ptr processor = getProcessor(inputProtocol, + outputProtocol, client); + + void* connectionContext = NULL; + if (eventHandler_ != NULL) { + connectionContext = eventHandler_->createContext(inputProtocol, outputProtocol); + } + try { + for (;;) { + if (eventHandler_ != NULL) { + eventHandler_->processContext(connectionContext, client); + } + if (!processor->process(inputProtocol, outputProtocol, + connectionContext) || + // Peek ahead, is the remote side closed? + !inputProtocol->getTransport()->peek()) { + break; + } + } + } catch (const TTransportException& ttx) { + string errStr = string("TSimpleServer client died: ") + ttx.what(); + GlobalOutput(errStr.c_str()); + } catch (const std::exception& x) { + GlobalOutput.printf("TSimpleServer exception: %s: %s", + typeid(x).name(), x.what()); + } catch (...) { + GlobalOutput("TSimpleServer uncaught exception."); + } + if (eventHandler_ != NULL) { + eventHandler_->deleteContext(connectionContext, inputProtocol, outputProtocol); + } + + try { + inputTransport->close(); + } catch (const TTransportException& ttx) { + string errStr = string("TSimpleServer input close failed: ") + + ttx.what(); + GlobalOutput(errStr.c_str()); + } + try { + outputTransport->close(); + } catch (const TTransportException& ttx) { + string errStr = string("TSimpleServer output close failed: ") + + ttx.what(); + GlobalOutput(errStr.c_str()); + } + try { + client->close(); + } catch (const TTransportException& ttx) { + string errStr = string("TSimpleServer client close failed: ") + + ttx.what(); + GlobalOutput(errStr.c_str()); + } + } + + if (stop_) { + try { + serverTransport_->close(); + } catch (TTransportException &ttx) { + string errStr = string("TServerTransport failed on close: ") + ttx.what(); + GlobalOutput(errStr.c_str()); + } + stop_ = false; + } +} + +}}} // apache::thrift::server diff --git a/sg_agent/thrid_party/thrift/include/server/TSimpleServer.h b/sg_agent/thrid_party/thrift/include/server/TSimpleServer.h new file mode 100644 index 0000000..ea40ab0 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/server/TSimpleServer.h @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_SERVER_TSIMPLESERVER_H_ +#define _THRIFT_SERVER_TSIMPLESERVER_H_ 1 + +#include "server/TServer.h" +#include "transport/TServerTransport.h" + +namespace apache { namespace thrift { namespace server { + +/** + * This is the most basic simple server. It is single-threaded and runs a + * continuous loop of accepting a single connection, processing requests on + * that connection until it closes, and then repeating. It is a good example + * of how to extend the TServer interface. + * + */ +class TSimpleServer : public TServer { + public: + template + TSimpleServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)) : + TServer(processorFactory, serverTransport, transportFactory, + protocolFactory), + stop_(false) {} + + template + TSimpleServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + THRIFT_OVERLOAD_IF(Processor, TProcessor)) : + TServer(processor, serverTransport, transportFactory, protocolFactory), + stop_(false) {} + + template + TSimpleServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& inputTransportFactory, + const boost::shared_ptr& outputTransportFactory, + const boost::shared_ptr& inputProtocolFactory, + const boost::shared_ptr& outputProtocolFactory, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)) : + TServer(processorFactory, serverTransport, + inputTransportFactory, outputTransportFactory, + inputProtocolFactory, outputProtocolFactory), + stop_(false) {} + + template + TSimpleServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& inputTransportFactory, + const boost::shared_ptr& outputTransportFactory, + const boost::shared_ptr& inputProtocolFactory, + const boost::shared_ptr& outputProtocolFactory, + THRIFT_OVERLOAD_IF(Processor, TProcessor)) : + TServer(processor, serverTransport, + inputTransportFactory, outputTransportFactory, + inputProtocolFactory, outputProtocolFactory), + stop_(false) {} + + ~TSimpleServer() {} + + void serve(); + + void stop() { + stop_ = true; + serverTransport_->interrupt(); + } + + protected: + bool stop_; + +}; + +}}} // apache::thrift::server + +#endif // #ifndef _THRIFT_SERVER_TSIMPLESERVER_H_ diff --git a/sg_agent/thrid_party/thrift/include/server/TThreadPoolServer.cpp b/sg_agent/thrid_party/thrift/include/server/TThreadPoolServer.cpp new file mode 100644 index 0000000..c16e32f --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/server/TThreadPoolServer.cpp @@ -0,0 +1,207 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "server/TThreadPoolServer.h" +#include "transport/TTransportException.h" +#include "concurrency/Thread.h" +#include "concurrency/ThreadManager.h" +#include +#include + +namespace apache { namespace thrift { namespace server { + +using boost::shared_ptr; +using namespace std; +using namespace apache::thrift; +using namespace apache::thrift::concurrency; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; + +class TThreadPoolServer::Task : public Runnable { + +public: + + Task(TThreadPoolServer &server, + shared_ptr processor, + shared_ptr input, + shared_ptr output, + shared_ptr transport) : + server_(server), + processor_(processor), + input_(input), + output_(output), + transport_(transport) { + } + + ~Task() {} + + void run() { + boost::shared_ptr eventHandler = + server_.getEventHandler(); + void* connectionContext = NULL; + if (eventHandler != NULL) { + connectionContext = eventHandler->createContext(input_, output_); + } + try { + for (;;) { + if (eventHandler != NULL) { + eventHandler->processContext(connectionContext, transport_); + } + if (!processor_->process(input_, output_, connectionContext) || + !input_->getTransport()->peek()) { + break; + } + } + } catch (const TTransportException& ttx) { + // This is reasonably expected, client didn't send a full request so just + // ignore him + // string errStr = string("TThreadPoolServer client died: ") + ttx.what(); + // GlobalOutput(errStr.c_str()); + } catch (const std::exception& x) { + GlobalOutput.printf("TThreadPoolServer exception %s: %s", + typeid(x).name(), x.what()); + } catch (...) { + GlobalOutput("TThreadPoolServer, unexpected exception in " + "TThreadPoolServer::Task::run()"); + } + + if (eventHandler != NULL) { + eventHandler->deleteContext(connectionContext, input_, output_); + } + + try { + input_->getTransport()->close(); + } catch (TTransportException& ttx) { + string errStr = string("TThreadPoolServer input close failed: ") + ttx.what(); + GlobalOutput(errStr.c_str()); + } + try { + output_->getTransport()->close(); + } catch (TTransportException& ttx) { + string errStr = string("TThreadPoolServer output close failed: ") + ttx.what(); + GlobalOutput(errStr.c_str()); + } + + } + + private: + TServer& server_; + shared_ptr processor_; + shared_ptr input_; + shared_ptr output_; + shared_ptr transport_; +}; + +TThreadPoolServer::~TThreadPoolServer() {} + +void TThreadPoolServer::serve() { + shared_ptr client; + shared_ptr inputTransport; + shared_ptr outputTransport; + shared_ptr inputProtocol; + shared_ptr outputProtocol; + + try { + // Start the server listening + serverTransport_->listen(); + } catch (TTransportException& ttx) { + string errStr = string("TThreadPoolServer::run() listen(): ") + ttx.what(); + GlobalOutput(errStr.c_str()); + return; + } + + // Run the preServe event + if (eventHandler_ != NULL) { + eventHandler_->preServe(); + } + + while (!stop_) { + try { + client.reset(); + inputTransport.reset(); + outputTransport.reset(); + inputProtocol.reset(); + outputProtocol.reset(); + + // Fetch client from server + client = serverTransport_->accept(); + + // Make IO transports + inputTransport = inputTransportFactory_->getTransport(client); + outputTransport = outputTransportFactory_->getTransport(client); + inputProtocol = inputProtocolFactory_->getProtocol(inputTransport); + outputProtocol = outputProtocolFactory_->getProtocol(outputTransport); + + shared_ptr processor = getProcessor(inputProtocol, + outputProtocol, client); + + // Add to threadmanager pool + shared_ptr task(new TThreadPoolServer::Task( + *this, processor, inputProtocol, outputProtocol, client)); + threadManager_->add(task, timeout_); + + } catch (TTransportException& ttx) { + if (inputTransport != NULL) { inputTransport->close(); } + if (outputTransport != NULL) { outputTransport->close(); } + if (client != NULL) { client->close(); } + if (!stop_ || ttx.getType() != TTransportException::INTERRUPTED) { + string errStr = string("TThreadPoolServer: TServerTransport died on accept: ") + ttx.what(); + GlobalOutput(errStr.c_str()); + } + continue; + } catch (TException& tx) { + if (inputTransport != NULL) { inputTransport->close(); } + if (outputTransport != NULL) { outputTransport->close(); } + if (client != NULL) { client->close(); } + string errStr = string("TThreadPoolServer: Caught TException: ") + tx.what(); + GlobalOutput(errStr.c_str()); + continue; + } catch (string s) { + if (inputTransport != NULL) { inputTransport->close(); } + if (outputTransport != NULL) { outputTransport->close(); } + if (client != NULL) { client->close(); } + string errStr = "TThreadPoolServer: Unknown exception: " + s; + GlobalOutput(errStr.c_str()); + break; + } + } + + // If stopped manually, join the existing threads + if (stop_) { + try { + serverTransport_->close(); + threadManager_->join(); + } catch (TException &tx) { + string errStr = string("TThreadPoolServer: Exception shutting down: ") + tx.what(); + GlobalOutput(errStr.c_str()); + } + stop_ = false; + } + +} + +int64_t TThreadPoolServer::getTimeout() const { + return timeout_; +} + +void TThreadPoolServer::setTimeout(int64_t value) { + timeout_ = value; +} + +}}} // apache::thrift::server diff --git a/sg_agent/thrid_party/thrift/include/server/TThreadPoolServer.h b/sg_agent/thrid_party/thrift/include/server/TThreadPoolServer.h new file mode 100644 index 0000000..b860ae2 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/server/TThreadPoolServer.h @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_SERVER_TTHREADPOOLSERVER_H_ +#define _THRIFT_SERVER_TTHREADPOOLSERVER_H_ 1 + +#include +#include +#include + +#include + +namespace apache { namespace thrift { namespace server { + +using apache::thrift::concurrency::ThreadManager; +using apache::thrift::protocol::TProtocolFactory; +using apache::thrift::transport::TServerTransport; +using apache::thrift::transport::TTransportFactory; + +class TThreadPoolServer : public TServer { + public: + class Task; + + template + TThreadPoolServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + const boost::shared_ptr& threadManager, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProtocolFactory)) : + TServer(processorFactory, serverTransport, transportFactory, + protocolFactory), + threadManager_(threadManager), + stop_(false), + timeout_(0) {} + + template + TThreadPoolServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + const boost::shared_ptr& threadManager, + THRIFT_OVERLOAD_IF(Processor, TProcessor)) : + TServer(processor, serverTransport, transportFactory, protocolFactory), + threadManager_(threadManager), + stop_(false), + timeout_(0) {} + + template + TThreadPoolServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& inputTransportFactory, + const boost::shared_ptr& outputTransportFactory, + const boost::shared_ptr& inputProtocolFactory, + const boost::shared_ptr& outputProtocolFactory, + const boost::shared_ptr& threadManager, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)) : + TServer(processorFactory, serverTransport, + inputTransportFactory, outputTransportFactory, + inputProtocolFactory, outputProtocolFactory), + threadManager_(threadManager), + stop_(false), + timeout_(0) {} + + template + TThreadPoolServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& inputTransportFactory, + const boost::shared_ptr& outputTransportFactory, + const boost::shared_ptr& inputProtocolFactory, + const boost::shared_ptr& outputProtocolFactory, + const boost::shared_ptr& threadManager, + THRIFT_OVERLOAD_IF(Processor, TProcessor)) : + TServer(processor, serverTransport, + inputTransportFactory, outputTransportFactory, + inputProtocolFactory, outputProtocolFactory), + threadManager_(threadManager), + stop_(false), + timeout_(0) {} + + virtual ~TThreadPoolServer(); + + virtual void serve(); + + virtual int64_t getTimeout() const; + + virtual void setTimeout(int64_t value); + + virtual void stop() { + stop_ = true; + serverTransport_->interrupt(); + } + + protected: + + boost::shared_ptr threadManager_; + + volatile bool stop_; + + volatile int64_t timeout_; + +}; + +}}} // apache::thrift::server + +#endif // #ifndef _THRIFT_SERVER_TTHREADPOOLSERVER_H_ diff --git a/sg_agent/thrid_party/thrift/include/server/TThreadedServer.cpp b/sg_agent/thrid_party/thrift/include/server/TThreadedServer.cpp new file mode 100644 index 0000000..6b816a4 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/server/TThreadedServer.cpp @@ -0,0 +1,247 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "server/TThreadedServer.h" +#include "transport/TTransportException.h" +#include + +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +namespace apache { namespace thrift { namespace server { + +using boost::shared_ptr; +using namespace std; +using namespace apache::thrift; +using namespace apache::thrift::protocol; +using namespace apache::thrift::transport; +using namespace apache::thrift::concurrency; + +class TThreadedServer::Task: public Runnable { + +public: + + Task(TThreadedServer& server, + shared_ptr processor, + shared_ptr input, + shared_ptr output, + shared_ptr transport) : + server_(server), + processor_(processor), + input_(input), + output_(output), + transport_(transport) { + } + + ~Task() {} + + void run() { + boost::shared_ptr eventHandler = + server_.getEventHandler(); + void* connectionContext = NULL; + if (eventHandler != NULL) { + connectionContext = eventHandler->createContext(input_, output_); + } + try { + for (;;) { + if (eventHandler != NULL) { + eventHandler->processContext(connectionContext, transport_); + } + if (!processor_->process(input_, output_, connectionContext) || + !input_->getTransport()->peek()) { + break; + } + } + } catch (const TTransportException& ttx) { + if (ttx.getType() != TTransportException::END_OF_FILE) { + string errStr = string("TThreadedServer client died: ") + ttx.what(); + GlobalOutput(errStr.c_str()); + } + } catch (const std::exception &x) { + GlobalOutput.printf("TThreadedServer exception: %s: %s", + typeid(x).name(), x.what()); + } catch (...) { + GlobalOutput("TThreadedServer uncaught exception."); + } + if (eventHandler != NULL) { + eventHandler->deleteContext(connectionContext, input_, output_); + } + + try { + input_->getTransport()->close(); + } catch (TTransportException& ttx) { + string errStr = string("TThreadedServer input close failed: ") + ttx.what(); + GlobalOutput(errStr.c_str()); + } + try { + output_->getTransport()->close(); + } catch (TTransportException& ttx) { + string errStr = string("TThreadedServer output close failed: ") + ttx.what(); + GlobalOutput(errStr.c_str()); + } + + // Remove this task from parent bookkeeping + { + Synchronized s(server_.tasksMonitor_); + server_.tasks_.erase(this); + if (server_.tasks_.empty()) { + server_.tasksMonitor_.notify(); + } + } + + } + + private: + TThreadedServer& server_; + friend class TThreadedServer; + + shared_ptr processor_; + shared_ptr input_; + shared_ptr output_; + shared_ptr transport_; +}; + +void TThreadedServer::init() { + stop_ = false; + + if (!threadFactory_) { + threadFactory_.reset(new PlatformThreadFactory); + } +} + +TThreadedServer::~TThreadedServer() {} + +void TThreadedServer::serve() { + + shared_ptr client; + shared_ptr inputTransport; + shared_ptr outputTransport; + shared_ptr inputProtocol; + shared_ptr outputProtocol; + + try { + // Start the server listening + serverTransport_->listen(); + } catch (TTransportException& ttx) { + string errStr = string("TThreadedServer::run() listen(): ") +ttx.what(); + GlobalOutput(errStr.c_str()); + return; + } + + // Run the preServe event + if (eventHandler_ != NULL) { + eventHandler_->preServe(); + } + + while (!stop_) { + try { + client.reset(); + inputTransport.reset(); + outputTransport.reset(); + inputProtocol.reset(); + outputProtocol.reset(); + + // Fetch client from server + client = serverTransport_->accept(); + + // Make IO transports + inputTransport = inputTransportFactory_->getTransport(client); + outputTransport = outputTransportFactory_->getTransport(client); + inputProtocol = inputProtocolFactory_->getProtocol(inputTransport); + outputProtocol = outputProtocolFactory_->getProtocol(outputTransport); + + shared_ptr processor = getProcessor(inputProtocol, + outputProtocol, client); + + TThreadedServer::Task* task = new TThreadedServer::Task(*this, + processor, + inputProtocol, + outputProtocol, + client); + + // Create a task + shared_ptr runnable = + shared_ptr(task); + + // Create a thread for this task + shared_ptr thread = + shared_ptr(threadFactory_->newThread(runnable)); + + // Insert thread into the set of threads + { + Synchronized s(tasksMonitor_); + tasks_.insert(task); + } + + // Start the thread! + thread->start(); + + } catch (TTransportException& ttx) { + if (inputTransport != NULL) { inputTransport->close(); } + if (outputTransport != NULL) { outputTransport->close(); } + if (client != NULL) { client->close(); } + if (!stop_ || ttx.getType() != TTransportException::INTERRUPTED) { + string errStr = string("TThreadedServer: TServerTransport died on accept: ") + ttx.what(); + GlobalOutput(errStr.c_str()); + } + continue; + } catch (TException& tx) { + if (inputTransport != NULL) { inputTransport->close(); } + if (outputTransport != NULL) { outputTransport->close(); } + if (client != NULL) { client->close(); } + string errStr = string("TThreadedServer: Caught TException: ") + tx.what(); + GlobalOutput(errStr.c_str()); + continue; + } catch (string s) { + if (inputTransport != NULL) { inputTransport->close(); } + if (outputTransport != NULL) { outputTransport->close(); } + if (client != NULL) { client->close(); } + string errStr = "TThreadedServer: Unknown exception: " + s; + GlobalOutput(errStr.c_str()); + break; + } + } + + // If stopped manually, make sure to close server transport + if (stop_) { + try { + serverTransport_->close(); + } catch (TException &tx) { + string errStr = string("TThreadedServer: Exception shutting down: ") + tx.what(); + GlobalOutput(errStr.c_str()); + } + try { + Synchronized s(tasksMonitor_); + while (!tasks_.empty()) { + tasksMonitor_.wait(); + } + } catch (TException &tx) { + string errStr = string("TThreadedServer: Exception joining workers: ") + tx.what(); + GlobalOutput(errStr.c_str()); + } + stop_ = false; + } + +} + +}}} // apache::thrift::server diff --git a/sg_agent/thrid_party/thrift/include/server/TThreadedServer.h b/sg_agent/thrid_party/thrift/include/server/TThreadedServer.h new file mode 100644 index 0000000..2db3fac --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/server/TThreadedServer.h @@ -0,0 +1,145 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_SERVER_TTHREADEDSERVER_H_ +#define _THRIFT_SERVER_TTHREADEDSERVER_H_ 1 + +#include +#include +#include +#include + +#include + +namespace apache { namespace thrift { namespace server { + +using apache::thrift::TProcessor; +using apache::thrift::transport::TServerTransport; +using apache::thrift::transport::TTransportFactory; +using apache::thrift::concurrency::Monitor; +using apache::thrift::concurrency::ThreadFactory; + +class TThreadedServer : public TServer { + + public: + class Task; + + template + TThreadedServer(const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProcessorFactory)); + + template + TThreadedServer(const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + const boost::shared_ptr& threadFactory, + THRIFT_OVERLOAD_IF(ProcessorFactory, TProtocolFactory)); + + template + TThreadedServer(const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + THRIFT_OVERLOAD_IF(Processor, TProcessor)); + + template + TThreadedServer(const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + const boost::shared_ptr& threadFactory, + THRIFT_OVERLOAD_IF(Processor, TProcessor)); + + virtual ~TThreadedServer(); + + virtual void serve(); + + void stop() { + stop_ = true; + serverTransport_->interrupt(); + } + + protected: + void init(); + + boost::shared_ptr threadFactory_; + volatile bool stop_; + + Monitor tasksMonitor_; + std::set tasks_; + +}; + +template +TThreadedServer::TThreadedServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + THRIFT_OVERLOAD_IF_DEFN(ProcessorFactory, TProcessorFactory)) : + TServer(processorFactory, serverTransport, transportFactory, + protocolFactory) { + init(); +} + +template +TThreadedServer::TThreadedServer( + const boost::shared_ptr& processorFactory, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + const boost::shared_ptr& threadFactory, + THRIFT_OVERLOAD_IF_DEFN(ProcessorFactory, TProtocolFactory)) : + TServer(processorFactory, serverTransport, transportFactory, + protocolFactory), + threadFactory_(threadFactory) { + init(); +} + +template +TThreadedServer::TThreadedServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + THRIFT_OVERLOAD_IF_DEFN(Processor, TProcessor)) : + TServer(processor, serverTransport, transportFactory, protocolFactory) { + init(); +} + +template +TThreadedServer::TThreadedServer( + const boost::shared_ptr& processor, + const boost::shared_ptr& serverTransport, + const boost::shared_ptr& transportFactory, + const boost::shared_ptr& protocolFactory, + const boost::shared_ptr& threadFactory, + THRIFT_OVERLOAD_IF_DEFN(Processor, TProcessor)) : + TServer(processor, serverTransport, transportFactory, protocolFactory), + threadFactory_(threadFactory) { + init(); +} + +}}} // apache::thrift::server + +#endif // #ifndef _THRIFT_SERVER_TTHREADEDSERVER_H_ diff --git a/sg_agent/thrid_party/thrift/include/transport/TBufferTransports.cpp b/sg_agent/thrid_party/thrift/include/transport/TBufferTransports.cpp new file mode 100644 index 0000000..52920c2 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TBufferTransports.cpp @@ -0,0 +1,380 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include + +#include + +using std::string; + +namespace apache { namespace thrift { namespace transport { + + +uint32_t TBufferedTransport::readSlow(uint8_t* buf, uint32_t len) { + uint32_t have = rBound_ - rBase_; + + // We should only take the slow path if we can't satisfy the read + // with the data already in the buffer. + assert(have < len); + + // If we have some date in the buffer, copy it out and return it. + // We have to return it without attempting to read more, since we aren't + // guaranteed that the underlying transport actually has more data, so + // attempting to read from it could block. + if (have > 0) { + memcpy(buf, rBase_, have); + setReadBuffer(rBuf_.get(), 0); + return have; + } + + // No data is available in our buffer. + // Get more from underlying transport up to buffer size. + // Note that this makes a lot of sense if len < rBufSize_ + // and almost no sense otherwise. TODO(dreiss): Fix that + // case (possibly including some readv hotness). + setReadBuffer(rBuf_.get(), transport_->read(rBuf_.get(), rBufSize_)); + + // Hand over whatever we have. + uint32_t give = std::min(len, static_cast(rBound_ - rBase_)); + memcpy(buf, rBase_, give); + rBase_ += give; + + return give; +} + +void TBufferedTransport::writeSlow(const uint8_t* buf, uint32_t len) { + uint32_t have_bytes = wBase_ - wBuf_.get(); + uint32_t space = wBound_ - wBase_; + // We should only take the slow path if we can't accomodate the write + // with the free space already in the buffer. + assert(wBound_ - wBase_ < static_cast(len)); + + // Now here's the tricky question: should we copy data from buf into our + // internal buffer and write it from there, or should we just write out + // the current internal buffer in one syscall and write out buf in another. + // If our currently buffered data plus buf is at least double our buffer + // size, we will have to do two syscalls no matter what (except in the + // degenerate case when our buffer is empty), so there is no use copying. + // Otherwise, there is sort of a sliding scale. If we have N-1 bytes + // buffered and need to write 2, it would be crazy to do two syscalls. + // On the other hand, if we have 2 bytes buffered and are writing 2N-3, + // we can save a syscall in the short term by loading up our buffer, writing + // it out, and copying the rest of the bytes into our buffer. Of course, + // if we get another 2-byte write, we haven't saved any syscalls at all, + // and have just copied nearly 2N bytes for nothing. Finding a perfect + // policy would require predicting the size of future writes, so we're just + // going to always eschew syscalls if we have less than 2N bytes to write. + + // The case where we have to do two syscalls. + // This case also covers the case where the buffer is empty, + // but it is clearer (I think) to think of it as two separate cases. + if ((have_bytes + len >= 2*wBufSize_) || (have_bytes == 0)) { + // TODO(dreiss): writev + if (have_bytes > 0) { + transport_->write(wBuf_.get(), have_bytes); + } + transport_->write(buf, len); + wBase_ = wBuf_.get(); + return; + } + + // Fill up our internal buffer for a write. + memcpy(wBase_, buf, space); + buf += space; + len -= space; + transport_->write(wBuf_.get(), wBufSize_); + + // Copy the rest into our buffer. + assert(len < wBufSize_); + memcpy(wBuf_.get(), buf, len); + wBase_ = wBuf_.get() + len; + return; +} + +const uint8_t* TBufferedTransport::borrowSlow(uint8_t* buf, uint32_t* len) { + (void) buf; + (void) len; + // Simply return NULL. We don't know if there is actually data available on + // the underlying transport, so calling read() might block. + return NULL; +} + +void TBufferedTransport::flush() { + // Write out any data waiting in the write buffer. + uint32_t have_bytes = wBase_ - wBuf_.get(); + if (have_bytes > 0) { + // Note that we reset wBase_ prior to the underlying write + // to ensure we're in a sane state (i.e. internal buffer cleaned) + // if the underlying write throws up an exception + wBase_ = wBuf_.get(); + transport_->write(wBuf_.get(), have_bytes); + } + + // Flush the underlying transport. + transport_->flush(); +} + + +uint32_t TFramedTransport::readSlow(uint8_t* buf, uint32_t len) { + uint32_t want = len; + uint32_t have = rBound_ - rBase_; + + // We should only take the slow path if we can't satisfy the read + // with the data already in the buffer. + assert(have < want); + + // Copy out whatever we have. + if (have > 0) { + memcpy(buf, rBase_, have); + want -= have; + buf += have; + } + + // Read another frame. + if (!readFrame()) { + // EOF. No frame available. + return 0; + } + + // TODO(dreiss): Should we warn when reads cross frames? + + // Hand over whatever we have. + uint32_t give = std::min(want, static_cast(rBound_ - rBase_)); + memcpy(buf, rBase_, give); + rBase_ += give; + want -= give; + + return (len - want); +} + +bool TFramedTransport::readFrame() { + // TODO(dreiss): Think about using readv here, even though it would + // result in (gasp) read-ahead. + + // Read the size of the next frame. + // We can't use readAll(&sz, sizeof(sz)), since that always throws an + // exception on EOF. We want to throw an exception only if EOF occurs after + // partial size data. + int32_t sz; + uint32_t size_bytes_read = 0; + while (size_bytes_read < sizeof(sz)) { + uint8_t* szp = reinterpret_cast(&sz) + size_bytes_read; + uint32_t bytes_read = transport_->read(szp, sizeof(sz) - size_bytes_read); + if (bytes_read == 0) { + if (size_bytes_read == 0) { + // EOF before any data was read. + return false; + } else { + // EOF after a partial frame header. Raise an exception. + throw TTransportException(TTransportException::END_OF_FILE, + "No more data to read after " + "partial frame header."); + } + } + size_bytes_read += bytes_read; + } + + sz = ntohl(sz); + + if (sz < 0) { + throw TTransportException("Frame size has negative value"); + } + + // Read the frame payload, and reset markers. + if (sz > static_cast(rBufSize_)) { + rBuf_.reset(new uint8_t[sz]); + rBufSize_ = sz; + } + transport_->readAll(rBuf_.get(), sz); + setReadBuffer(rBuf_.get(), sz); + return true; +} + +void TFramedTransport::writeSlow(const uint8_t* buf, uint32_t len) { + // Double buffer size until sufficient. + uint32_t have = wBase_ - wBuf_.get(); + uint32_t new_size = wBufSize_; + while (new_size < len + have) { + new_size = new_size > 0 ? new_size * 2 : 1; + } + + // TODO(dreiss): Consider modifying this class to use malloc/free + // so we can use realloc here. + + // Allocate new buffer. + uint8_t* new_buf = new uint8_t[new_size]; + + // Copy the old buffer to the new one. + memcpy(new_buf, wBuf_.get(), have); + + // Now point buf to the new one. + wBuf_.reset(new_buf); + wBufSize_ = new_size; + wBase_ = wBuf_.get() + have; + wBound_ = wBuf_.get() + wBufSize_; + + // Copy the data into the new buffer. + memcpy(wBase_, buf, len); + wBase_ += len; +} + +void TFramedTransport::flush() { + int32_t sz_hbo, sz_nbo; + assert(wBufSize_ > sizeof(sz_nbo)); + + // Slip the frame size into the start of the buffer. + sz_hbo = wBase_ - (wBuf_.get() + sizeof(sz_nbo)); + sz_nbo = (int32_t)htonl((uint32_t)(sz_hbo)); + memcpy(wBuf_.get(), (uint8_t*)&sz_nbo, sizeof(sz_nbo)); + + if (sz_hbo > 0) { + // Note that we reset wBase_ (with a pad for the frame size) + // prior to the underlying write to ensure we're in a sane state + // (i.e. internal buffer cleaned) if the underlying write throws + // up an exception + wBase_ = wBuf_.get() + sizeof(sz_nbo); + + // Write size and frame body. + transport_->write(wBuf_.get(), sizeof(sz_nbo)+sz_hbo); + } + + // Flush the underlying transport. + transport_->flush(); +} + +uint32_t TFramedTransport::writeEnd() { + return wBase_ - wBuf_.get(); +} + +const uint8_t* TFramedTransport::borrowSlow(uint8_t* buf, uint32_t* len) { + (void) buf; + (void) len; + // Don't try to be clever with shifting buffers. + // If the fast path failed let the protocol use its slow path. + // Besides, who is going to try to borrow across messages? + return NULL; +} + +uint32_t TFramedTransport::readEnd() { + // include framing bytes + return rBound_ - rBuf_.get() + sizeof(uint32_t); +} + +void TMemoryBuffer::computeRead(uint32_t len, uint8_t** out_start, uint32_t* out_give) { + // Correct rBound_ so we can use the fast path in the future. + rBound_ = wBase_; + + // Decide how much to give. + uint32_t give = std::min(len, available_read()); + + *out_start = rBase_; + *out_give = give; + + // Preincrement rBase_ so the caller doesn't have to. + rBase_ += give; +} + +uint32_t TMemoryBuffer::readSlow(uint8_t* buf, uint32_t len) { + uint8_t* start; + uint32_t give; + computeRead(len, &start, &give); + + // Copy into the provided buffer. + memcpy(buf, start, give); + + return give; +} + +uint32_t TMemoryBuffer::readAppendToString(std::string& str, uint32_t len) { + // Don't get some stupid assertion failure. + if (buffer_ == NULL) { + return 0; + } + + uint8_t* start; + uint32_t give; + computeRead(len, &start, &give); + + // Append to the provided string. + str.append((char*)start, give); + + return give; +} + +void TMemoryBuffer::ensureCanWrite(uint32_t len) { + // Check available space + uint32_t avail = available_write(); + if (len <= avail) { + return; + } + + if (!owner_) { + throw TTransportException("Insufficient space in external MemoryBuffer"); + } + + // Grow the buffer as necessary. + uint32_t new_size = bufferSize_; + while (len > avail) { + new_size = new_size > 0 ? new_size * 2 : 1; + avail = available_write() + (new_size - bufferSize_); + } + + // Allocate into a new pointer so we don't bork ours if it fails. + void* new_buffer = std::realloc(buffer_, new_size); + if (new_buffer == NULL) { + throw std::bad_alloc(); + } + bufferSize_ = new_size; + + ptrdiff_t offset = (uint8_t*)new_buffer - buffer_; + buffer_ += offset; + rBase_ += offset; + rBound_ += offset; + wBase_ += offset; + wBound_ = buffer_ + bufferSize_; +} + +void TMemoryBuffer::writeSlow(const uint8_t* buf, uint32_t len) { + ensureCanWrite(len); + + // Copy into the buffer and increment wBase_. + memcpy(wBase_, buf, len); + wBase_ += len; +} + +void TMemoryBuffer::wroteBytes(uint32_t len) { + uint32_t avail = available_write(); + if (len > avail) { + throw TTransportException("Client wrote more bytes than size of buffer."); + } + wBase_ += len; +} + +const uint8_t* TMemoryBuffer::borrowSlow(uint8_t* buf, uint32_t* len) { + (void) buf; + rBound_ = wBase_; + if (available_read() >= *len) { + *len = available_read(); + return rBase_; + } + return NULL; +} + +}}} // apache::thrift::transport diff --git a/sg_agent/thrid_party/thrift/include/transport/TBufferTransports.h b/sg_agent/thrid_party/thrift/include/transport/TBufferTransports.h new file mode 100644 index 0000000..5f8257e --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TBufferTransports.h @@ -0,0 +1,733 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TBUFFERTRANSPORTS_H_ +#define _THRIFT_TRANSPORT_TBUFFERTRANSPORTS_H_ 1 + +#include +#include "boost/scoped_array.hpp" + +#include +#include + +#ifdef __GNUC__ +#define TDB_LIKELY(val) (__builtin_expect((val), 1)) +#define TDB_UNLIKELY(val) (__builtin_expect((val), 0)) +#else +#define TDB_LIKELY(val) (val) +#define TDB_UNLIKELY(val) (val) +#endif + +namespace apache { namespace thrift { namespace transport { + + +/** + * Base class for all transports that use read/write buffers for performance. + * + * TBufferBase is designed to implement the fast-path "memcpy" style + * operations that work in the common case. It does so with small and + * (eventually) nonvirtual, inlinable methods. TBufferBase is an abstract + * class. Subclasses are expected to define the "slow path" operations + * that have to be done when the buffers are full or empty. + * + */ +class TBufferBase : public TVirtualTransport { + + public: + + /** + * Fast-path read. + * + * When we have enough data buffered to fulfill the read, we can satisfy it + * with a single memcpy, then adjust our internal pointers. If the buffer + * is empty, we call out to our slow path, implemented by a subclass. + * This method is meant to eventually be nonvirtual and inlinable. + */ + uint32_t read(uint8_t* buf, uint32_t len) { + uint8_t* new_rBase = rBase_ + len; + if (TDB_LIKELY(new_rBase <= rBound_)) { + std::memcpy(buf, rBase_, len); + rBase_ = new_rBase; + return len; + } + return readSlow(buf, len); + } + + /** + * Shortcutted version of readAll. + */ + uint32_t readAll(uint8_t* buf, uint32_t len) { + uint8_t* new_rBase = rBase_ + len; + if (TDB_LIKELY(new_rBase <= rBound_)) { + std::memcpy(buf, rBase_, len); + rBase_ = new_rBase; + return len; + } + return apache::thrift::transport::readAll(*this, buf, len); + } + + /** + * Fast-path write. + * + * When we have enough empty space in our buffer to accomodate the write, we + * can satisfy it with a single memcpy, then adjust our internal pointers. + * If the buffer is full, we call out to our slow path, implemented by a + * subclass. This method is meant to eventually be nonvirtual and + * inlinable. + */ + void write(const uint8_t* buf, uint32_t len) { + uint8_t* new_wBase = wBase_ + len; + if (TDB_LIKELY(new_wBase <= wBound_)) { + std::memcpy(wBase_, buf, len); + wBase_ = new_wBase; + return; + } + writeSlow(buf, len); + } + + /** + * Fast-path borrow. A lot like the fast-path read. + */ + const uint8_t* borrow(uint8_t* buf, uint32_t* len) { + if (TDB_LIKELY(static_cast(*len) <= rBound_ - rBase_)) { + // With strict aliasing, writing to len shouldn't force us to + // refetch rBase_ from memory. TODO(dreiss): Verify this. + *len = static_cast(rBound_ - rBase_); + return rBase_; + } + return borrowSlow(buf, len); + } + + /** + * Consume doesn't require a slow path. + */ + void consume(uint32_t len) { + if (TDB_LIKELY(static_cast(len) <= rBound_ - rBase_)) { + rBase_ += len; + } else { + throw TTransportException(TTransportException::BAD_ARGS, + "consume did not follow a borrow."); + } + } + + + protected: + + /// Slow path read. + virtual uint32_t readSlow(uint8_t* buf, uint32_t len) = 0; + + /// Slow path write. + virtual void writeSlow(const uint8_t* buf, uint32_t len) = 0; + + /** + * Slow path borrow. + * + * POSTCONDITION: return == NULL || rBound_ - rBase_ >= *len + */ + virtual const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len) = 0; + + /** + * Trivial constructor. + * + * Initialize pointers safely. Constructing is not a very + * performance-sensitive operation, so it is okay to just leave it to + * the concrete class to set up pointers correctly. + */ + TBufferBase() + : rBase_(NULL) + , rBound_(NULL) + , wBase_(NULL) + , wBound_(NULL) + {} + + /// Convenience mutator for setting the read buffer. + void setReadBuffer(uint8_t* buf, uint32_t len) { + rBase_ = buf; + rBound_ = buf+len; + } + + /// Convenience mutator for setting the write buffer. + void setWriteBuffer(uint8_t* buf, uint32_t len) { + wBase_ = buf; + wBound_ = buf+len; + } + + virtual ~TBufferBase() {} + + /// Reads begin here. + uint8_t* rBase_; + /// Reads may extend to just before here. + uint8_t* rBound_; + + /// Writes begin here. + uint8_t* wBase_; + /// Writes may extend to just before here. + uint8_t* wBound_; +}; + + +/** + * Buffered transport. For reads it will read more data than is requested + * and will serve future data out of a local buffer. For writes, data is + * stored to an in memory buffer before being written out. + * + */ +class TBufferedTransport + : public TVirtualTransport { + public: + + static const int DEFAULT_BUFFER_SIZE = 512; + + /// Use default buffer sizes. + TBufferedTransport(boost::shared_ptr transport) + : transport_(transport) + , rBufSize_(DEFAULT_BUFFER_SIZE) + , wBufSize_(DEFAULT_BUFFER_SIZE) + , rBuf_(new uint8_t[rBufSize_]) + , wBuf_(new uint8_t[wBufSize_]) + { + initPointers(); + } + + /// Use specified buffer sizes. + TBufferedTransport(boost::shared_ptr transport, uint32_t sz) + : transport_(transport) + , rBufSize_(sz) + , wBufSize_(sz) + , rBuf_(new uint8_t[rBufSize_]) + , wBuf_(new uint8_t[wBufSize_]) + { + initPointers(); + } + + /// Use specified read and write buffer sizes. + TBufferedTransport(boost::shared_ptr transport, uint32_t rsz, uint32_t wsz) + : transport_(transport) + , rBufSize_(rsz) + , wBufSize_(wsz) + , rBuf_(new uint8_t[rBufSize_]) + , wBuf_(new uint8_t[wBufSize_]) + { + initPointers(); + } + + void open() { + transport_->open(); + } + + bool isOpen() { + return transport_->isOpen(); + } + + bool peek() { + if (rBase_ == rBound_) { + setReadBuffer(rBuf_.get(), transport_->read(rBuf_.get(), rBufSize_)); + } + return (rBound_ > rBase_); + } + + void close() { + flush(); + transport_->close(); + } + + virtual uint32_t readSlow(uint8_t* buf, uint32_t len); + + virtual void writeSlow(const uint8_t* buf, uint32_t len); + + void flush(); + + + /** + * The following behavior is currently implemented by TBufferedTransport, + * but that may change in a future version: + * 1/ If len is at most rBufSize_, borrow will never return NULL. + * Depending on the underlying transport, it could throw an exception + * or hang forever. + * 2/ Some borrow requests may copy bytes internally. However, + * if len is at most rBufSize_/2, none of the copied bytes + * will ever have to be copied again. For optimial performance, + * stay under this limit. + */ + virtual const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len); + + boost::shared_ptr getUnderlyingTransport() { + return transport_; + } + + /* + * TVirtualTransport provides a default implementation of readAll(). + * We want to use the TBufferBase version instead. + */ + uint32_t readAll(uint8_t* buf, uint32_t len) { + return TBufferBase::readAll(buf, len); + } + + protected: + void initPointers() { + setReadBuffer(rBuf_.get(), 0); + setWriteBuffer(wBuf_.get(), wBufSize_); + // Write size never changes. + } + + boost::shared_ptr transport_; + + uint32_t rBufSize_; + uint32_t wBufSize_; + boost::scoped_array rBuf_; + boost::scoped_array wBuf_; +}; + + +/** + * Wraps a transport into a buffered one. + * + */ +class TBufferedTransportFactory : public TTransportFactory { + public: + TBufferedTransportFactory() {} + + virtual ~TBufferedTransportFactory() {} + + /** + * Wraps the transport into a buffered one. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr trans) { + return boost::shared_ptr(new TBufferedTransport(trans)); + } + +}; + + +/** + * Framed transport. All writes go into an in-memory buffer until flush is + * called, at which point the transport writes the length of the entire + * binary chunk followed by the data payload. This allows the receiver on the + * other end to always do fixed-length reads. + * + */ +class TFramedTransport + : public TVirtualTransport { + public: + + static const int DEFAULT_BUFFER_SIZE = 512; + + /// Use default buffer sizes. + TFramedTransport(boost::shared_ptr transport) + : transport_(transport) + , rBufSize_(0) + , wBufSize_(DEFAULT_BUFFER_SIZE) + , rBuf_() + , wBuf_(new uint8_t[wBufSize_]) + { + initPointers(); + } + + TFramedTransport(boost::shared_ptr transport, uint32_t sz) + : transport_(transport) + , rBufSize_(0) + , wBufSize_(sz) + , rBuf_() + , wBuf_(new uint8_t[wBufSize_]) + { + initPointers(); + } + + void open() { + transport_->open(); + } + + bool isOpen() { + return transport_->isOpen(); + } + + bool peek() { + return (rBase_ < rBound_) || transport_->peek(); + } + + void close() { + flush(); + transport_->close(); + } + + virtual uint32_t readSlow(uint8_t* buf, uint32_t len); + + virtual void writeSlow(const uint8_t* buf, uint32_t len); + + virtual void flush(); + + uint32_t readEnd(); + + uint32_t writeEnd(); + + const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len); + + boost::shared_ptr getUnderlyingTransport() { + return transport_; + } + + /* + * TVirtualTransport provides a default implementation of readAll(). + * We want to use the TBufferBase version instead. + */ + uint32_t readAll(uint8_t* buf, uint32_t len) { + return TBufferBase::readAll(buf,len); + } + + protected: + /** + * Reads a frame of input from the underlying stream. + * + * Returns true if a frame was read successfully, or false on EOF. + * (Raises a TTransportException if EOF occurs after a partial frame.) + */ + bool readFrame(); + + void initPointers() { + setReadBuffer(NULL, 0); + setWriteBuffer(wBuf_.get(), wBufSize_); + + // Pad the buffer so we can insert the size later. + int32_t pad = 0; + this->write((uint8_t*)&pad, sizeof(pad)); + } + + boost::shared_ptr transport_; + + uint32_t rBufSize_; + uint32_t wBufSize_; + boost::scoped_array rBuf_; + boost::scoped_array wBuf_; +}; + +/** + * Wraps a transport into a framed one. + * + */ +class TFramedTransportFactory : public TTransportFactory { + public: + TFramedTransportFactory() {} + + virtual ~TFramedTransportFactory() {} + + /** + * Wraps the transport into a framed one. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr trans) { + return boost::shared_ptr(new TFramedTransport(trans)); + } + +}; + + +/** + * A memory buffer is a tranpsort that simply reads from and writes to an + * in memory buffer. Anytime you call write on it, the data is simply placed + * into a buffer, and anytime you call read, data is read from that buffer. + * + * The buffers are allocated using C constructs malloc,realloc, and the size + * doubles as necessary. We've considered using scoped + * + */ +class TMemoryBuffer : public TVirtualTransport { + private: + + // Common initialization done by all constructors. + void initCommon(uint8_t* buf, uint32_t size, bool owner, uint32_t wPos) { + if (buf == NULL && size != 0) { + assert(owner); + buf = (uint8_t*)std::malloc(size); + if (buf == NULL) { + throw std::bad_alloc(); + } + } + + buffer_ = buf; + bufferSize_ = size; + + rBase_ = buffer_; + rBound_ = buffer_ + wPos; + // TODO(dreiss): Investigate NULL-ing this if !owner. + wBase_ = buffer_ + wPos; + wBound_ = buffer_ + bufferSize_; + + owner_ = owner; + + // rBound_ is really an artifact. In principle, it should always be + // equal to wBase_. We update it in a few places (computeRead, etc.). + } + + public: + static const uint32_t defaultSize = 1024; + + /** + * This enum specifies how a TMemoryBuffer should treat + * memory passed to it via constructors or resetBuffer. + * + * OBSERVE: + * TMemoryBuffer will simply store a pointer to the memory. + * It is the callers responsibility to ensure that the pointer + * remains valid for the lifetime of the TMemoryBuffer, + * and that it is properly cleaned up. + * Note that no data can be written to observed buffers. + * + * COPY: + * TMemoryBuffer will make an internal copy of the buffer. + * The caller has no responsibilities. + * + * TAKE_OWNERSHIP: + * TMemoryBuffer will become the "owner" of the buffer, + * and will be responsible for freeing it. + * The membory must have been allocated with malloc. + */ + enum MemoryPolicy + { OBSERVE = 1 + , COPY = 2 + , TAKE_OWNERSHIP = 3 + }; + + /** + * Construct a TMemoryBuffer with a default-sized buffer, + * owned by the TMemoryBuffer object. + */ + TMemoryBuffer() { + initCommon(NULL, defaultSize, true, 0); + } + + /** + * Construct a TMemoryBuffer with a buffer of a specified size, + * owned by the TMemoryBuffer object. + * + * @param sz The initial size of the buffer. + */ + TMemoryBuffer(uint32_t sz) { + initCommon(NULL, sz, true, 0); + } + + /** + * Construct a TMemoryBuffer with buf as its initial contents. + * + * @param buf The initial contents of the buffer. + * Note that, while buf is a non-const pointer, + * TMemoryBuffer will not write to it if policy == OBSERVE, + * so it is safe to const_cast(whatever). + * @param sz The size of @c buf. + * @param policy See @link MemoryPolicy @endlink . + */ + TMemoryBuffer(uint8_t* buf, uint32_t sz, MemoryPolicy policy = OBSERVE) { + if (buf == NULL && sz != 0) { + throw TTransportException(TTransportException::BAD_ARGS, + "TMemoryBuffer given null buffer with non-zero size."); + } + + switch (policy) { + case OBSERVE: + case TAKE_OWNERSHIP: + initCommon(buf, sz, policy == TAKE_OWNERSHIP, sz); + break; + case COPY: + initCommon(NULL, sz, true, 0); + this->write(buf, sz); + break; + default: + throw TTransportException(TTransportException::BAD_ARGS, + "Invalid MemoryPolicy for TMemoryBuffer"); + } + } + + ~TMemoryBuffer() { + if (owner_) { + std::free(buffer_); + } + } + + bool isOpen() { + return true; + } + + bool peek() { + return (rBase_ < wBase_); + } + + void open() {} + + void close() {} + + // TODO(dreiss): Make bufPtr const. + void getBuffer(uint8_t** bufPtr, uint32_t* sz) { + *bufPtr = rBase_; + *sz = static_cast(wBase_ - rBase_); + } + + std::string getBufferAsString() { + if (buffer_ == NULL) { + return ""; + } + uint8_t* buf; + uint32_t sz; + getBuffer(&buf, &sz); + return std::string((char*)buf, (std::string::size_type)sz); + } + + void appendBufferToString(std::string& str) { + if (buffer_ == NULL) { + return; + } + uint8_t* buf; + uint32_t sz; + getBuffer(&buf, &sz); + str.append((char*)buf, sz); + } + + void resetBuffer() { + rBase_ = buffer_; + rBound_ = buffer_; + wBase_ = buffer_; + // It isn't safe to write into a buffer we don't own. + if (!owner_) { + wBound_ = wBase_; + bufferSize_ = 0; + } + } + + /// See constructor documentation. + void resetBuffer(uint8_t* buf, uint32_t sz, MemoryPolicy policy = OBSERVE) { + // Use a variant of the copy-and-swap trick for assignment operators. + // This is sub-optimal in terms of performance for two reasons: + // 1/ The constructing and swapping of the (small) values + // in the temporary object takes some time, and is not necessary. + // 2/ If policy == COPY, we allocate the new buffer before + // freeing the old one, precluding the possibility of + // reusing that memory. + // I doubt that either of these problems could be optimized away, + // but the second is probably no a common case, and the first is minor. + // I don't expect resetBuffer to be a common operation, so I'm willing to + // bite the performance bullet to make the method this simple. + + // Construct the new buffer. + TMemoryBuffer new_buffer(buf, sz, policy); + // Move it into ourself. + this->swap(new_buffer); + // Our old self gets destroyed. + } + + /// See constructor documentation. + void resetBuffer(uint32_t sz) { + // Construct the new buffer. + TMemoryBuffer new_buffer(sz); + // Move it into ourself. + this->swap(new_buffer); + // Our old self gets destroyed. + } + + std::string readAsString(uint32_t len) { + std::string str; + (void)readAppendToString(str, len); + return str; + } + + uint32_t readAppendToString(std::string& str, uint32_t len); + + // return number of bytes read + uint32_t readEnd() { + uint32_t bytes = rBase_ - buffer_; + if (rBase_ == wBase_) { + resetBuffer(); + } + return bytes; + } + + // Return number of bytes written + uint32_t writeEnd() { + return wBase_ - buffer_; + } + + uint32_t available_read() const { + // Remember, wBase_ is the real rBound_. + return static_cast(wBase_ - rBase_); + } + + uint32_t available_write() const { + return static_cast(wBound_ - wBase_); + } + + // Returns a pointer to where the client can write data to append to + // the TMemoryBuffer, and ensures the buffer is big enough to accomodate a + // write of the provided length. The returned pointer is very convenient for + // passing to read(), recv(), or similar. You must call wroteBytes() as soon + // as data is written or the buffer will not be aware that data has changed. + uint8_t* getWritePtr(uint32_t len) { + ensureCanWrite(len); + return wBase_; + } + + // Informs the buffer that the client has written 'len' bytes into storage + // that had been provided by getWritePtr(). + void wroteBytes(uint32_t len); + + /* + * TVirtualTransport provides a default implementation of readAll(). + * We want to use the TBufferBase version instead. + */ + uint32_t readAll(uint8_t* buf, uint32_t len) { + return TBufferBase::readAll(buf,len); + } + + protected: + void swap(TMemoryBuffer& that) { + using std::swap; + swap(buffer_, that.buffer_); + swap(bufferSize_, that.bufferSize_); + + swap(rBase_, that.rBase_); + swap(rBound_, that.rBound_); + swap(wBase_, that.wBase_); + swap(wBound_, that.wBound_); + + swap(owner_, that.owner_); + } + + // Make sure there's at least 'len' bytes available for writing. + void ensureCanWrite(uint32_t len); + + // Compute the position and available data for reading. + void computeRead(uint32_t len, uint8_t** out_start, uint32_t* out_give); + + uint32_t readSlow(uint8_t* buf, uint32_t len); + + void writeSlow(const uint8_t* buf, uint32_t len); + + const uint8_t* borrowSlow(uint8_t* buf, uint32_t* len); + + // Data buffer + uint8_t* buffer_; + + // Allocated buffer size + uint32_t bufferSize_; + + // Is this object the owner of the buffer? + bool owner_; + + // Don't forget to update constrctors, initCommon, and swap if + // you add new members. +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TBUFFERTRANSPORTS_H_ diff --git a/sg_agent/thrid_party/thrift/include/transport/TFDTransport.cpp b/sg_agent/thrid_party/thrift/include/transport/TFDTransport.cpp new file mode 100644 index 0000000..a47e2a4 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TFDTransport.cpp @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include + +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef _WIN32 +#include +#endif + +using namespace std; + +namespace apache { namespace thrift { namespace transport { + +void TFDTransport::close() { + if (!isOpen()) { + return; + } + + int rv = ::close(fd_); + int errno_copy = errno; + fd_ = -1; + // Have to check uncaught_exception because this is called in the destructor. + if (rv < 0 && !std::uncaught_exception()) { + throw TTransportException(TTransportException::UNKNOWN, + "TFDTransport::close()", + errno_copy); + } +} + +uint32_t TFDTransport::read(uint8_t* buf, uint32_t len) { + unsigned int maxRetries = 5; // same as the TSocket default + unsigned int retries = 0; + while (true) { + ssize_t rv = ::read(fd_, buf, len); + if (rv < 0) { + if (errno == EINTR && retries < maxRetries) { + // If interrupted, try again + ++retries; + continue; + } + int errno_copy = errno; + throw TTransportException(TTransportException::UNKNOWN, + "TFDTransport::read()", + errno_copy); + } + return rv; + } +} + +void TFDTransport::write(const uint8_t* buf, uint32_t len) { + while (len > 0) { + ssize_t rv = ::write(fd_, buf, len); + + if (rv < 0) { + int errno_copy = errno; + throw TTransportException(TTransportException::UNKNOWN, + "TFDTransport::write()", + errno_copy); + } else if (rv == 0) { + throw TTransportException(TTransportException::END_OF_FILE, + "TFDTransport::write()"); + } + + buf += rv; + len -= rv; + } +} + +}}} // apache::thrift::transport diff --git a/sg_agent/thrid_party/thrift/include/transport/TFDTransport.h b/sg_agent/thrid_party/thrift/include/transport/TFDTransport.h new file mode 100644 index 0000000..3ebad5c --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TFDTransport.h @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TFDTRANSPORT_H_ +#define _THRIFT_TRANSPORT_TFDTRANSPORT_H_ 1 + +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#include "TTransport.h" +#include "TVirtualTransport.h" + +namespace apache { namespace thrift { namespace transport { + +/** + * Dead-simple wrapper around a file descriptor. + * + */ +class TFDTransport : public TVirtualTransport { + public: + enum ClosePolicy + { NO_CLOSE_ON_DESTROY = 0 + , CLOSE_ON_DESTROY = 1 + }; + + TFDTransport(int fd, ClosePolicy close_policy = NO_CLOSE_ON_DESTROY) + : fd_(fd) + , close_policy_(close_policy) + {} + + ~TFDTransport() { + if (close_policy_ == CLOSE_ON_DESTROY) { + close(); + } + } + + bool isOpen() { return fd_ >= 0; } + + void open() {} + + void close(); + + uint32_t read(uint8_t* buf, uint32_t len); + + void write(const uint8_t* buf, uint32_t len); + + void setFD(int fd) { fd_ = fd; } + int getFD() { return fd_; } + + protected: + int fd_; + ClosePolicy close_policy_; +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TFDTRANSPORT_H_ diff --git a/sg_agent/thrid_party/thrift/include/transport/TFileTransport.cpp b/sg_agent/thrid_party/thrift/include/transport/TFileTransport.cpp new file mode 100644 index 0000000..47dc328 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TFileTransport.cpp @@ -0,0 +1,1122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "TFileTransport.h" +#include "TTransportUtils.h" + +#ifdef HAVE_PTHREAD_H +#include +#endif +#ifdef HAVE_SYS_TIME_H +#include +#else +#include +#endif +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_STRINGS_H +#include +#endif +#include +#include +#include +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#ifdef _WIN32 +#include +#endif + +namespace apache { namespace thrift { namespace transport { + +using boost::scoped_ptr; +using boost::shared_ptr; +using namespace std; +using namespace apache::thrift::protocol; +using namespace apache::thrift::concurrency; + +#ifndef HAVE_CLOCK_GETTIME + +/** + * Fake clock_gettime for systems like darwin + * + */ +#define CLOCK_REALTIME 0 +static int clock_gettime(int clk_id /*ignored*/, struct timespec *tp) { + struct timeval now; + + int rv = gettimeofday(&now, NULL); + if (rv != 0) { + return rv; + } + + tp->tv_sec = now.tv_sec; + tp->tv_nsec = now.tv_usec * 1000; + return 0; +} +#endif + +TFileTransport::TFileTransport(string path, bool readOnly) + : readState_() + , readBuff_(NULL) + , currentEvent_(NULL) + , readBuffSize_(DEFAULT_READ_BUFF_SIZE) + , readTimeout_(NO_TAIL_READ_TIMEOUT) + , chunkSize_(DEFAULT_CHUNK_SIZE) + , eventBufferSize_(DEFAULT_EVENT_BUFFER_SIZE) + , flushMaxUs_(DEFAULT_FLUSH_MAX_US) + , flushMaxBytes_(DEFAULT_FLUSH_MAX_BYTES) + , maxEventSize_(DEFAULT_MAX_EVENT_SIZE) + , maxCorruptedEvents_(DEFAULT_MAX_CORRUPTED_EVENTS) + , eofSleepTime_(DEFAULT_EOF_SLEEP_TIME_US) + , corruptedEventSleepTime_(DEFAULT_CORRUPTED_SLEEP_TIME_US) + , writerThreadIOErrorSleepTime_(DEFAULT_WRITER_THREAD_SLEEP_TIME_US) + , writerThreadId_(0) + , dequeueBuffer_(NULL) + , enqueueBuffer_(NULL) + , notFull_(&mutex_) + , notEmpty_(&mutex_) + , closing_(false) + , flushed_(&mutex_) + , forceFlush_(false) + , filename_(path) + , fd_(0) + , bufferAndThreadInitialized_(false) + , offset_(0) + , lastBadChunk_(0) + , numCorruptedEventsInChunk_(0) + , readOnly_(readOnly) +{ + openLogFile(); +} + +void TFileTransport::resetOutputFile(int fd, string filename, int64_t offset) { + filename_ = filename; + offset_ = offset; + + // check if current file is still open + if (fd_ > 0) { + // flush any events in the queue + flush(); + GlobalOutput.printf("error, current file (%s) not closed", filename_.c_str()); + if (-1 == ::close(fd_)) { + int errno_copy = errno; + GlobalOutput.perror("TFileTransport: resetOutputFile() ::close() ", errno_copy); + throw TTransportException(TTransportException::UNKNOWN, "TFileTransport: error in file close", errno_copy); + } else { + //successfully closed fd + fd_ = 0; + } + } + + if (fd) { + fd_ = fd; + } else { + // open file if the input fd is 0 + openLogFile(); + } +} + + +TFileTransport::~TFileTransport() { + // flush the buffer if a writer thread is active +#ifdef USE_BOOST_THREAD + if(writerThreadId_.get()) { +#else + if (writerThreadId_ > 0) { +#endif + // set state to closing + closing_ = true; + + // wake up the writer thread + // Since closing_ is true, it will attempt to flush all data, then exit. + notEmpty_.notify(); + +#ifdef USE_BOOST_THREAD + writerThreadId_->join(); + writerThreadId_.reset(); +#else + pthread_join(writerThreadId_, NULL); + writerThreadId_ = 0; +#endif + } + + if (dequeueBuffer_) { + delete dequeueBuffer_; + dequeueBuffer_ = NULL; + } + + if (enqueueBuffer_) { + delete enqueueBuffer_; + enqueueBuffer_ = NULL; + } + + if (readBuff_) { + delete[] readBuff_; + readBuff_ = NULL; + } + + if (currentEvent_) { + delete currentEvent_; + currentEvent_ = NULL; + } + + // close logfile + if (fd_ > 0) { + if(-1 == ::close(fd_)) { + GlobalOutput.perror("TFileTransport: ~TFileTransport() ::close() ", errno); + } else { + //successfully closed fd + fd_ = 0; + } + } +} + +bool TFileTransport::initBufferAndWriteThread() { + if (bufferAndThreadInitialized_) { + T_ERROR("%s", "Trying to double-init TFileTransport"); + return false; + } + +#ifdef USE_BOOST_THREAD + if(!writerThreadId_.get()) { + writerThreadId_ = std::auto_ptr(new boost::thread(boost::bind(startWriterThread, (void *)this))); + } +#else + if (writerThreadId_ == 0) { + if (pthread_create(&writerThreadId_, NULL, startWriterThread, (void *)this) != 0) { + T_ERROR("%s", "Could not create writer thread"); + return false; + } + } +#endif + + dequeueBuffer_ = new TFileTransportBuffer(eventBufferSize_); + enqueueBuffer_ = new TFileTransportBuffer(eventBufferSize_); + bufferAndThreadInitialized_ = true; + + return true; +} + +void TFileTransport::write(const uint8_t* buf, uint32_t len) { + if (readOnly_) { + throw TTransportException("TFileTransport: attempting to write to file opened readonly"); + } + + enqueueEvent(buf, len); +} + +void TFileTransport::enqueueEvent(const uint8_t* buf, uint32_t eventLen) { + // can't enqueue more events if file is going to close + if (closing_) { + return; + } + + // make sure that event size is valid + if ( (maxEventSize_ > 0) && (eventLen > maxEventSize_) ) { + T_ERROR("msg size is greater than max event size: %u > %u\n", eventLen, maxEventSize_); + return; + } + + if (eventLen == 0) { + T_ERROR("%s", "cannot enqueue an empty event"); + return; + } + + eventInfo* toEnqueue = new eventInfo(); + toEnqueue->eventBuff_ = (uint8_t *)std::malloc((sizeof(uint8_t) * eventLen) + 4); + if (toEnqueue->eventBuff_ == NULL) { + delete toEnqueue; + throw std::bad_alloc(); + } + // first 4 bytes is the event length + memcpy(toEnqueue->eventBuff_, (void*)(&eventLen), 4); + // actual event contents + memcpy(toEnqueue->eventBuff_ + 4, buf, eventLen); + toEnqueue->eventSize_ = eventLen + 4; + + // lock mutex + Guard g(mutex_); + + // make sure that enqueue buffer is initialized and writer thread is running + if (!bufferAndThreadInitialized_) { + if (!initBufferAndWriteThread()) { + delete toEnqueue; + return; + } + } + + // Can't enqueue while buffer is full + while (enqueueBuffer_->isFull()) { + notFull_.wait(); + } + + // We shouldn't be trying to enqueue new data while a forced flush is + // requested. (Otherwise the writer thread might not ever be able to finish + // the flush if more data keeps being enqueued.) + assert(!forceFlush_); + + // add to the buffer + if (!enqueueBuffer_->addEvent(toEnqueue)) { + delete toEnqueue; + return; + } + + // signal anybody who's waiting for the buffer to be non-empty + notEmpty_.notify(); + + // this really should be a loop where it makes sure it got flushed + // because condition variables can get triggered by the os for no reason + // it is probably a non-factor for the time being +} + +bool TFileTransport::swapEventBuffers(struct timespec* deadline) { + bool swap; + Guard g(mutex_); + + if (!enqueueBuffer_->isEmpty()) { + swap = true; + } else if (closing_) { + // even though there is no data to write, + // return immediately if the transport is closing + swap = false; + } else { + if (deadline != NULL) { + // if we were handed a deadline time struct, do a timed wait + notEmpty_.waitForTime(deadline); + } else { + // just wait until the buffer gets an item + notEmpty_.wait(); + } + + // could be empty if we timed out + swap = enqueueBuffer_->isEmpty(); + } + + if (swap) { + TFileTransportBuffer *temp = enqueueBuffer_; + enqueueBuffer_ = dequeueBuffer_; + dequeueBuffer_ = temp; + } + + + if (swap) { + notFull_.notify(); + } + + return swap; +} + + +void TFileTransport::writerThread() { + bool hasIOError = false; + + // open file if it is not open + if(!fd_) { + try { + openLogFile(); + } catch (...) { + int errno_copy = errno; + GlobalOutput.perror("TFileTransport: writerThread() openLogFile() ", errno_copy); + fd_ = 0; + hasIOError = true; + } + } + + // set the offset to the correct value (EOF) + if (!hasIOError) { + try { + seekToEnd(); + // throw away any partial events + offset_ += readState_.lastDispatchPtr_; +#ifndef _WIN32 + ftruncate(fd_, offset_); +#else + _chsize_s(fd_, offset_); +#endif + readState_.resetAllValues(); + } catch (...) { + int errno_copy = errno; + GlobalOutput.perror("TFileTransport: writerThread() initialization ", errno_copy); + hasIOError = true; + } + } + + // Figure out the next time by which a flush must take place + struct timespec ts_next_flush; + getNextFlushTime(&ts_next_flush); + uint32_t unflushed = 0; + + while (1) { + // this will only be true when the destructor is being invoked + if (closing_) { + if (hasIOError) { +#ifndef USE_BOOST_THREAD + pthread_exit(NULL); +#else + return; +#endif + } + + // Try to empty buffers before exit + if (enqueueBuffer_->isEmpty() && dequeueBuffer_->isEmpty()) { +#ifndef _WIN32 + fsync(fd_); +#endif + if (-1 == ::close(fd_)) { + int errno_copy = errno; + GlobalOutput.perror("TFileTransport: writerThread() ::close() ", errno_copy); + } else { + //fd successfully closed + fd_ = 0; + } +#ifndef USE_BOOST_THREAD + pthread_exit(NULL); +#else + return; +#endif + } + } + + if (swapEventBuffers(&ts_next_flush)) { + eventInfo* outEvent; + while (NULL != (outEvent = dequeueBuffer_->getNext())) { + // Remove an event from the buffer and write it out to disk. If there is any IO error, for instance, + // the output file is unmounted or deleted, then this event is dropped. However, the writer thread + // will: (1) sleep for a short while; (2) try to reopen the file; (3) if successful then start writing + // from the end. + + while (hasIOError) { + T_ERROR("TFileTransport: writer thread going to sleep for %d microseconds due to IO errors", writerThreadIOErrorSleepTime_); + usleep(writerThreadIOErrorSleepTime_); + if (closing_) { +#ifndef USE_BOOST_THREAD + pthread_exit(NULL); +#else + return; +#endif + } + if (!fd_) { + ::close(fd_); + fd_ = 0; + } + try { + openLogFile(); + seekToEnd(); + unflushed = 0; + hasIOError = false; + T_LOG_OPER("TFileTransport: log file %s reopened by writer thread during error recovery", filename_.c_str()); + } catch (...) { + T_ERROR("TFileTransport: unable to reopen log file %s during error recovery", filename_.c_str()); + } + } + + // sanity check on event + if ((maxEventSize_ > 0) && (outEvent->eventSize_ > maxEventSize_)) { + T_ERROR("msg size is greater than max event size: %u > %u\n", outEvent->eventSize_, maxEventSize_); + continue; + } + + // If chunking is required, then make sure that msg does not cross chunk boundary + if ((outEvent->eventSize_ > 0) && (chunkSize_ != 0)) { + // event size must be less than chunk size + if (outEvent->eventSize_ > chunkSize_) { + T_ERROR("TFileTransport: event size(%u) > chunk size(%u): skipping event", outEvent->eventSize_, chunkSize_); + continue; + } + + int64_t chunk1 = offset_/chunkSize_; + int64_t chunk2 = (offset_ + outEvent->eventSize_ - 1)/chunkSize_; + + // if adding this event will cross a chunk boundary, pad the chunk with zeros + if (chunk1 != chunk2) { + // refetch the offset to keep in sync + offset_ = lseek(fd_, 0, SEEK_CUR); + int32_t padding = (int32_t)((offset_ / chunkSize_ + 1) * chunkSize_ - offset_); + + uint8_t* zeros = new uint8_t[padding]; + memset(zeros, '\0', padding); + boost::scoped_array array(zeros); + if (-1 == ::write(fd_, zeros, padding)) { + int errno_copy = errno; + GlobalOutput.perror("TFileTransport: writerThread() error while padding zeros ", errno_copy); + hasIOError = true; + continue; + } + unflushed += padding; + offset_ += padding; + } + } + + // write the dequeued event to the file + if (outEvent->eventSize_ > 0) { + if (-1 == ::write(fd_, outEvent->eventBuff_, outEvent->eventSize_)) { + int errno_copy = errno; + GlobalOutput.perror("TFileTransport: error while writing event ", errno_copy); + hasIOError = true; + continue; + } + unflushed += outEvent->eventSize_; + offset_ += outEvent->eventSize_; + } + } + dequeueBuffer_->reset(); + } + + if (hasIOError) { + continue; + } + + // Local variable to cache the state of forceFlush_. + // + // We only want to check the value of forceFlush_ once each time around the + // loop. If we check it more than once without holding the lock the entire + // time, it could have changed state in between. This will result in us + // making inconsistent decisions. + bool forced_flush = false; + { + Guard g(mutex_); + if (forceFlush_) { + if (!enqueueBuffer_->isEmpty()) { + // If forceFlush_ is true, we need to flush all available data. + // If enqueueBuffer_ is not empty, go back to the start of the loop to + // write it out. + // + // We know the main thread is waiting on forceFlush_ to be cleared, + // so no new events will be added to enqueueBuffer_ until we clear + // forceFlush_. Therefore the next time around the loop enqueueBuffer_ + // is guaranteed to be empty. (I.e., we're guaranteed to make progress + // and clear forceFlush_ the next time around the loop.) + continue; + } + forced_flush = true; + } + } + + // determine if we need to perform an fsync + bool flush = false; + if (forced_flush || unflushed > flushMaxBytes_) { + flush = true; + } else { + struct timespec current_time; + clock_gettime(CLOCK_REALTIME, ¤t_time); + if (current_time.tv_sec > ts_next_flush.tv_sec || + (current_time.tv_sec == ts_next_flush.tv_sec && + current_time.tv_nsec > ts_next_flush.tv_nsec)) { + if (unflushed > 0) { + flush = true; + } else { + // If there is no new data since the last fsync, + // don't perform the fsync, but do reset the timer. + getNextFlushTime(&ts_next_flush); + } + } + } + + if (flush) { + // sync (force flush) file to disk +#ifndef _WIN32 + fsync(fd_); +#endif + unflushed = 0; + getNextFlushTime(&ts_next_flush); + + // notify anybody waiting for flush completion + if (forced_flush) { + Guard g(mutex_); + forceFlush_ = false; + assert(enqueueBuffer_->isEmpty()); + assert(dequeueBuffer_->isEmpty()); + flushed_.notifyAll(); + } + } + } +} + +void TFileTransport::flush() { + // file must be open for writing for any flushing to take place +#ifdef USE_BOOST_THREAD + if (!writerThreadId_.get()) { + return; + } +#else + if (writerThreadId_ <= 0) { + return; + } +#endif + // wait for flush to take place + Guard g(mutex_); + + // Indicate that we are requesting a flush + forceFlush_ = true; + // Wake up the writer thread so it will perform the flush immediately + notEmpty_.notify(); + + while (forceFlush_) { + flushed_.wait(); + } +} + + +uint32_t TFileTransport::readAll(uint8_t* buf, uint32_t len) { + uint32_t have = 0; + uint32_t get = 0; + + while (have < len) { + get = read(buf+have, len-have); + if (get <= 0) { + throw TEOFException(); + } + have += get; + } + + return have; +} + +bool TFileTransport::peek() { + // check if there is an event ready to be read + if (!currentEvent_) { + currentEvent_ = readEvent(); + } + + // did not manage to read an event from the file. This could have happened + // if the timeout expired or there was some other error + if (!currentEvent_) { + return false; + } + + // check if there is anything to read + return (currentEvent_->eventSize_ - currentEvent_->eventBuffPos_) > 0; +} + +uint32_t TFileTransport::read(uint8_t* buf, uint32_t len) { + // check if there an event is ready to be read + if (!currentEvent_) { + currentEvent_ = readEvent(); + } + + // did not manage to read an event from the file. This could have happened + // if the timeout expired or there was some other error + if (!currentEvent_) { + return 0; + } + + // read as much of the current event as possible + int32_t remaining = currentEvent_->eventSize_ - currentEvent_->eventBuffPos_; + if (remaining <= (int32_t)len) { + // copy over anything thats remaining + if (remaining > 0) { + memcpy(buf, + currentEvent_->eventBuff_ + currentEvent_->eventBuffPos_, + remaining); + } + delete(currentEvent_); + currentEvent_ = NULL; + return remaining; + } + + // read as much as possible + memcpy(buf, currentEvent_->eventBuff_ + currentEvent_->eventBuffPos_, len); + currentEvent_->eventBuffPos_ += len; + return len; +} + +// note caller is responsible for freeing returned events +eventInfo* TFileTransport::readEvent() { + int readTries = 0; + + if (!readBuff_) { + readBuff_ = new uint8_t[readBuffSize_]; + } + + while (1) { + // read from the file if read buffer is exhausted + if (readState_.bufferPtr_ == readState_.bufferLen_) { + // advance the offset pointer + offset_ += readState_.bufferLen_; + readState_.bufferLen_ = ::read(fd_, readBuff_, readBuffSize_); + // if (readState_.bufferLen_) { + // T_DEBUG_L(1, "Amount read: %u (offset: %lu)", readState_.bufferLen_, offset_); + // } + readState_.bufferPtr_ = 0; + readState_.lastDispatchPtr_ = 0; + + // read error + if (readState_.bufferLen_ == -1) { + readState_.resetAllValues(); + GlobalOutput("TFileTransport: error while reading from file"); + throw TTransportException("TFileTransport: error while reading from file"); + } else if (readState_.bufferLen_ == 0) { // EOF + // wait indefinitely if there is no timeout + if (readTimeout_ == TAIL_READ_TIMEOUT) { + usleep(eofSleepTime_); + continue; + } else if (readTimeout_ == NO_TAIL_READ_TIMEOUT) { + // reset state + readState_.resetState(0); + return NULL; + } else if (readTimeout_ > 0) { + // timeout already expired once + if (readTries > 0) { + readState_.resetState(0); + return NULL; + } else { + usleep(readTimeout_ * 1000); + readTries++; + continue; + } + } + } + } + + readTries = 0; + + // attempt to read an event from the buffer + while(readState_.bufferPtr_ < readState_.bufferLen_) { + if (readState_.readingSize_) { + if(readState_.eventSizeBuffPos_ == 0) { + if ( (offset_ + readState_.bufferPtr_)/chunkSize_ != + ((offset_ + readState_.bufferPtr_ + 3)/chunkSize_)) { + // skip one byte towards chunk boundary + // T_DEBUG_L(1, "Skipping a byte"); + readState_.bufferPtr_++; + continue; + } + } + + readState_.eventSizeBuff_[readState_.eventSizeBuffPos_++] = + readBuff_[readState_.bufferPtr_++]; + if (readState_.eventSizeBuffPos_ == 4) { + // 0 length event indicates padding + if (*((uint32_t *)(readState_.eventSizeBuff_)) == 0) { + // T_DEBUG_L(1, "Got padding"); + readState_.resetState(readState_.lastDispatchPtr_); + continue; + } + // got a valid event + readState_.readingSize_ = false; + if (readState_.event_) { + delete(readState_.event_); + } + readState_.event_ = new eventInfo(); + readState_.event_->eventSize_ = *((uint32_t *)(readState_.eventSizeBuff_)); + + // check if the event is corrupted and perform recovery if required + if (isEventCorrupted()) { + performRecovery(); + // start from the top + break; + } + } + } else { + if (!readState_.event_->eventBuff_) { + readState_.event_->eventBuff_ = new uint8_t[readState_.event_->eventSize_]; + readState_.event_->eventBuffPos_ = 0; + } + // take either the entire event or the remaining bytes in the buffer + int reclaimBuffer = min((uint32_t)(readState_.bufferLen_ - readState_.bufferPtr_), + readState_.event_->eventSize_ - readState_.event_->eventBuffPos_); + + // copy data from read buffer into event buffer + memcpy(readState_.event_->eventBuff_ + readState_.event_->eventBuffPos_, + readBuff_ + readState_.bufferPtr_, + reclaimBuffer); + + // increment position ptrs + readState_.event_->eventBuffPos_ += reclaimBuffer; + readState_.bufferPtr_ += reclaimBuffer; + + // check if the event has been read in full + if (readState_.event_->eventBuffPos_ == readState_.event_->eventSize_) { + // set the completed event to the current event + eventInfo* completeEvent = readState_.event_; + completeEvent->eventBuffPos_ = 0; + + readState_.event_ = NULL; + readState_.resetState(readState_.bufferPtr_); + + // exit criteria + return completeEvent; + } + } + } + + } +} + +bool TFileTransport::isEventCorrupted() { + // an error is triggered if: + if ( (maxEventSize_ > 0) && (readState_.event_->eventSize_ > maxEventSize_)) { + // 1. Event size is larger than user-speficied max-event size + T_ERROR("Read corrupt event. Event size(%u) greater than max event size (%u)", + readState_.event_->eventSize_, maxEventSize_); + return true; + } else if (readState_.event_->eventSize_ > chunkSize_) { + // 2. Event size is larger than chunk size + T_ERROR("Read corrupt event. Event size(%u) greater than chunk size (%u)", + readState_.event_->eventSize_, chunkSize_); + return true; + } else if( ((offset_ + readState_.bufferPtr_ - 4)/chunkSize_) != + ((offset_ + readState_.bufferPtr_ + readState_.event_->eventSize_ - 1)/chunkSize_) ) { + // 3. size indicates that event crosses chunk boundary + T_ERROR("Read corrupt event. Event crosses chunk boundary. Event size:%u Offset:%lu", + readState_.event_->eventSize_, + (offset_ + readState_.bufferPtr_ + 4)); + + return true; + } + + return false; +} + +void TFileTransport::performRecovery() { + // perform some kickass recovery + uint32_t curChunk = getCurChunk(); + if (lastBadChunk_ == curChunk) { + numCorruptedEventsInChunk_++; + } else { + lastBadChunk_ = curChunk; + numCorruptedEventsInChunk_ = 1; + } + + if (numCorruptedEventsInChunk_ < maxCorruptedEvents_) { + // maybe there was an error in reading the file from disk + // seek to the beginning of chunk and try again + seekToChunk(curChunk); + } else { + + // just skip ahead to the next chunk if we not already at the last chunk + if (curChunk != (getNumChunks() - 1)) { + seekToChunk(curChunk + 1); + } else if (readTimeout_ == TAIL_READ_TIMEOUT) { + // if tailing the file, wait until there is enough data to start + // the next chunk + while(curChunk == (getNumChunks() - 1)) { + usleep(DEFAULT_CORRUPTED_SLEEP_TIME_US); + } + seekToChunk(curChunk + 1); + } else { + // pretty hosed at this stage, rewind the file back to the last successful + // point and punt on the error + readState_.resetState(readState_.lastDispatchPtr_); + currentEvent_ = NULL; + char errorMsg[1024]; + sprintf(errorMsg, "TFileTransport: log file corrupted at offset: %lu", + (offset_ + readState_.lastDispatchPtr_)); + + GlobalOutput(errorMsg); + throw TTransportException(errorMsg); + } + } + +} + +void TFileTransport::seekToChunk(int32_t chunk) { + if (fd_ <= 0) { + throw TTransportException("File not open"); + } + + int32_t numChunks = getNumChunks(); + + // file is empty, seeking to chunk is pointless + if (numChunks == 0) { + return; + } + + // negative indicates reverse seek (from the end) + if (chunk < 0) { + chunk += numChunks; + } + + // too large a value for reverse seek, just seek to beginning + if (chunk < 0) { + T_DEBUG("%s", "Incorrect value for reverse seek. Seeking to beginning..."); + chunk = 0; + } + + // cannot seek past EOF + bool seekToEnd = false; + off_t minEndOffset = 0; + if (chunk >= numChunks) { + T_DEBUG("%s", "Trying to seek past EOF. Seeking to EOF instead..."); + seekToEnd = true; + chunk = numChunks - 1; + // this is the min offset to process events till + minEndOffset = lseek(fd_, 0, SEEK_END); + } + + off_t newOffset = off_t(chunk) * chunkSize_; + offset_ = lseek(fd_, newOffset, SEEK_SET); + readState_.resetAllValues(); + currentEvent_ = NULL; + if (offset_ == -1) { + GlobalOutput("TFileTransport: lseek error in seekToChunk"); + throw TTransportException("TFileTransport: lseek error in seekToChunk"); + } + + // seek to EOF if user wanted to go to last chunk + if (seekToEnd) { + uint32_t oldReadTimeout = getReadTimeout(); + setReadTimeout(NO_TAIL_READ_TIMEOUT); + // keep on reading unti the last event at point of seekChunk call + boost::scoped_ptr event; + while ((offset_ + readState_.bufferPtr_) < minEndOffset) { + event.reset(readEvent()); + if (event.get() == NULL) { + break; + } + } + setReadTimeout(oldReadTimeout); + } + +} + +void TFileTransport::seekToEnd() { + seekToChunk(getNumChunks()); +} + +uint32_t TFileTransport::getNumChunks() { + if (fd_ <= 0) { + return 0; + } + + struct stat f_info; + int rv = fstat(fd_, &f_info); + + if (rv < 0) { + int errno_copy = errno; + throw TTransportException(TTransportException::UNKNOWN, + "TFileTransport::getNumChunks() (fstat)", + errno_copy); + } + + if (f_info.st_size > 0) { + return ((f_info.st_size)/chunkSize_) + 1; + } + + // empty file has no chunks + return 0; +} + +uint32_t TFileTransport::getCurChunk() { + return offset_/chunkSize_; +} + +// Utility Functions +void TFileTransport::openLogFile() { +#ifndef _WIN32 + mode_t mode = readOnly_ ? S_IRUSR | S_IRGRP | S_IROTH : S_IRUSR | S_IWUSR| S_IRGRP | S_IROTH; + int flags = readOnly_ ? O_RDONLY : O_RDWR | O_CREAT | O_APPEND; + fd_ = ::open(filename_.c_str(), flags, mode); +#else + int mode = readOnly_ ? _S_IREAD : _S_IREAD | _S_IWRITE; + int flags = readOnly_ ? _O_RDONLY : _O_RDWR | _O_CREAT | _O_APPEND; + fd_ = ::_open(filename_.c_str(), flags, mode); +#endif + offset_ = 0; + + // make sure open call was successful + if(fd_ == -1) { + int errno_copy = errno; + GlobalOutput.perror("TFileTransport: openLogFile() ::open() file: " + filename_, errno_copy); + throw TTransportException(TTransportException::NOT_OPEN, filename_, errno_copy); + } + +} + +void TFileTransport::getNextFlushTime(struct timespec* ts_next_flush) { + clock_gettime(CLOCK_REALTIME, ts_next_flush); + ts_next_flush->tv_nsec += (flushMaxUs_ % 1000000) * 1000; + if (ts_next_flush->tv_nsec > 1000000000) { + ts_next_flush->tv_nsec -= 1000000000; + ts_next_flush->tv_sec += 1; + } + ts_next_flush->tv_sec += flushMaxUs_ / 1000000; +} + +TFileTransportBuffer::TFileTransportBuffer(uint32_t size) + : bufferMode_(WRITE) + , writePoint_(0) + , readPoint_(0) + , size_(size) +{ + buffer_ = new eventInfo*[size]; +} + +TFileTransportBuffer::~TFileTransportBuffer() { + if (buffer_) { + for (uint32_t i = 0; i < writePoint_; i++) { + delete buffer_[i]; + } + delete[] buffer_; + buffer_ = NULL; + } +} + +bool TFileTransportBuffer::addEvent(eventInfo *event) { + if (bufferMode_ == READ) { + GlobalOutput("Trying to write to a buffer in read mode"); + } + if (writePoint_ < size_) { + buffer_[writePoint_++] = event; + return true; + } else { + // buffer is full + return false; + } +} + +eventInfo* TFileTransportBuffer::getNext() { + if (bufferMode_ == WRITE) { + bufferMode_ = READ; + } + if (readPoint_ < writePoint_) { + return buffer_[readPoint_++]; + } else { + // no more entries + return NULL; + } +} + +void TFileTransportBuffer::reset() { + if (bufferMode_ == WRITE || writePoint_ > readPoint_) { + T_DEBUG("%s", "Resetting a buffer with unread entries"); + } + // Clean up the old entries + for (uint32_t i = 0; i < writePoint_; i++) { + delete buffer_[i]; + } + bufferMode_ = WRITE; + writePoint_ = 0; + readPoint_ = 0; +} + +bool TFileTransportBuffer::isFull() { + return writePoint_ == size_; +} + +bool TFileTransportBuffer::isEmpty() { + return writePoint_ == 0; +} + +TFileProcessor::TFileProcessor(shared_ptr processor, + shared_ptr protocolFactory, + shared_ptr inputTransport): + processor_(processor), + inputProtocolFactory_(protocolFactory), + outputProtocolFactory_(protocolFactory), + inputTransport_(inputTransport) { + + // default the output transport to a null transport (common case) + outputTransport_ = shared_ptr(new TNullTransport()); +} + +TFileProcessor::TFileProcessor(shared_ptr processor, + shared_ptr inputProtocolFactory, + shared_ptr outputProtocolFactory, + shared_ptr inputTransport): + processor_(processor), + inputProtocolFactory_(inputProtocolFactory), + outputProtocolFactory_(outputProtocolFactory), + inputTransport_(inputTransport) { + + // default the output transport to a null transport (common case) + outputTransport_ = shared_ptr(new TNullTransport()); +} + +TFileProcessor::TFileProcessor(shared_ptr processor, + shared_ptr protocolFactory, + shared_ptr inputTransport, + shared_ptr outputTransport): + processor_(processor), + inputProtocolFactory_(protocolFactory), + outputProtocolFactory_(protocolFactory), + inputTransport_(inputTransport), + outputTransport_(outputTransport) {} + +void TFileProcessor::process(uint32_t numEvents, bool tail) { + shared_ptr inputProtocol = inputProtocolFactory_->getProtocol(inputTransport_); + shared_ptr outputProtocol = outputProtocolFactory_->getProtocol(outputTransport_); + + // set the read timeout to 0 if tailing is required + int32_t oldReadTimeout = inputTransport_->getReadTimeout(); + if (tail) { + // save old read timeout so it can be restored + inputTransport_->setReadTimeout(TFileTransport::TAIL_READ_TIMEOUT); + } + + uint32_t numProcessed = 0; + while(1) { + // bad form to use exceptions for flow control but there is really + // no other way around it + try { + processor_->process(inputProtocol, outputProtocol, NULL); + numProcessed++; + if ( (numEvents > 0) && (numProcessed == numEvents)) { + return; + } + } catch (TEOFException& teof) { + if (!tail) { + break; + } + } catch (TException &te) { + cerr << te.what() << endl; + break; + } + } + + // restore old read timeout + if (tail) { + inputTransport_->setReadTimeout(oldReadTimeout); + } + +} + +void TFileProcessor::processChunk() { + shared_ptr inputProtocol = inputProtocolFactory_->getProtocol(inputTransport_); + shared_ptr outputProtocol = outputProtocolFactory_->getProtocol(outputTransport_); + + uint32_t curChunk = inputTransport_->getCurChunk(); + + while(1) { + // bad form to use exceptions for flow control but there is really + // no other way around it + try { + processor_->process(inputProtocol, outputProtocol, NULL); + if (curChunk != inputTransport_->getCurChunk()) { + break; + } + } catch (TEOFException& teof) { + break; + } catch (TException &te) { + cerr << te.what() << endl; + break; + } + } +} + +}}} // apache::thrift::transport diff --git a/sg_agent/thrid_party/thrift/include/transport/TFileTransport.h b/sg_agent/thrid_party/thrift/include/transport/TFileTransport.h new file mode 100644 index 0000000..b0e48d1 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TFileTransport.h @@ -0,0 +1,478 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TFILETRANSPORT_H_ +#define _THRIFT_TRANSPORT_TFILETRANSPORT_H_ 1 + +#include "TTransport.h" +#include "Thrift.h" +#include "TProcessor.h" + +#include +#include + +#ifdef HAVE_PTHREAD_H +#include +#endif + +#ifdef USE_BOOST_THREAD +#include +#endif + +#include +#include + +#include "concurrency/Mutex.h" +#include "concurrency/Monitor.h" + +namespace apache { namespace thrift { namespace transport { + +using apache::thrift::TProcessor; +using apache::thrift::protocol::TProtocolFactory; +using apache::thrift::concurrency::Mutex; +using apache::thrift::concurrency::Monitor; + +// Data pertaining to a single event +typedef struct eventInfo { + uint8_t* eventBuff_; + uint32_t eventSize_; + uint32_t eventBuffPos_; + + eventInfo():eventBuff_(NULL), eventSize_(0), eventBuffPos_(0){}; + ~eventInfo() { + if (eventBuff_) { + delete[] eventBuff_; + } + } +} eventInfo; + +// information about current read state +typedef struct readState { + eventInfo* event_; + + // keep track of event size + uint8_t eventSizeBuff_[4]; + uint8_t eventSizeBuffPos_; + bool readingSize_; + + // read buffer variables + int32_t bufferPtr_; + int32_t bufferLen_; + + // last successful dispatch point + int32_t lastDispatchPtr_; + + void resetState(uint32_t lastDispatchPtr) { + readingSize_ = true; + eventSizeBuffPos_ = 0; + lastDispatchPtr_ = lastDispatchPtr; + } + + void resetAllValues() { + resetState(0); + bufferPtr_ = 0; + bufferLen_ = 0; + if (event_) { + delete(event_); + } + event_ = 0; + } + + readState() { + event_ = 0; + resetAllValues(); + } + + ~readState() { + if (event_) { + delete(event_); + } + } + +} readState; + +/** + * TFileTransportBuffer - buffer class used by TFileTransport for queueing up events + * to be written to disk. Should be used in the following way: + * 1) Buffer created + * 2) Buffer written to (addEvent) + * 3) Buffer read from (getNext) + * 4) Buffer reset (reset) + * 5) Go back to 2, or destroy buffer + * + * The buffer should never be written to after it is read from, unless it is reset first. + * Note: The above rules are enforced mainly for debugging its sole client TFileTransport + * which uses the buffer in this way. + * + */ +class TFileTransportBuffer { + public: + TFileTransportBuffer(uint32_t size); + ~TFileTransportBuffer(); + + bool addEvent(eventInfo *event); + eventInfo* getNext(); + void reset(); + bool isFull(); + bool isEmpty(); + + private: + TFileTransportBuffer(); // should not be used + + enum mode { + WRITE, + READ + }; + mode bufferMode_; + + uint32_t writePoint_; + uint32_t readPoint_; + uint32_t size_; + eventInfo** buffer_; +}; + +/** + * Abstract interface for transports used to read files + */ +class TFileReaderTransport : virtual public TTransport { + public: + virtual int32_t getReadTimeout() = 0; + virtual void setReadTimeout(int32_t readTimeout) = 0; + + virtual uint32_t getNumChunks() = 0; + virtual uint32_t getCurChunk() = 0; + virtual void seekToChunk(int32_t chunk) = 0; + virtual void seekToEnd() = 0; +}; + +/** + * Abstract interface for transports used to write files + */ +class TFileWriterTransport : virtual public TTransport { + public: + virtual uint32_t getChunkSize() = 0; + virtual void setChunkSize(uint32_t chunkSize) = 0; +}; + +/** + * File implementation of a transport. Reads and writes are done to a + * file on disk. + * + */ +class TFileTransport : public TFileReaderTransport, + public TFileWriterTransport { + public: + TFileTransport(std::string path, bool readOnly=false); + ~TFileTransport(); + + // TODO: what is the correct behaviour for this? + // the log file is generally always open + bool isOpen() { + return true; + } + + void write(const uint8_t* buf, uint32_t len); + void flush(); + + uint32_t readAll(uint8_t* buf, uint32_t len); + uint32_t read(uint8_t* buf, uint32_t len); + bool peek(); + + // log-file specific functions + void seekToChunk(int32_t chunk); + void seekToEnd(); + uint32_t getNumChunks(); + uint32_t getCurChunk(); + + // for changing the output file + void resetOutputFile(int fd, std::string filename, int64_t offset); + + // Setter/Getter functions for user-controllable options + void setReadBuffSize(uint32_t readBuffSize) { + if (readBuffSize) { + readBuffSize_ = readBuffSize; + } + } + uint32_t getReadBuffSize() { + return readBuffSize_; + } + + static const int32_t TAIL_READ_TIMEOUT = -1; + static const int32_t NO_TAIL_READ_TIMEOUT = 0; + void setReadTimeout(int32_t readTimeout) { + readTimeout_ = readTimeout; + } + int32_t getReadTimeout() { + return readTimeout_; + } + + void setChunkSize(uint32_t chunkSize) { + if (chunkSize) { + chunkSize_ = chunkSize; + } + } + uint32_t getChunkSize() { + return chunkSize_; + } + + void setEventBufferSize(uint32_t bufferSize) { + if (bufferAndThreadInitialized_) { + GlobalOutput("Cannot change the buffer size after writer thread started"); + return; + } + eventBufferSize_ = bufferSize; + } + + uint32_t getEventBufferSize() { + return eventBufferSize_; + } + + void setFlushMaxUs(uint32_t flushMaxUs) { + if (flushMaxUs) { + flushMaxUs_ = flushMaxUs; + } + } + uint32_t getFlushMaxUs() { + return flushMaxUs_; + } + + void setFlushMaxBytes(uint32_t flushMaxBytes) { + if (flushMaxBytes) { + flushMaxBytes_ = flushMaxBytes; + } + } + uint32_t getFlushMaxBytes() { + return flushMaxBytes_; + } + + void setMaxEventSize(uint32_t maxEventSize) { + maxEventSize_ = maxEventSize; + } + uint32_t getMaxEventSize() { + return maxEventSize_; + } + + void setMaxCorruptedEvents(uint32_t maxCorruptedEvents) { + maxCorruptedEvents_ = maxCorruptedEvents; + } + uint32_t getMaxCorruptedEvents() { + return maxCorruptedEvents_; + } + + void setEofSleepTimeUs(uint32_t eofSleepTime) { + if (eofSleepTime) { + eofSleepTime_ = eofSleepTime; + } + } + uint32_t getEofSleepTimeUs() { + return eofSleepTime_; + } + + /* + * Override TTransport *_virt() functions to invoke our implementations. + * We cannot use TVirtualTransport to provide these, since we need to inherit + * virtually from TTransport. + */ + virtual uint32_t read_virt(uint8_t* buf, uint32_t len) { + return this->read(buf, len); + } + virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len) { + return this->readAll(buf, len); + } + virtual void write_virt(const uint8_t* buf, uint32_t len) { + this->write(buf, len); + } + + private: + // helper functions for writing to a file + void enqueueEvent(const uint8_t* buf, uint32_t eventLen); + bool swapEventBuffers(struct timespec* deadline); + bool initBufferAndWriteThread(); + + // control for writer thread + static void* startWriterThread(void* ptr) { + (((TFileTransport*)ptr)->writerThread()); + return 0; + } + void writerThread(); + + // helper functions for reading from a file + eventInfo* readEvent(); + + // event corruption-related functions + bool isEventCorrupted(); + void performRecovery(); + + // Utility functions + void openLogFile(); + void getNextFlushTime(struct timespec* ts_next_flush); + + // Class variables + readState readState_; + uint8_t* readBuff_; + eventInfo* currentEvent_; + + uint32_t readBuffSize_; + static const uint32_t DEFAULT_READ_BUFF_SIZE = 1 * 1024 * 1024; + + int32_t readTimeout_; + static const int32_t DEFAULT_READ_TIMEOUT_MS = 200; + + // size of chunks that file will be split up into + uint32_t chunkSize_; + static const uint32_t DEFAULT_CHUNK_SIZE = 16 * 1024 * 1024; + + // size of event buffers + uint32_t eventBufferSize_; + static const uint32_t DEFAULT_EVENT_BUFFER_SIZE = 10000; + + // max number of microseconds that can pass without flushing + uint32_t flushMaxUs_; + static const uint32_t DEFAULT_FLUSH_MAX_US = 3000000; + + // max number of bytes that can be written without flushing + uint32_t flushMaxBytes_; + static const uint32_t DEFAULT_FLUSH_MAX_BYTES = 1000 * 1024; + + // max event size + uint32_t maxEventSize_; + static const uint32_t DEFAULT_MAX_EVENT_SIZE = 0; + + // max number of corrupted events per chunk + uint32_t maxCorruptedEvents_; + static const uint32_t DEFAULT_MAX_CORRUPTED_EVENTS = 0; + + // sleep duration when EOF is hit + uint32_t eofSleepTime_; + static const uint32_t DEFAULT_EOF_SLEEP_TIME_US = 500 * 1000; + + // sleep duration when a corrupted event is encountered + uint32_t corruptedEventSleepTime_; + static const uint32_t DEFAULT_CORRUPTED_SLEEP_TIME_US = 1 * 1000 * 1000; + + // sleep duration in seconds when an IO error is encountered in the writer thread + uint32_t writerThreadIOErrorSleepTime_; + static const uint32_t DEFAULT_WRITER_THREAD_SLEEP_TIME_US = 60 * 1000 * 1000; + + // writer thread id +#ifdef USE_BOOST_THREAD + std::auto_ptr writerThreadId_; +#else + pthread_t writerThreadId_; +#endif + + // buffers to hold data before it is flushed. Each element of the buffer stores a msg that + // needs to be written to the file. The buffers are swapped by the writer thread. + TFileTransportBuffer *dequeueBuffer_; + TFileTransportBuffer *enqueueBuffer_; + + // conditions used to block when the buffer is full or empty + Monitor notFull_, notEmpty_; + volatile bool closing_; + + // To keep track of whether the buffer has been flushed + Monitor flushed_; + volatile bool forceFlush_; + + // Mutex that is grabbed when enqueueing and swapping the read/write buffers + Mutex mutex_; + + // File information + std::string filename_; + int fd_; + + // Whether the writer thread and buffers have been initialized + bool bufferAndThreadInitialized_; + + // Offset within the file + off_t offset_; + + // event corruption information + uint32_t lastBadChunk_; + uint32_t numCorruptedEventsInChunk_; + + bool readOnly_; +}; + +// Exception thrown when EOF is hit +class TEOFException : public TTransportException { + public: + TEOFException(): + TTransportException(TTransportException::END_OF_FILE) {}; +}; + + +// wrapper class to process events from a file containing thrift events +class TFileProcessor { + public: + /** + * Constructor that defaults output transport to null transport + * + * @param processor processes log-file events + * @param protocolFactory protocol factory + * @param inputTransport file transport + */ + TFileProcessor(boost::shared_ptr processor, + boost::shared_ptr protocolFactory, + boost::shared_ptr inputTransport); + + TFileProcessor(boost::shared_ptr processor, + boost::shared_ptr inputProtocolFactory, + boost::shared_ptr outputProtocolFactory, + boost::shared_ptr inputTransport); + + /** + * Constructor + * + * @param processor processes log-file events + * @param protocolFactory protocol factory + * @param inputTransport input file transport + * @param output output transport + */ + TFileProcessor(boost::shared_ptr processor, + boost::shared_ptr protocolFactory, + boost::shared_ptr inputTransport, + boost::shared_ptr outputTransport); + + /** + * processes events from the file + * + * @param numEvents number of events to process (0 for unlimited) + * @param tail tails the file if true + */ + void process(uint32_t numEvents, bool tail); + + /** + * process events until the end of the chunk + * + */ + void processChunk(); + + private: + boost::shared_ptr processor_; + boost::shared_ptr inputProtocolFactory_; + boost::shared_ptr outputProtocolFactory_; + boost::shared_ptr inputTransport_; + boost::shared_ptr outputTransport_; +}; + + +}}} // apache::thrift::transport + +#endif // _THRIFT_TRANSPORT_TFILETRANSPORT_H_ diff --git a/sg_agent/thrid_party/thrift/include/transport/THttpClient.cpp b/sg_agent/thrid_party/thrift/include/transport/THttpClient.cpp new file mode 100644 index 0000000..04864ce --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/THttpClient.cpp @@ -0,0 +1,114 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include + +#include +#include + +namespace apache { namespace thrift { namespace transport { + +using namespace std; + +THttpClient::THttpClient(boost::shared_ptr transport, std::string host, std::string path) : + THttpTransport(transport), host_(host), path_(path) { +} + +THttpClient::THttpClient(string host, int port, string path) : + THttpTransport(boost::shared_ptr(new TSocket(host, port))), host_(host), path_(path) { +} + +THttpClient::~THttpClient() {} + +void THttpClient::parseHeader(char* header) { + char* colon = strchr(header, ':'); + if (colon == NULL) { + return; + } + char* value = colon+1; + + if (boost::istarts_with(header, "Transfer-Encoding")) { + if (boost::iends_with(value, "chunked")) { + chunked_ = true; + } + } else if (boost::istarts_with(header, "Content-Length")) { + chunked_ = false; + contentLength_ = atoi(value); + } +} + +bool THttpClient::parseStatusLine(char* status) { + char* http = status; + + char* code = strchr(http, ' '); + if (code == NULL) { + throw TTransportException(string("Bad Status: ") + status); + } + + *code = '\0'; + while (*(code++) == ' ') {}; + + char* msg = strchr(code, ' '); + if (msg == NULL) { + throw TTransportException(string("Bad Status: ") + status); + } + *msg = '\0'; + + if (strcmp(code, "200") == 0) { + // HTTP 200 = OK, we got the response + return true; + } else if (strcmp(code, "100") == 0) { + // HTTP 100 = continue, just keep reading + return false; + } else { + throw TTransportException(string("Bad Status: ") + status); + } +} + +void THttpClient::flush() { + // Fetch the contents of the write buffer + uint8_t* buf; + uint32_t len; + writeBuffer_.getBuffer(&buf, &len); + + // Construct the HTTP header + std::ostringstream h; + h << + "POST " << path_ << " HTTP/1.1" << CRLF << + "Host: " << host_ << CRLF << + "Content-Type: application/x-thrift" << CRLF << + "Content-Length: " << len << CRLF << + "Accept: application/x-thrift" << CRLF << + "User-Agent: Thrift/" << VERSION << " (C++/THttpClient)" << CRLF << + CRLF; + string header = h.str(); + + // Write the header, then the data, then flush + transport_->write((const uint8_t*)header.c_str(), header.size()); + transport_->write(buf, len); + transport_->flush(); + + // Reset the buffer and header variables + writeBuffer_.resetBuffer(); + readHeaders_ = true; +} + +}}} // apache::thrift::transport diff --git a/sg_agent/thrid_party/thrift/include/transport/THttpClient.h b/sg_agent/thrid_party/thrift/include/transport/THttpClient.h new file mode 100644 index 0000000..142063d --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/THttpClient.h @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_THTTPCLIENT_H_ +#define _THRIFT_TRANSPORT_THTTPCLIENT_H_ 1 + +#include + +namespace apache { namespace thrift { namespace transport { + +class THttpClient : public THttpTransport { + public: + THttpClient(boost::shared_ptr transport, std::string host, std::string path=""); + + THttpClient(std::string host, int port, std::string path=""); + + virtual ~THttpClient(); + + virtual void flush(); + + protected: + + std::string host_; + std::string path_; + + virtual void parseHeader(char* header); + virtual bool parseStatusLine(char* status); + +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_THTTPCLIENT_H_ diff --git a/sg_agent/thrid_party/thrift/include/transport/THttpServer.cpp b/sg_agent/thrid_party/thrift/include/transport/THttpServer.cpp new file mode 100644 index 0000000..166c0f6 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/THttpServer.cpp @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include + +#include +#include + +namespace apache { namespace thrift { namespace transport { + +using namespace std; + +THttpServer::THttpServer(boost::shared_ptr transport) : + THttpTransport(transport) { +} + +THttpServer::~THttpServer() {} + +void THttpServer::parseHeader(char* header) { + char* colon = strchr(header, ':'); + if (colon == NULL) { + return; + } + uint32_t sz = colon - header; + char* value = colon+1; + + if (strncmp(header, "Transfer-Encoding", sz) == 0) { + if (strstr(value, "chunked") != NULL) { + chunked_ = true; + } + } else if (strncmp(header, "Content-Length", sz) == 0) { + chunked_ = false; + contentLength_ = atoi(value); + } +} + +bool THttpServer::parseStatusLine(char* status) { + char* method = status; + + char* path = strchr(method, ' '); + if (path == NULL) { + throw TTransportException(string("Bad Status: ") + status); + } + + *path = '\0'; + while (*(++path) == ' ') {}; + + char* http = strchr(path, ' '); + if (http == NULL) { + throw TTransportException(string("Bad Status: ") + status); + } + *http = '\0'; + + if (strcmp(method, "POST") == 0) { + // POST method ok, looking for content. + return true; + } + throw TTransportException(string("Bad Status (unsupported method): ") + status); +} + +void THttpServer::flush() { + // Fetch the contents of the write buffer + uint8_t* buf; + uint32_t len; + writeBuffer_.getBuffer(&buf, &len); + + // Construct the HTTP header + std::ostringstream h; + h << + "HTTP/1.1 200 OK" << CRLF << + "Date: " << getTimeRFC1123() << CRLF << + "Server: Thrift/" << VERSION << CRLF << + "Content-Type: application/x-thrift" << CRLF << + "Content-Length: " << len << CRLF << + "Connection: Keep-Alive" << CRLF << + CRLF; + string header = h.str(); + + // Write the header, then the data, then flush + transport_->write((const uint8_t*)header.c_str(), header.size()); + transport_->write(buf, len); + transport_->flush(); + + // Reset the buffer and header variables + writeBuffer_.resetBuffer(); + readHeaders_ = true; +} + +std::string THttpServer::getTimeRFC1123() +{ + static const char* Days[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; + static const char* Months[] = {"Jan","Feb","Mar", "Apr", "May", "Jun", "Jul","Aug", "Sep", "Oct","Nov","Dec"}; + char buff[128]; + time_t t = time(NULL); + tm* broken_t = gmtime(&t); + + sprintf(buff,"%s, %d %s %d %d:%d:%d GMT", + Days[broken_t->tm_wday], broken_t->tm_mday, Months[broken_t->tm_mon], + broken_t->tm_year + 1900, + broken_t->tm_hour,broken_t->tm_min,broken_t->tm_sec); + return std::string(buff); +} + +}}} // apache::thrift::transport diff --git a/sg_agent/thrid_party/thrift/include/transport/THttpServer.h b/sg_agent/thrid_party/thrift/include/transport/THttpServer.h new file mode 100644 index 0000000..6523408 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/THttpServer.h @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_THTTPSERVER_H_ +#define _THRIFT_TRANSPORT_THTTPSERVER_H_ 1 + +#include + +namespace apache { namespace thrift { namespace transport { + +class THttpServer : public THttpTransport { + public: + THttpServer(boost::shared_ptr transport); + + virtual ~THttpServer(); + + virtual void flush(); + + protected: + + void readHeaders(); + virtual void parseHeader(char* header); + virtual bool parseStatusLine(char* status); + std::string getTimeRFC1123(); + +}; + +/** + * Wraps a transport into HTTP protocol + */ +class THttpServerTransportFactory : public TTransportFactory { + public: + THttpServerTransportFactory() {} + + virtual ~THttpServerTransportFactory() {} + + /** + * Wraps the transport into a buffered one. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr trans) { + return boost::shared_ptr(new THttpServer(trans)); + } + +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_THTTPSERVER_H_ diff --git a/sg_agent/thrid_party/thrift/include/transport/THttpTransport.cpp b/sg_agent/thrid_party/thrift/include/transport/THttpTransport.cpp new file mode 100644 index 0000000..95fe207 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/THttpTransport.cpp @@ -0,0 +1,252 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include + +namespace apache { namespace thrift { namespace transport { + +using namespace std; + +// Yeah, yeah, hacky to put these here, I know. +const char* THttpTransport::CRLF = "\r\n"; +const int THttpTransport::CRLF_LEN = 2; + +THttpTransport::THttpTransport(boost::shared_ptr transport) : + transport_(transport), + readHeaders_(true), + chunked_(false), + chunkedDone_(false), + chunkSize_(0), + contentLength_(0), + httpBuf_(NULL), + httpPos_(0), + httpBufLen_(0), + httpBufSize_(1024) { + init(); +} + +void THttpTransport::init() { + httpBuf_ = (char*)std::malloc(httpBufSize_+1); + if (httpBuf_ == NULL) { + throw std::bad_alloc(); + } + httpBuf_[httpBufLen_] = '\0'; +} + +THttpTransport::~THttpTransport() { + if (httpBuf_ != NULL) { + std::free(httpBuf_); + } +} + +uint32_t THttpTransport::read(uint8_t* buf, uint32_t len) { + if (readBuffer_.available_read() == 0) { + readBuffer_.resetBuffer(); + uint32_t got = readMoreData(); + if (got == 0) { + return 0; + } + } + return readBuffer_.read(buf, len); +} + +uint32_t THttpTransport::readEnd() { + // Read any pending chunked data (footers etc.) + if (chunked_) { + while (!chunkedDone_) { + readChunked(); + } + } + return 0; +} + +uint32_t THttpTransport::readMoreData() { + uint32_t size; + + // Get more data! + refill(); + + if (readHeaders_) { + readHeaders(); + } + + if (chunked_) { + size = readChunked(); + } else { + size = readContent(contentLength_); + } + readHeaders_ = true; + return size; +} + +uint32_t THttpTransport::readChunked() { + uint32_t length = 0; + + char* line = readLine(); + uint32_t chunkSize = parseChunkSize(line); + if (chunkSize == 0) { + readChunkedFooters(); + } else { + // Read data content + length += readContent(chunkSize); + // Read trailing CRLF after content + readLine(); + } + return length; +} + +void THttpTransport::readChunkedFooters() { + // End of data, read footer lines until a blank one appears + while (true) { + char* line = readLine(); + if (strlen(line) == 0) { + chunkedDone_ = true; + break; + } + } +} + +uint32_t THttpTransport::parseChunkSize(char* line) { + char* semi = strchr(line, ';'); + if (semi != NULL) { + *semi = '\0'; + } + uint32_t size = 0; + sscanf(line, "%x", &size); + return size; +} + +uint32_t THttpTransport::readContent(uint32_t size) { + uint32_t need = size; + while (need > 0) { + uint32_t avail = httpBufLen_ - httpPos_; + if (avail == 0) { + // We have given all the data, reset position to head of the buffer + httpPos_ = 0; + httpBufLen_ = 0; + refill(); + + // Now have available however much we read + avail = httpBufLen_; + } + uint32_t give = avail; + if (need < give) { + give = need; + } + readBuffer_.write((uint8_t*)(httpBuf_+httpPos_), give); + httpPos_ += give; + need -= give; + } + return size; +} + +char* THttpTransport::readLine() { + while (true) { + char* eol = NULL; + + eol = strstr(httpBuf_+httpPos_, CRLF); + + // No CRLF yet? + if (eol == NULL) { + // Shift whatever we have now to front and refill + shift(); + refill(); + } else { + // Return pointer to next line + *eol = '\0'; + char* line = httpBuf_+httpPos_; + httpPos_ = (eol-httpBuf_) + CRLF_LEN; + return line; + } + } + +} + +void THttpTransport::shift() { + if (httpBufLen_ > httpPos_) { + // Shift down remaining data and read more + uint32_t length = httpBufLen_ - httpPos_; + memmove(httpBuf_, httpBuf_+httpPos_, length); + httpBufLen_ = length; + } else { + httpBufLen_ = 0; + } + httpPos_ = 0; + httpBuf_[httpBufLen_] = '\0'; +} + +void THttpTransport::refill() { + uint32_t avail = httpBufSize_ - httpBufLen_; + if (avail <= (httpBufSize_ / 4)) { + httpBufSize_ *= 2; + httpBuf_ = (char*)std::realloc(httpBuf_, httpBufSize_+1); + if (httpBuf_ == NULL) { + throw std::bad_alloc(); + } + } + + // Read more data + uint32_t got = transport_->read((uint8_t*)(httpBuf_+httpBufLen_), httpBufSize_-httpBufLen_); + httpBufLen_ += got; + httpBuf_[httpBufLen_] = '\0'; + + if (got == 0) { + throw TTransportException("Could not refill buffer"); + } +} + +void THttpTransport::readHeaders() { + // Initialize headers state variables + contentLength_ = 0; + chunked_ = false; + chunkedDone_ = false; + chunkSize_ = 0; + + // Control state flow + bool statusLine = true; + bool finished = false; + + // Loop until headers are finished + while (true) { + char* line = readLine(); + + if (strlen(line) == 0) { + if (finished) { + readHeaders_ = false; + return; + } else { + // Must have been an HTTP 100, keep going for another status line + statusLine = true; + } + } else { + if (statusLine) { + statusLine = false; + finished = parseStatusLine(line); + } else { + parseHeader(line); + } + } + } +} + +void THttpTransport::write(const uint8_t* buf, uint32_t len) { + writeBuffer_.write(buf, len); +} + +}}} diff --git a/sg_agent/thrid_party/thrift/include/transport/THttpTransport.h b/sg_agent/thrid_party/thrift/include/transport/THttpTransport.h new file mode 100644 index 0000000..977c65f --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/THttpTransport.h @@ -0,0 +1,107 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_THTTPTRANSPORT_H_ +#define _THRIFT_TRANSPORT_THTTPTRANSPORT_H_ 1 + +#include +#include "TVirtualTransport.h" + +namespace apache { namespace thrift { namespace transport { + +/** + * HTTP implementation of the thrift transport. This was irritating + * to write, but the alternatives in C++ land are daunting. Linking CURL + * requires 23 dynamic libraries last time I checked (WTF?!?). All we have + * here is a VERY basic HTTP/1.1 client which supports HTTP 100 Continue, + * chunked transfer encoding, keepalive, etc. Tested against Apache. + */ +class THttpTransport : public TVirtualTransport { + public: + THttpTransport(boost::shared_ptr transport); + + virtual ~THttpTransport(); + + void open() { + transport_->open(); + } + + bool isOpen() { + return transport_->isOpen(); + } + + bool peek() { + return transport_->peek(); + } + + void close() { + transport_->close(); + } + + uint32_t read(uint8_t* buf, uint32_t len); + + uint32_t readEnd(); + + void write(const uint8_t* buf, uint32_t len); + + virtual void flush() = 0; + + protected: + + boost::shared_ptr transport_; + + TMemoryBuffer writeBuffer_; + TMemoryBuffer readBuffer_; + + bool readHeaders_; + bool chunked_; + bool chunkedDone_; + uint32_t chunkSize_; + uint32_t contentLength_; + + char* httpBuf_; + uint32_t httpPos_; + uint32_t httpBufLen_; + uint32_t httpBufSize_; + + virtual void init(); + + uint32_t readMoreData(); + char* readLine(); + + void readHeaders(); + virtual void parseHeader(char* header) = 0; + virtual bool parseStatusLine(char* status) = 0; + + uint32_t readChunked(); + void readChunkedFooters(); + uint32_t parseChunkSize(char* line); + + uint32_t readContent(uint32_t size); + + void refill(); + void shift(); + + static const char* CRLF; + static const int CRLF_LEN; +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_THTTPCLIENT_H_ diff --git a/sg_agent/thrid_party/thrift/include/transport/TSSLServerSocket.cpp b/sg_agent/thrid_party/thrift/include/transport/TSSLServerSocket.cpp new file mode 100644 index 0000000..8e06f30 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TSSLServerSocket.cpp @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "TSSLServerSocket.h" +#include "TSSLSocket.h" + +namespace apache { namespace thrift { namespace transport { + +using namespace boost; + +/** + * SSL server socket implementation. + */ +TSSLServerSocket::TSSLServerSocket(int port, + shared_ptr factory): + TServerSocket(port), factory_(factory) { + factory_->server(true); +} + +TSSLServerSocket::TSSLServerSocket(int port, int sendTimeout, int recvTimeout, + shared_ptr factory): + TServerSocket(port, sendTimeout, recvTimeout), + factory_(factory) { + factory_->server(true); +} + +shared_ptr TSSLServerSocket::createSocket(int client) { + return factory_->createSocket(client); +} + +}}} diff --git a/sg_agent/thrid_party/thrift/include/transport/TSSLServerSocket.h b/sg_agent/thrid_party/thrift/include/transport/TSSLServerSocket.h new file mode 100644 index 0000000..a4e659d --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TSSLServerSocket.h @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TSSLSERVERSOCKET_H_ +#define _THRIFT_TRANSPORT_TSSLSERVERSOCKET_H_ 1 + +#include +#include "TServerSocket.h" + +namespace apache { namespace thrift { namespace transport { + +class TSSLSocketFactory; + +/** + * Server socket that accepts SSL connections. + */ +class TSSLServerSocket: public TServerSocket { + public: + /** + * Constructor. + * + * @param port Listening port + * @param factory SSL socket factory implementation + */ + TSSLServerSocket(int port, boost::shared_ptr factory); + /** + * Constructor. + * + * @param port Listening port + * @param sendTimeout Socket send timeout + * @param recvTimeout Socket receive timeout + * @param factory SSL socket factory implementation + */ + TSSLServerSocket(int port, int sendTimeout, int recvTimeout, + boost::shared_ptr factory); + protected: + boost::shared_ptr createSocket(int socket); + boost::shared_ptr factory_; +}; + +}}} + +#endif diff --git a/sg_agent/thrid_party/thrift/include/transport/TSSLSocket.cpp b/sg_agent/thrid_party/thrift/include/transport/TSSLSocket.cpp new file mode 100755 index 0000000..522d293 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TSSLSocket.cpp @@ -0,0 +1,670 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#ifdef HAVE_ARPA_INET_H +#include +#endif +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include "concurrency/Mutex.h" +#include "TSSLSocket.h" + +#define OPENSSL_VERSION_NO_THREAD_ID 0x10000000L + +using namespace std; +using namespace boost; +using namespace apache::thrift::concurrency; + +struct CRYPTO_dynlock_value { + Mutex mutex; +}; + +namespace apache { namespace thrift { namespace transport { + + +static void buildErrors(string& message, int error = 0); +static bool matchName(const char* host, const char* pattern, int size); +static char uppercase(char c); + +// SSLContext implementation +SSLContext::SSLContext() { + ctx_ = SSL_CTX_new(TLSv1_method()); + if (ctx_ == NULL) { + string errors; + buildErrors(errors); + throw TSSLException("SSL_CTX_new: " + errors); + } + SSL_CTX_set_mode(ctx_, SSL_MODE_AUTO_RETRY); +} + +SSLContext::~SSLContext() { + if (ctx_ != NULL) { + SSL_CTX_free(ctx_); + ctx_ = NULL; + } +} + +SSL* SSLContext::createSSL() { + SSL* ssl = SSL_new(ctx_); + if (ssl == NULL) { + string errors; + buildErrors(errors); + throw TSSLException("SSL_new: " + errors); + } + return ssl; +} + +// TSSLSocket implementation +TSSLSocket::TSSLSocket(boost::shared_ptr ctx): + TSocket(), server_(false), ssl_(NULL), ctx_(ctx) { +} + +TSSLSocket::TSSLSocket(boost::shared_ptr ctx, int socket): + TSocket(socket), server_(false), ssl_(NULL), ctx_(ctx) { +} + +TSSLSocket::TSSLSocket(boost::shared_ptr ctx, string host, int port): + TSocket(host, port), server_(false), ssl_(NULL), ctx_(ctx) { +} + +TSSLSocket::~TSSLSocket() { + close(); +} + +bool TSSLSocket::isOpen() { + if (ssl_ == NULL || !TSocket::isOpen()) { + return false; + } + int shutdown = SSL_get_shutdown(ssl_); + bool shutdownReceived = (shutdown & SSL_RECEIVED_SHUTDOWN); + bool shutdownSent = (shutdown & SSL_SENT_SHUTDOWN); + if (shutdownReceived && shutdownSent) { + return false; + } + return true; +} + +bool TSSLSocket::peek() { + if (!isOpen()) { + return false; + } + checkHandshake(); + int rc; + uint8_t byte; + rc = SSL_peek(ssl_, &byte, 1); + if (rc < 0) { + int errno_copy = errno; + string errors; + buildErrors(errors, errno_copy); + throw TSSLException("SSL_peek: " + errors); + } + if (rc == 0) { + ERR_clear_error(); + } + return (rc > 0); +} + +void TSSLSocket::open() { + if (isOpen() || server()) { + throw TTransportException(TTransportException::BAD_ARGS); + } + TSocket::open(); +} + +void TSSLSocket::close() { + if (ssl_ != NULL) { + int rc = SSL_shutdown(ssl_); + if (rc == 0) { + rc = SSL_shutdown(ssl_); + } + if (rc < 0) { + int errno_copy = errno; + string errors; + buildErrors(errors, errno_copy); + GlobalOutput(("SSL_shutdown: " + errors).c_str()); + } + SSL_free(ssl_); + ssl_ = NULL; + ERR_remove_state(0); + } + TSocket::close(); +} + +uint32_t TSSLSocket::read(uint8_t* buf, uint32_t len) { + checkHandshake(); + int32_t bytes = 0; + for (int32_t retries = 0; retries < maxRecvRetries_; retries++){ + bytes = SSL_read(ssl_, buf, len); + if (bytes >= 0) + break; + int errno_copy = errno; + if (SSL_get_error(ssl_, bytes) == SSL_ERROR_SYSCALL) { + if (ERR_get_error() == 0 && errno_copy == EINTR) { + continue; + } + } + string errors; + buildErrors(errors, errno_copy); + throw TSSLException("SSL_read: " + errors); + } + return bytes; +} + +void TSSLSocket::write(const uint8_t* buf, uint32_t len) { + checkHandshake(); + // loop in case SSL_MODE_ENABLE_PARTIAL_WRITE is set in SSL_CTX. + uint32_t written = 0; + while (written < len) { + int32_t bytes = SSL_write(ssl_, &buf[written], len - written); + if (bytes <= 0) { + int errno_copy = errno; + string errors; + buildErrors(errors, errno_copy); + throw TSSLException("SSL_write: " + errors); + } + written += bytes; + } +} + +void TSSLSocket::flush() { + // Don't throw exception if not open. Thrift servers close socket twice. + if (ssl_ == NULL) { + return; + } + checkHandshake(); + BIO* bio = SSL_get_wbio(ssl_); + if (bio == NULL) { + throw TSSLException("SSL_get_wbio returns NULL"); + } + if (BIO_flush(bio) != 1) { + int errno_copy = errno; + string errors; + buildErrors(errors, errno_copy); + throw TSSLException("BIO_flush: " + errors); + } +} + +void TSSLSocket::checkHandshake() { + if (!TSocket::isOpen()) { + throw TTransportException(TTransportException::NOT_OPEN); + } + if (ssl_ != NULL) { + return; + } + ssl_ = ctx_->createSSL(); + SSL_set_fd(ssl_, socket_); + int rc; + if (server()) { + rc = SSL_accept(ssl_); + } else { + rc = SSL_connect(ssl_); + } + if (rc <= 0) { + int errno_copy = errno; + string fname(server() ? "SSL_accept" : "SSL_connect"); + string errors; + buildErrors(errors, errno_copy); + throw TSSLException(fname + ": " + errors); + } + authorize(); +} + +void TSSLSocket::authorize() { + int rc = SSL_get_verify_result(ssl_); + if (rc != X509_V_OK) { // verify authentication result + throw TSSLException(string("SSL_get_verify_result(), ") + + X509_verify_cert_error_string(rc)); + } + + X509* cert = SSL_get_peer_certificate(ssl_); + if (cert == NULL) { + // certificate is not present + if (SSL_get_verify_mode(ssl_) & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) { + throw TSSLException("authorize: required certificate not present"); + } + // certificate was optional: didn't intend to authorize remote + if (server() && access_ != NULL) { + throw TSSLException("authorize: certificate required for authorization"); + } + return; + } + // certificate is present + if (access_ == NULL) { + X509_free(cert); + return; + } + // both certificate and access manager are present + + string host; + sockaddr_storage sa; + socklen_t saLength = sizeof(sa); + + if (getpeername(socket_, (sockaddr*)&sa, &saLength) != 0) { + sa.ss_family = AF_UNSPEC; + } + + AccessManager::Decision decision = access_->verify(sa); + + if (decision != AccessManager::SKIP) { + X509_free(cert); + if (decision != AccessManager::ALLOW) { + throw TSSLException("authorize: access denied based on remote IP"); + } + return; + } + + // extract subjectAlternativeName + STACK_OF(GENERAL_NAME)* alternatives = (STACK_OF(GENERAL_NAME)*) + X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); + if (alternatives != NULL) { + const int count = sk_GENERAL_NAME_num(alternatives); + for (int i = 0; decision == AccessManager::SKIP && i < count; i++) { + const GENERAL_NAME* name = sk_GENERAL_NAME_value(alternatives, i); + if (name == NULL) { + continue; + } + char* data = (char*)ASN1_STRING_data(name->d.ia5); + int length = ASN1_STRING_length(name->d.ia5); + switch (name->type) { + case GEN_DNS: + if (host.empty()) { + host = (server() ? getPeerHost() : getHost()); + } + decision = access_->verify(host, data, length); + break; + case GEN_IPADD: + decision = access_->verify(sa, data, length); + break; + } + } + sk_GENERAL_NAME_pop_free(alternatives, GENERAL_NAME_free); + } + + if (decision != AccessManager::SKIP) { + X509_free(cert); + if (decision != AccessManager::ALLOW) { + throw TSSLException("authorize: access denied"); + } + return; + } + + // extract commonName + X509_NAME* name = X509_get_subject_name(cert); + if (name != NULL) { + X509_NAME_ENTRY* entry; + unsigned char* utf8; + int last = -1; + while (decision == AccessManager::SKIP) { + last = X509_NAME_get_index_by_NID(name, NID_commonName, last); + if (last == -1) + break; + entry = X509_NAME_get_entry(name, last); + if (entry == NULL) + continue; + ASN1_STRING* common = X509_NAME_ENTRY_get_data(entry); + int size = ASN1_STRING_to_UTF8(&utf8, common); + if (host.empty()) { + host = (server() ? getHost() : getHost()); + } + decision = access_->verify(host, (char*)utf8, size); + OPENSSL_free(utf8); + } + } + X509_free(cert); + if (decision != AccessManager::ALLOW) { + throw TSSLException("authorize: cannot authorize peer"); + } +} + +// TSSLSocketFactory implementation +bool TSSLSocketFactory::initialized = false; +uint64_t TSSLSocketFactory::count_ = 0; +Mutex TSSLSocketFactory::mutex_; + +TSSLSocketFactory::TSSLSocketFactory(): server_(false) { + Guard guard(mutex_); + if (count_ == 0) { + initializeOpenSSL(); + randomize(); + } + count_++; + ctx_ = boost::shared_ptr(new SSLContext); +} + +TSSLSocketFactory::~TSSLSocketFactory() { + Guard guard(mutex_); + count_--; + if (count_ == 0) { + cleanupOpenSSL(); + } +} + +boost::shared_ptr TSSLSocketFactory::createSocket() { + boost::shared_ptr ssl(new TSSLSocket(ctx_)); + setup(ssl); + return ssl; +} + +boost::shared_ptr TSSLSocketFactory::createSocket(int socket) { + boost::shared_ptr ssl(new TSSLSocket(ctx_, socket)); + setup(ssl); + return ssl; +} + +boost::shared_ptr TSSLSocketFactory::createSocket(const string& host, + int port) { + boost::shared_ptr ssl(new TSSLSocket(ctx_, host, port)); + setup(ssl); + return ssl; +} + +void TSSLSocketFactory::setup(boost::shared_ptr ssl) { + ssl->server(server()); + if (access_ == NULL && !server()) { + access_ = boost::shared_ptr(new DefaultClientAccessManager); + } + if (access_ != NULL) { + ssl->access(access_); + } +} + +void TSSLSocketFactory::ciphers(const string& enable) { + int rc = SSL_CTX_set_cipher_list(ctx_->get(), enable.c_str()); + if (ERR_peek_error() != 0) { + string errors; + buildErrors(errors); + throw TSSLException("SSL_CTX_set_cipher_list: " + errors); + } + if (rc == 0) { + throw TSSLException("None of specified ciphers are supported"); + } +} + +void TSSLSocketFactory::authenticate(bool required) { + int mode; + if (required) { + mode = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | SSL_VERIFY_CLIENT_ONCE; + } else { + mode = SSL_VERIFY_NONE; + } + SSL_CTX_set_verify(ctx_->get(), mode, NULL); +} + +void TSSLSocketFactory::loadCertificate(const char* path, const char* format) { + if (path == NULL || format == NULL) { + throw TTransportException(TTransportException::BAD_ARGS, + "loadCertificateChain: either or is NULL"); + } + if (strcmp(format, "PEM") == 0) { + if (SSL_CTX_use_certificate_chain_file(ctx_->get(), path) == 0) { + int errno_copy = errno; + string errors; + buildErrors(errors, errno_copy); + throw TSSLException("SSL_CTX_use_certificate_chain_file: " + errors); + } + } else { + throw TSSLException("Unsupported certificate format: " + string(format)); + } +} + +void TSSLSocketFactory::loadPrivateKey(const char* path, const char* format) { + if (path == NULL || format == NULL) { + throw TTransportException(TTransportException::BAD_ARGS, + "loadPrivateKey: either or is NULL"); + } + if (strcmp(format, "PEM") == 0) { + if (SSL_CTX_use_PrivateKey_file(ctx_->get(), path, SSL_FILETYPE_PEM) == 0) { + int errno_copy = errno; + string errors; + buildErrors(errors, errno_copy); + throw TSSLException("SSL_CTX_use_PrivateKey_file: " + errors); + } + } +} + +void TSSLSocketFactory::loadTrustedCertificates(const char* path) { + if (path == NULL) { + throw TTransportException(TTransportException::BAD_ARGS, + "loadTrustedCertificates: is NULL"); + } + if (SSL_CTX_load_verify_locations(ctx_->get(), path, NULL) == 0) { + int errno_copy = errno; + string errors; + buildErrors(errors, errno_copy); + throw TSSLException("SSL_CTX_load_verify_locations: " + errors); + } +} + +void TSSLSocketFactory::randomize() { + RAND_poll(); +} + +void TSSLSocketFactory::overrideDefaultPasswordCallback() { + SSL_CTX_set_default_passwd_cb(ctx_->get(), passwordCallback); + SSL_CTX_set_default_passwd_cb_userdata(ctx_->get(), this); +} + +int TSSLSocketFactory::passwordCallback(char* password, + int size, + int, + void* data) { + TSSLSocketFactory* factory = (TSSLSocketFactory*)data; + string userPassword; + factory->getPassword(userPassword, size); + int length = userPassword.size(); + if (length > size) { + length = size; + } + strncpy(password, userPassword.c_str(), length); + return length; +} + +static shared_array mutexes; + +static void callbackLocking(int mode, int n, const char*, int) { + if (mode & CRYPTO_LOCK) { + mutexes[n].lock(); + } else { + mutexes[n].unlock(); + } +} + +#if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_NO_THREAD_ID) +static unsigned long callbackThreadID() { + return (unsigned long) pthread_self(); +} +#endif + +static CRYPTO_dynlock_value* dyn_create(const char*, int) { + return new CRYPTO_dynlock_value; +} + +static void dyn_lock(int mode, + struct CRYPTO_dynlock_value* lock, + const char*, int) { + if (lock != NULL) { + if (mode & CRYPTO_LOCK) { + lock->mutex.lock(); + } else { + lock->mutex.unlock(); + } + } +} + +static void dyn_destroy(struct CRYPTO_dynlock_value* lock, const char*, int) { + delete lock; +} + +void TSSLSocketFactory::initializeOpenSSL() { + if (initialized) { + return; + } + initialized = true; + SSL_library_init(); + SSL_load_error_strings(); + // static locking + mutexes = shared_array(new Mutex[::CRYPTO_num_locks()]); + if (mutexes == NULL) { + throw TTransportException(TTransportException::INTERNAL_ERROR, + "initializeOpenSSL() failed, " + "out of memory while creating mutex array"); + } +#if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_NO_THREAD_ID) + CRYPTO_set_id_callback(callbackThreadID); +#endif + CRYPTO_set_locking_callback(callbackLocking); + // dynamic locking + CRYPTO_set_dynlock_create_callback(dyn_create); + CRYPTO_set_dynlock_lock_callback(dyn_lock); + CRYPTO_set_dynlock_destroy_callback(dyn_destroy); +} + +void TSSLSocketFactory::cleanupOpenSSL() { + if (!initialized) { + return; + } + initialized = false; +#if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_NO_THREAD_ID) + CRYPTO_set_id_callback(NULL); +#endif + CRYPTO_set_locking_callback(NULL); + CRYPTO_set_dynlock_create_callback(NULL); + CRYPTO_set_dynlock_lock_callback(NULL); + CRYPTO_set_dynlock_destroy_callback(NULL); + CRYPTO_cleanup_all_ex_data(); + ERR_free_strings(); + EVP_cleanup(); + ERR_remove_state(0); + mutexes.reset(); +} + +// extract error messages from error queue +void buildErrors(string& errors, int errno_copy) { + unsigned long errorCode; + char message[256]; + + errors.reserve(512); + while ((errorCode = ERR_get_error()) != 0) { + if (!errors.empty()) { + errors += "; "; + } + const char* reason = ERR_reason_error_string(errorCode); + if (reason == NULL) { + snprintf(message, sizeof(message) - 1, "SSL error # %lu", errorCode); + reason = message; + } + errors += reason; + } + if (errors.empty()) { + if (errno_copy != 0) { + errors += TOutput::strerror_s(errno_copy); + } + } + if (errors.empty()) { + errors = "error code: " + lexical_cast(errno_copy); + } +} + +/** + * Default implementation of AccessManager + */ +Decision DefaultClientAccessManager::verify(const sockaddr_storage& sa) + throw() { + (void) sa; + return SKIP; +} + +Decision DefaultClientAccessManager::verify(const string& host, + const char* name, + int size) throw() { + if (host.empty() || name == NULL || size <= 0) { + return SKIP; + } + return (matchName(host.c_str(), name, size) ? ALLOW : SKIP); +} + +Decision DefaultClientAccessManager::verify(const sockaddr_storage& sa, + const char* data, + int size) throw() { + bool match = false; + if (sa.ss_family == AF_INET && size == sizeof(in_addr)) { + match = (memcmp(&((sockaddr_in*)&sa)->sin_addr, data, size) == 0); + } else if (sa.ss_family == AF_INET6 && size == sizeof(in6_addr)) { + match = (memcmp(&((sockaddr_in6*)&sa)->sin6_addr, data, size) == 0); + } + return (match ? ALLOW : SKIP); +} + +/** + * Match a name with a pattern. The pattern may include wildcard. A single + * wildcard "*" can match up to one component in the domain name. + * + * @param host Host name, typically the name of the remote host + * @param pattern Name retrieved from certificate + * @param size Size of "pattern" + * @return True, if "host" matches "pattern". False otherwise. + */ +bool matchName(const char* host, const char* pattern, int size) { + bool match = false; + int i = 0, j = 0; + while (i < size && host[j] != '\0') { + if (uppercase(pattern[i]) == uppercase(host[j])) { + i++; + j++; + continue; + } + if (pattern[i] == '*') { + while (host[j] != '.' && host[j] != '\0') { + j++; + } + i++; + continue; + } + break; + } + if (i == size && host[j] == '\0') { + match = true; + } + return match; + +} + +// This is to work around the Turkish locale issue, i.e., +// toupper('i') != toupper('I') if locale is "tr_TR" +char uppercase (char c) { + if ('a' <= c && c <= 'z') { + return c + ('A' - 'a'); + } + return c; +} + +}}} diff --git a/sg_agent/thrid_party/thrift/include/transport/TSSLSocket.h b/sg_agent/thrid_party/thrift/include/transport/TSSLSocket.h new file mode 100755 index 0000000..a0a1502 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TSSLSocket.h @@ -0,0 +1,315 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TSSLSOCKET_H_ +#define _THRIFT_TRANSPORT_TSSLSOCKET_H_ 1 + +#include +#include +#include +#include "concurrency/Mutex.h" +#include "TSocket.h" + +namespace apache { namespace thrift { namespace transport { + +class AccessManager; +class SSLContext; + +/** + * OpenSSL implementation for SSL socket interface. + */ +class TSSLSocket: public TSocket { + public: + ~TSSLSocket(); + /** + * TTransport interface. + */ + bool isOpen(); + bool peek(); + void open(); + void close(); + uint32_t read(uint8_t* buf, uint32_t len); + void write(const uint8_t* buf, uint32_t len); + void flush(); + /** + * Set whether to use client or server side SSL handshake protocol. + * + * @param flag Use server side handshake protocol if true. + */ + void server(bool flag) { server_ = flag; } + /** + * Determine whether the SSL socket is server or client mode. + */ + bool server() const { return server_; } + /** + * Set AccessManager. + * + * @param manager Instance of AccessManager + */ + virtual void access(boost::shared_ptr manager) { + access_ = manager; + } +protected: + /** + * Constructor. + */ + TSSLSocket(boost::shared_ptr ctx); + /** + * Constructor, create an instance of TSSLSocket given an existing socket. + * + * @param socket An existing socket + */ + TSSLSocket(boost::shared_ptr ctx, int socket); + /** + * Constructor. + * + * @param host Remote host name + * @param port Remote port number + */ + TSSLSocket(boost::shared_ptr ctx, + std::string host, + int port); + /** + * Authorize peer access after SSL handshake completes. + */ + virtual void authorize(); + /** + * Initiate SSL handshake if not already initiated. + */ + void checkHandshake(); + + bool server_; + SSL* ssl_; + boost::shared_ptr ctx_; + boost::shared_ptr access_; + friend class TSSLSocketFactory; +}; + +/** + * SSL socket factory. SSL sockets should be created via SSL factory. + */ +class TSSLSocketFactory { + public: + /** + * Constructor/Destructor + */ + TSSLSocketFactory(); + virtual ~TSSLSocketFactory(); + /** + * Create an instance of TSSLSocket with a fresh new socket. + */ + virtual boost::shared_ptr createSocket(); + /** + * Create an instance of TSSLSocket with the given socket. + * + * @param socket An existing socket. + */ + virtual boost::shared_ptr createSocket(int socket); + /** + * Create an instance of TSSLSocket. + * + * @param host Remote host to be connected to + * @param port Remote port to be connected to + */ + virtual boost::shared_ptr createSocket(const std::string& host, + int port); + /** + * Set ciphers to be used in SSL handshake process. + * + * @param ciphers A list of ciphers + */ + virtual void ciphers(const std::string& enable); + /** + * Enable/Disable authentication. + * + * @param required Require peer to present valid certificate if true + */ + virtual void authenticate(bool required); + /** + * Load server certificate. + * + * @param path Path to the certificate file + * @param format Certificate file format + */ + virtual void loadCertificate(const char* path, const char* format = "PEM"); + /** + * Load private key. + * + * @param path Path to the private key file + * @param format Private key file format + */ + virtual void loadPrivateKey(const char* path, const char* format = "PEM"); + /** + * Load trusted certificates from specified file. + * + * @param path Path to trusted certificate file + */ + virtual void loadTrustedCertificates(const char* path); + /** + * Default randomize method. + */ + virtual void randomize(); + /** + * Override default OpenSSL password callback with getPassword(). + */ + void overrideDefaultPasswordCallback(); + /** + * Set/Unset server mode. + * + * @param flag Server mode if true + */ + virtual void server(bool flag) { server_ = flag; } + /** + * Determine whether the socket is in server or client mode. + * + * @return true, if server mode, or, false, if client mode + */ + virtual bool server() const { return server_; } + /** + * Set AccessManager. + * + * @param manager The AccessManager instance + */ + virtual void access(boost::shared_ptr manager) { + access_ = manager; + } + protected: + boost::shared_ptr ctx_; + + static void initializeOpenSSL(); + static void cleanupOpenSSL(); + /** + * Override this method for custom password callback. It may be called + * multiple times at any time during a session as necessary. + * + * @param password Pass collected password to OpenSSL + * @param size Maximum length of password including NULL character + */ + virtual void getPassword(std::string& /* password */, int /* size */) {} + private: + bool server_; + boost::shared_ptr access_; + static bool initialized; + static concurrency::Mutex mutex_; + static uint64_t count_; + void setup(boost::shared_ptr ssl); + static int passwordCallback(char* password, int size, int, void* data); +}; + +/** + * SSL exception. + */ +class TSSLException: public TTransportException { + public: + TSSLException(const std::string& message): + TTransportException(TTransportException::INTERNAL_ERROR, message) {} + + virtual const char* what() const throw() { + if (message_.empty()) { + return "TSSLException"; + } else { + return message_.c_str(); + } + } +}; + +/** + * Wrap OpenSSL SSL_CTX into a class. + */ +class SSLContext { + public: + SSLContext(); + virtual ~SSLContext(); + SSL* createSSL(); + SSL_CTX* get() { return ctx_; } + private: + SSL_CTX* ctx_; +}; + +/** + * Callback interface for access control. It's meant to verify the remote host. + * It's constructed when application starts and set to TSSLSocketFactory + * instance. It's passed onto all TSSLSocket instances created by this factory + * object. + */ +class AccessManager { + public: + enum Decision { + DENY = -1, // deny access + SKIP = 0, // cannot make decision, move on to next (if any) + ALLOW = 1 // allow access + }; + /** + * Destructor + */ + virtual ~AccessManager() {} + /** + * Determine whether the peer should be granted access or not. It's called + * once after the SSL handshake completes successfully, before peer certificate + * is examined. + * + * If a valid decision (ALLOW or DENY) is returned, the peer certificate is + * not to be verified. + * + * @param sa Peer IP address + * @return True if the peer is trusted, false otherwise + */ + virtual Decision verify(const sockaddr_storage& /* sa */ ) throw() { return DENY; } + /** + * Determine whether the peer should be granted access or not. It's called + * every time a DNS subjectAltName/common name is extracted from peer's + * certificate. + * + * @param host Client mode: host name returned by TSocket::getHost() + * Server mode: host name returned by TSocket::getPeerHost() + * @param name SubjectAltName or common name extracted from peer certificate + * @param size Length of name + * @return True if the peer is trusted, false otherwise + * + * Note: The "name" parameter may be UTF8 encoded. + */ + virtual Decision verify(const std::string& /* host */, const char* /* name */, int /* size */) + throw() { return DENY; } + /** + * Determine whether the peer should be granted access or not. It's called + * every time an IP subjectAltName is extracted from peer's certificate. + * + * @param sa Peer IP address retrieved from the underlying socket + * @param data IP address extracted from certificate + * @param size Length of the IP address + * @return True if the peer is trusted, false otherwise + */ + virtual Decision verify(const sockaddr_storage& /* sa */, const char* /* data */, int /* size */) + throw() { return DENY; } +}; + +typedef AccessManager::Decision Decision; + +class DefaultClientAccessManager: public AccessManager { + public: + // AccessManager interface + Decision verify(const sockaddr_storage& sa) throw(); + Decision verify(const std::string& host, const char* name, int size) throw(); + Decision verify(const sockaddr_storage& sa, const char* data, int size) throw(); +}; + + +}}} + +#endif diff --git a/sg_agent/thrid_party/thrift/include/transport/TServerSocket.cpp b/sg_agent/thrid_party/thrift/include/transport/TServerSocket.cpp new file mode 100644 index 0000000..c4a7f7c --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TServerSocket.cpp @@ -0,0 +1,489 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_SYS_UN_H +#include +#endif +#ifdef HAVE_SYS_POLL_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "TSocket.h" +#include "TServerSocket.h" +#include + +#ifndef AF_LOCAL +#define AF_LOCAL AF_UNIX +#endif + +#ifndef SOCKOPT_CAST_T +# ifndef _WIN32 +# define SOCKOPT_CAST_T void +# else +# define SOCKOPT_CAST_T char +# endif // _WIN32 +#endif + +template +inline const SOCKOPT_CAST_T* const_cast_sockopt(const T* v) { + return reinterpret_cast(v); +} + +template +inline SOCKOPT_CAST_T* cast_sockopt(T* v) { + return reinterpret_cast(v); +} + +namespace apache { namespace thrift { namespace transport { + +using namespace std; +using boost::shared_ptr; + +TServerSocket::TServerSocket(int port) : + port_(port), + serverSocket_(-1), + acceptBacklog_(1024), + sendTimeout_(0), + recvTimeout_(0), + accTimeout_(-1), + retryLimit_(0), + retryDelay_(0), + tcpSendBuffer_(0), + tcpRecvBuffer_(0), + intSock1_(-1), + intSock2_(-1) {} + +TServerSocket::TServerSocket(int port, int sendTimeout, int recvTimeout) : + port_(port), + serverSocket_(-1), + acceptBacklog_(1024), + sendTimeout_(sendTimeout), + recvTimeout_(recvTimeout), + accTimeout_(-1), + retryLimit_(0), + retryDelay_(0), + tcpSendBuffer_(0), + tcpRecvBuffer_(0), + intSock1_(-1), + intSock2_(-1) {} + +TServerSocket::TServerSocket(string path) : + port_(0), + path_(path), + serverSocket_(-1), + acceptBacklog_(1024), + sendTimeout_(0), + recvTimeout_(0), + accTimeout_(-1), + retryLimit_(0), + retryDelay_(0), + tcpSendBuffer_(0), + tcpRecvBuffer_(0), + intSock1_(-1), + intSock2_(-1) {} + +TServerSocket::~TServerSocket() { + close(); +} + +void TServerSocket::setSendTimeout(int sendTimeout) { + sendTimeout_ = sendTimeout; +} + +void TServerSocket::setRecvTimeout(int recvTimeout) { + recvTimeout_ = recvTimeout; +} + +void TServerSocket::setAcceptTimeout(int accTimeout) { + accTimeout_ = accTimeout; +} + +void TServerSocket::setRetryLimit(int retryLimit) { + retryLimit_ = retryLimit; +} + +void TServerSocket::setRetryDelay(int retryDelay) { + retryDelay_ = retryDelay; +} + +void TServerSocket::setTcpSendBuffer(int tcpSendBuffer) { + tcpSendBuffer_ = tcpSendBuffer; +} + +void TServerSocket::setTcpRecvBuffer(int tcpRecvBuffer) { + tcpRecvBuffer_ = tcpRecvBuffer; +} + +void TServerSocket::listen() { + int sv[2]; + if (-1 == socketpair(AF_LOCAL, SOCK_STREAM, 0, sv)) { + GlobalOutput.perror("TServerSocket::listen() socketpair() ", errno); + intSock1_ = -1; + intSock2_ = -1; + } else { + intSock1_ = sv[1]; + intSock2_ = sv[0]; + } + + struct addrinfo hints, *res, *res0; + int error; + char port[sizeof("65536") + 1]; + std::memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + sprintf(port, "%d", port_); + + // Wildcard address + error = getaddrinfo(NULL, port, &hints, &res0); + if (error) { + GlobalOutput.printf("getaddrinfo %d: %s", error, gai_strerror(error)); + close(); + throw TTransportException(TTransportException::NOT_OPEN, "Could not resolve host for server socket."); + } + + // Pick the ipv6 address first since ipv4 addresses can be mapped + // into ipv6 space. + for (res = res0; res; res = res->ai_next) { + if (res->ai_family == AF_INET6 || res->ai_next == NULL) + break; + } + + if (! path_.empty()) { + serverSocket_ = socket(PF_UNIX, SOCK_STREAM, IPPROTO_IP); + } else { + serverSocket_ = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + } + + if (serverSocket_ == -1) { + int errno_copy = errno; + GlobalOutput.perror("TServerSocket::listen() socket() ", errno_copy); + close(); + throw TTransportException(TTransportException::NOT_OPEN, "Could not create server socket.", errno_copy); + } + + // Set reusaddress to prevent 2MSL delay on accept + int one = 1; + if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_REUSEADDR, + cast_sockopt(&one), sizeof(one))) { + int errno_copy = errno; + GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_REUSEADDR ", errno_copy); + close(); + throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_REUSEADDR", errno_copy); + } + + // Set TCP buffer sizes + if (tcpSendBuffer_ > 0) { + if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_SNDBUF, + cast_sockopt(&tcpSendBuffer_), sizeof(tcpSendBuffer_))) { + int errno_copy = errno; + GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_SNDBUF ", errno_copy); + close(); + throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_SNDBUF", errno_copy); + } + } + + if (tcpRecvBuffer_ > 0) { + if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_RCVBUF, + cast_sockopt(&tcpRecvBuffer_), sizeof(tcpRecvBuffer_))) { + int errno_copy = errno; + GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_RCVBUF ", errno_copy); + close(); + throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_RCVBUF", errno_copy); + } + } + + // Defer accept + #ifdef TCP_DEFER_ACCEPT + if (-1 == setsockopt(serverSocket_, SOL_SOCKET, TCP_DEFER_ACCEPT, + &one, sizeof(one))) { + int errno_copy = errno; + GlobalOutput.perror("TServerSocket::listen() setsockopt() TCP_DEFER_ACCEPT ", errno_copy); + close(); + throw TTransportException(TTransportException::NOT_OPEN, "Could not set TCP_DEFER_ACCEPT", errno_copy); + } + #endif // #ifdef TCP_DEFER_ACCEPT + + #ifdef IPV6_V6ONLY + if (res->ai_family == AF_INET6 && path_.empty()) { + int zero = 0; + if (-1 == setsockopt(serverSocket_, IPPROTO_IPV6, IPV6_V6ONLY, + cast_sockopt(&zero), sizeof(zero))) { + GlobalOutput.perror("TServerSocket::listen() IPV6_V6ONLY ", errno); + } + } + #endif // #ifdef IPV6_V6ONLY + + // Turn linger off, don't want to block on calls to close + struct linger ling = {0, 0}; + if (-1 == setsockopt(serverSocket_, SOL_SOCKET, SO_LINGER, + cast_sockopt(&ling), sizeof(ling))) { + int errno_copy = errno; + GlobalOutput.perror("TServerSocket::listen() setsockopt() SO_LINGER ", errno_copy); + close(); + throw TTransportException(TTransportException::NOT_OPEN, "Could not set SO_LINGER", errno_copy); + } + + // Unix Sockets do not need that + if (path_.empty()) { + // TCP Nodelay, speed over bandwidth + if (-1 == setsockopt(serverSocket_, IPPROTO_TCP, TCP_NODELAY, + cast_sockopt(&one), sizeof(one))) { + int errno_copy = errno; + GlobalOutput.perror("TServerSocket::listen() setsockopt() TCP_NODELAY ", errno_copy); + close(); + throw TTransportException(TTransportException::NOT_OPEN, "Could not set TCP_NODELAY", errno_copy); + } + } + + // Set NONBLOCK on the accept socket + int flags = fcntl(serverSocket_, F_GETFL, 0); + if (flags == -1) { + int errno_copy = errno; + GlobalOutput.perror("TServerSocket::listen() fcntl() F_GETFL ", errno_copy); + throw TTransportException(TTransportException::NOT_OPEN, "fcntl() failed", errno_copy); + } + + if (-1 == fcntl(serverSocket_, F_SETFL, flags | O_NONBLOCK)) { + int errno_copy = errno; + GlobalOutput.perror("TServerSocket::listen() fcntl() O_NONBLOCK ", errno_copy); + throw TTransportException(TTransportException::NOT_OPEN, "fcntl() failed", errno_copy); + } + + // prepare the port information + // we may want to try to bind more than once, since SO_REUSEADDR doesn't + // always seem to work. The client can configure the retry variables. + int retries = 0; + + if (! path_.empty()) { + +#ifndef _WIN32 + + // Unix Domain Socket + struct sockaddr_un address; + socklen_t len; + + if (path_.length() > sizeof(address.sun_path)) { + int errno_copy = errno; + GlobalOutput.perror("TSocket::listen() Unix Domain socket path too long", errno_copy); + throw TTransportException(TTransportException::NOT_OPEN, " Unix Domain socket path too long"); + } + + address.sun_family = AF_UNIX; + snprintf(address.sun_path, sizeof(address.sun_path), "%s", path_.c_str()); + len = sizeof(address); + + do { + if (0 == bind(serverSocket_, (struct sockaddr *) &address, len)) { + break; + } + // use short circuit evaluation here to only sleep if we need to + } while ((retries++ < retryLimit_) && (sleep(retryDelay_) == 0)); + } else { + do { + if (0 == bind(serverSocket_, res->ai_addr, res->ai_addrlen)) { + break; + } + // use short circuit evaluation here to only sleep if we need to + } while ((retries++ < retryLimit_) && (sleep(retryDelay_) == 0)); + + // free addrinfo + freeaddrinfo(res0); + +#else + GlobalOutput.perror("TSocket::open() Unix Domain socket path not supported on windows", -99); + throw TTransportException(TTransportException::NOT_OPEN, " Unix Domain socket path not supported"); +#endif + + } + + // throw an error if we failed to bind properly + if (retries > retryLimit_) { + char errbuf[1024]; + if (! path_.empty()) { + sprintf(errbuf, "TServerSocket::listen() PATH %s", path_.c_str()); + } + else { + sprintf(errbuf, "TServerSocket::listen() BIND %d", port_); + } + GlobalOutput(errbuf); + close(); + throw TTransportException(TTransportException::NOT_OPEN, "Could not bind"); + } + + // Call listen + if (-1 == ::listen(serverSocket_, acceptBacklog_)) { + int errno_copy = errno; + GlobalOutput.perror("TServerSocket::listen() listen() ", errno_copy); + close(); + throw TTransportException(TTransportException::NOT_OPEN, "Could not listen", errno_copy); + } + + // The socket is now listening! +} + +shared_ptr TServerSocket::acceptImpl() { + if (serverSocket_ < 0) { + throw TTransportException(TTransportException::NOT_OPEN, "TServerSocket not listening"); + } + + struct pollfd fds[2]; + + int maxEintrs = 5; + int numEintrs = 0; + + while (true) { + std::memset(fds, 0 , sizeof(fds)); + fds[0].fd = serverSocket_; + fds[0].events = POLLIN; + if (intSock2_ >= 0) { + fds[1].fd = intSock2_; + fds[1].events = POLLIN; + } + /* + TODO: if EINTR is received, we'll restart the timeout. + To be accurate, we need to fix this in the future. + */ + int ret = poll(fds, 2, accTimeout_); + + if (ret < 0) { + // error cases + if (errno == EINTR && (numEintrs++ < maxEintrs)) { + // EINTR needs to be handled manually and we can tolerate + // a certain number + continue; + } + int errno_copy = errno; + GlobalOutput.perror("TServerSocket::acceptImpl() poll() ", errno_copy); + throw TTransportException(TTransportException::UNKNOWN, "Unknown", errno_copy); + } else if (ret > 0) { + // Check for an interrupt signal + if (intSock2_ >= 0 && (fds[1].revents & POLLIN)) { + int8_t buf; + if (-1 == recv(intSock2_, cast_sockopt(&buf), sizeof(int8_t), 0)) { + GlobalOutput.perror("TServerSocket::acceptImpl() recv() interrupt ", errno); + } + throw TTransportException(TTransportException::INTERRUPTED); + } + + // Check for the actual server socket being ready + if (fds[0].revents & POLLIN) { + break; + } + } else { + GlobalOutput("TServerSocket::acceptImpl() poll 0"); + throw TTransportException(TTransportException::UNKNOWN); + } + } + + struct sockaddr_storage clientAddress; + int size = sizeof(clientAddress); + int clientSocket = ::accept(serverSocket_, + (struct sockaddr *) &clientAddress, + (socklen_t *) &size); + + if (clientSocket < 0) { + int errno_copy = errno; + GlobalOutput.perror("TServerSocket::acceptImpl() ::accept() ", errno_copy); + throw TTransportException(TTransportException::UNKNOWN, "accept()", errno_copy); + } + + // Make sure client socket is blocking + int flags = fcntl(clientSocket, F_GETFL, 0); + if (flags == -1) { + int errno_copy = errno; + GlobalOutput.perror("TServerSocket::acceptImpl() fcntl() F_GETFL ", errno_copy); + throw TTransportException(TTransportException::UNKNOWN, "fcntl(F_GETFL)", errno_copy); + } + + if (-1 == fcntl(clientSocket, F_SETFL, flags & ~O_NONBLOCK)) { + int errno_copy = errno; + GlobalOutput.perror("TServerSocket::acceptImpl() fcntl() F_SETFL ~O_NONBLOCK ", errno_copy); + throw TTransportException(TTransportException::UNKNOWN, "fcntl(F_SETFL)", errno_copy); + } + + shared_ptr client = createSocket(clientSocket); + if (sendTimeout_ > 0) { + client->setSendTimeout(sendTimeout_); + } + if (recvTimeout_ > 0) { + client->setRecvTimeout(recvTimeout_); + } + client->setCachedAddress((sockaddr*) &clientAddress, size); + + return client; +} + +shared_ptr TServerSocket::createSocket(int clientSocket) { + return shared_ptr(new TSocket(clientSocket)); +} + +void TServerSocket::interrupt() { + if (intSock1_ >= 0) { + int8_t byte = 0; + if (-1 == send(intSock1_, cast_sockopt(&byte), sizeof(int8_t), 0)) { + GlobalOutput.perror("TServerSocket::interrupt() send() ", errno); + } + } +} + +void TServerSocket::close() { + if (serverSocket_ >= 0) { + +#ifdef _WIN32 + shutdown(serverSocket_, SD_BOTH); + ::closesocket(serverSocket_); +#else + shutdown(serverSocket_, SHUT_RDWR); + ::close(serverSocket_); +#endif + + } + if (intSock1_ >= 0) { + ::close(intSock1_); + } + if (intSock2_ >= 0) { + ::close(intSock2_); + } + serverSocket_ = -1; + intSock1_ = -1; + intSock2_ = -1; +} + +}}} // apache::thrift::transport diff --git a/sg_agent/thrid_party/thrift/include/transport/TServerSocket.h b/sg_agent/thrid_party/thrift/include/transport/TServerSocket.h new file mode 100644 index 0000000..280ee69 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TServerSocket.h @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TSERVERSOCKET_H_ +#define _THRIFT_TRANSPORT_TSERVERSOCKET_H_ 1 + +#include "TServerTransport.h" +#include + +namespace apache { namespace thrift { namespace transport { + +class TSocket; + +/** + * Server socket implementation of TServerTransport. Wrapper around a unix + * socket listen and accept calls. + * + */ +class TServerSocket : public TServerTransport { + public: + TServerSocket(int port); + TServerSocket(int port, int sendTimeout, int recvTimeout); + TServerSocket(std::string path); + + ~TServerSocket(); + + void setSendTimeout(int sendTimeout); + void setRecvTimeout(int recvTimeout); + + void setAcceptTimeout(int accTimeout); + + void setRetryLimit(int retryLimit); + void setRetryDelay(int retryDelay); + + void setTcpSendBuffer(int tcpSendBuffer); + void setTcpRecvBuffer(int tcpRecvBuffer); + + void listen(); + void close(); + + void interrupt(); + + protected: + boost::shared_ptr acceptImpl(); + virtual boost::shared_ptr createSocket(int client); + + private: + int port_; + std::string path_; + int serverSocket_; + int acceptBacklog_; + int sendTimeout_; + int recvTimeout_; + int accTimeout_; + int retryLimit_; + int retryDelay_; + int tcpSendBuffer_; + int tcpRecvBuffer_; + + int intSock1_; + int intSock2_; +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TSERVERSOCKET_H_ diff --git a/sg_agent/thrid_party/thrift/include/transport/TServerTransport.h b/sg_agent/thrid_party/thrift/include/transport/TServerTransport.h new file mode 100644 index 0000000..40bbc6c --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TServerTransport.h @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TSERVERTRANSPORT_H_ +#define _THRIFT_TRANSPORT_TSERVERTRANSPORT_H_ 1 + +#include "TTransport.h" +#include "TTransportException.h" +#include + +namespace apache { namespace thrift { namespace transport { + +/** + * Server transport framework. A server needs to have some facility for + * creating base transports to read/write from. + * + */ +class TServerTransport { + public: + virtual ~TServerTransport() {} + + /** + * Starts the server transport listening for new connections. Prior to this + * call most transports will not return anything when accept is called. + * + * @throws TTransportException if we were unable to listen + */ + virtual void listen() {} + + /** + * Gets a new dynamically allocated transport object and passes it to the + * caller. Note that it is the explicit duty of the caller to free the + * allocated object. The returned TTransport object must always be in the + * opened state. NULL should never be returned, instead an Exception should + * always be thrown. + * + * @return A new TTransport object + * @throws TTransportException if there is an error + */ + boost::shared_ptr accept() { + boost::shared_ptr result = acceptImpl(); + if (result == NULL) { + throw TTransportException("accept() may not return NULL"); + } + return result; + } + + /** + * For "smart" TServerTransport implementations that work in a multi + * threaded context this can be used to break out of an accept() call. + * It is expected that the transport will throw a TTransportException + * with the interrupted error code. + */ + virtual void interrupt() {} + + /** + * Closes this transport such that future calls to accept will do nothing. + */ + virtual void close() = 0; + + protected: + TServerTransport() {} + + /** + * Subclasses should implement this function for accept. + * + * @return A newly allocated TTransport object + * @throw TTransportException If an error occurs + */ + virtual boost::shared_ptr acceptImpl() = 0; + +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TSERVERTRANSPORT_H_ diff --git a/sg_agent/thrid_party/thrift/include/transport/TShortReadTransport.h b/sg_agent/thrid_party/thrift/include/transport/TShortReadTransport.h new file mode 100644 index 0000000..0d0eb86 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TShortReadTransport.h @@ -0,0 +1,97 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TSHORTREADTRANSPORT_H_ +#define _THRIFT_TRANSPORT_TSHORTREADTRANSPORT_H_ 1 + +#include + +#include +#include + +namespace apache { namespace thrift { namespace transport { namespace test { + +/** + * This class is only meant for testing. It wraps another transport. + * Calls to read are passed through with some probability. Otherwise, + * the read amount is randomly reduced before being passed through. + * + */ +class TShortReadTransport : public TVirtualTransport { + public: + TShortReadTransport(boost::shared_ptr transport, double full_prob) + : transport_(transport) + , fullProb_(full_prob) + {} + + bool isOpen() { + return transport_->isOpen(); + } + + bool peek() { + return transport_->peek(); + } + + void open() { + transport_->open(); + } + + void close() { + transport_->close(); + } + + uint32_t read(uint8_t* buf, uint32_t len) { + if (len == 0) { + return 0; + } + + if (rand()/(double)RAND_MAX >= fullProb_) { + len = 1 + rand()%len; + } + return transport_->read(buf, len); + } + + void write(const uint8_t* buf, uint32_t len) { + transport_->write(buf, len); + } + + void flush() { + transport_->flush(); + } + + const uint8_t* borrow(uint8_t* buf, uint32_t* len) { + return transport_->borrow(buf, len); + } + + void consume(uint32_t len) { + return transport_->consume(len); + } + + boost::shared_ptr getUnderlyingTransport() { + return transport_; + } + + protected: + boost::shared_ptr transport_; + double fullProb_; +}; + +}}}} // apache::thrift::transport::test + +#endif // #ifndef _THRIFT_TRANSPORT_TSHORTREADTRANSPORT_H_ diff --git a/sg_agent/thrid_party/thrift/include/transport/TSimpleFileTransport.cpp b/sg_agent/thrid_party/thrift/include/transport/TSimpleFileTransport.cpp new file mode 100644 index 0000000..b52e4d5 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TSimpleFileTransport.cpp @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "TSimpleFileTransport.h" + +#include +#ifdef HAVE_SYS_STAT_H +#include +#endif +#include + +#ifdef _WIN32 +#include +#endif + +namespace apache { namespace thrift { namespace transport { + +TSimpleFileTransport:: +TSimpleFileTransport(const std::string& path, bool read, bool write) + : TFDTransport(-1, TFDTransport::CLOSE_ON_DESTROY) { + int flags = 0; + if (read && write) { + flags = O_RDWR; + } else if (read) { + flags = O_RDONLY; + } else if (write) { + flags = O_WRONLY; + } else { + throw TTransportException("Neither READ nor WRITE specified"); + } + if (write) { + flags |= O_CREAT | O_APPEND; + } +#ifndef _WIN32 + mode_t mode = S_IRUSR | S_IWUSR| S_IRGRP | S_IROTH; +#else + int mode = _S_IREAD | _S_IWRITE; +#endif + int fd = ::open(path.c_str(), + flags, + mode); + if (fd < 0) { + throw TTransportException("failed to open file for writing: " + path); + } + setFD(fd); + open(); +} + +}}} // apache::thrift::transport diff --git a/sg_agent/thrid_party/thrift/include/transport/TSimpleFileTransport.h b/sg_agent/thrid_party/thrift/include/transport/TSimpleFileTransport.h new file mode 100644 index 0000000..6cc52ea --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TSimpleFileTransport.h @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TSIMPLEFILETRANSPORT_H_ +#define _THRIFT_TRANSPORT_TSIMPLEFILETRANSPORT_H_ 1 + +#include "TFDTransport.h" + +namespace apache { namespace thrift { namespace transport { + +/** + * Dead-simple wrapper around a file. + * + * Writeable files are opened with O_CREAT and O_APPEND + */ +class TSimpleFileTransport : public TFDTransport { + public: + TSimpleFileTransport(const std::string& path, + bool read = true, + bool write = false); +}; + +}}} // apache::thrift::transport + +#endif // _THRIFT_TRANSPORT_TSIMPLEFILETRANSPORT_H_ diff --git a/sg_agent/thrid_party/thrift/include/transport/TSocket.cpp b/sg_agent/thrid_party/thrift/include/transport/TSocket.cpp new file mode 100644 index 0000000..a0cc77a --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TSocket.cpp @@ -0,0 +1,823 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_SYS_UN_H +#include +#endif +#ifdef HAVE_SYS_POLL_H +#include +#endif +#include +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#include +#include + +#include "concurrency/Monitor.h" +#include "TSocket.h" +#include "TTransportException.h" + +#ifndef SOCKOPT_CAST_T +# ifndef _WIN32 +# define SOCKOPT_CAST_T void +# else +# define SOCKOPT_CAST_T char +# endif // _WIN32 +#endif + +template +inline const SOCKOPT_CAST_T* const_cast_sockopt(const T* v) { + return reinterpret_cast(v); +} + +template +inline SOCKOPT_CAST_T* cast_sockopt(T* v) { + return reinterpret_cast(v); +} + +namespace apache { namespace thrift { namespace transport { + +using namespace std; + +// Global var to track total socket sys calls +uint32_t g_socket_syscalls = 0; + +/** + * TSocket implementation. + * + */ + +TSocket::TSocket(string host, int port) : + host_(host), + port_(port), + path_(""), + socket_(-1), + connTimeout_(0), + sendTimeout_(0), + recvTimeout_(0), + lingerOn_(1), + lingerVal_(0), + noDelay_(1), + maxRecvRetries_(5) { + recvTimeval_.tv_sec = (int)(recvTimeout_/1000); + recvTimeval_.tv_usec = (int)((recvTimeout_%1000)*1000); +} + +TSocket::TSocket(string path) : + host_(""), + port_(0), + path_(path), + socket_(-1), + connTimeout_(0), + sendTimeout_(0), + recvTimeout_(0), + lingerOn_(1), + lingerVal_(0), + noDelay_(1), + maxRecvRetries_(5) { + recvTimeval_.tv_sec = (int)(recvTimeout_/1000); + recvTimeval_.tv_usec = (int)((recvTimeout_%1000)*1000); + cachedPeerAddr_.ipv4.sin_family = AF_UNSPEC; +} + +TSocket::TSocket() : + host_(""), + port_(0), + path_(""), + socket_(-1), + connTimeout_(0), + sendTimeout_(0), + recvTimeout_(0), + lingerOn_(1), + lingerVal_(0), + noDelay_(1), + maxRecvRetries_(5) { + recvTimeval_.tv_sec = (int)(recvTimeout_/1000); + recvTimeval_.tv_usec = (int)((recvTimeout_%1000)*1000); + cachedPeerAddr_.ipv4.sin_family = AF_UNSPEC; +} + +TSocket::TSocket(int socket) : + host_(""), + port_(0), + path_(""), + socket_(socket), + connTimeout_(0), + sendTimeout_(0), + recvTimeout_(0), + lingerOn_(1), + lingerVal_(0), + noDelay_(1), + maxRecvRetries_(5) { + recvTimeval_.tv_sec = (int)(recvTimeout_/1000); + recvTimeval_.tv_usec = (int)((recvTimeout_%1000)*1000); + cachedPeerAddr_.ipv4.sin_family = AF_UNSPEC; +} + +TSocket::~TSocket() { + close(); +} + +bool TSocket::isOpen() { + return (socket_ >= 0); +} + +bool TSocket::peek() { + if (!isOpen()) { + return false; + } + uint8_t buf; + int r = recv(socket_, cast_sockopt(&buf), 1, MSG_PEEK); + if (r == -1) { + int errno_copy = errno; + #if defined __FreeBSD__ || defined __MACH__ + /* shigin: + * freebsd returns -1 and ECONNRESET if socket was closed by + * the other side + */ + if (errno_copy == ECONNRESET) + { + close(); + return false; + } + #endif + GlobalOutput.perror("TSocket::peek() recv() " + getSocketInfo(), errno_copy); + throw TTransportException(TTransportException::UNKNOWN, "recv()", errno_copy); + } + return (r > 0); +} + +void TSocket::openConnection(struct addrinfo *res) { + + if (isOpen()) { + return; + } + + if (! path_.empty()) { + socket_ = socket(PF_UNIX, SOCK_STREAM, IPPROTO_IP); + } else { + socket_ = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + } + + if (socket_ == -1) { + int errno_copy = errno; + GlobalOutput.perror("TSocket::open() socket() " + getSocketInfo(), errno_copy); + throw TTransportException(TTransportException::NOT_OPEN, "socket()", errno_copy); + } + + // Send timeout + if (sendTimeout_ > 0) { + setSendTimeout(sendTimeout_); + } + + // Recv timeout + if (recvTimeout_ > 0) { + setRecvTimeout(recvTimeout_); + } + + // Linger + setLinger(lingerOn_, lingerVal_); + + // No delay + setNoDelay(noDelay_); + + // Uses a low min RTO if asked to. +#ifdef TCP_LOW_MIN_RTO + if (getUseLowMinRto()) { + int one = 1; + setsockopt(socket_, IPPROTO_TCP, TCP_LOW_MIN_RTO, &one, sizeof(one)); + } +#endif + + + // Set the socket to be non blocking for connect if a timeout exists + int flags = fcntl(socket_, F_GETFL, 0); + if (connTimeout_ > 0) { + if (-1 == fcntl(socket_, F_SETFL, flags | O_NONBLOCK)) { + int errno_copy = errno; + GlobalOutput.perror("TSocket::open() fcntl() " + getSocketInfo(), errno_copy); + throw TTransportException(TTransportException::NOT_OPEN, "fcntl() failed", errno_copy); + } + } else { + if (-1 == fcntl(socket_, F_SETFL, flags & ~O_NONBLOCK)) { + int errno_copy = errno; + GlobalOutput.perror("TSocket::open() fcntl " + getSocketInfo(), errno_copy); + throw TTransportException(TTransportException::NOT_OPEN, "fcntl() failed", errno_copy); + } + } + + // Connect the socket + int ret; + if (! path_.empty()) { + +#ifndef _WIN32 + + struct sockaddr_un address; + socklen_t len; + + if (path_.length() > sizeof(address.sun_path)) { + int errno_copy = errno; + GlobalOutput.perror("TSocket::open() Unix Domain socket path too long", errno_copy); + throw TTransportException(TTransportException::NOT_OPEN, " Unix Domain socket path too long"); + } + + address.sun_family = AF_UNIX; + snprintf(address.sun_path, sizeof(address.sun_path), "%s", path_.c_str()); + len = sizeof(address); + ret = connect(socket_, (struct sockaddr *) &address, len); + +#else + GlobalOutput.perror("TSocket::open() Unix Domain socket path not supported on windows", -99); + throw TTransportException(TTransportException::NOT_OPEN, " Unix Domain socket path not supported"); +#endif + + } else { + ret = connect(socket_, res->ai_addr, res->ai_addrlen); + } + + // success case + if (ret == 0) { + goto done; + } + + if ((errno != EINPROGRESS) && (errno != EWOULDBLOCK)) { + int errno_copy = errno; + GlobalOutput.perror("TSocket::open() connect() " + getSocketInfo(), errno_copy); + throw TTransportException(TTransportException::NOT_OPEN, "connect() failed", errno_copy); + } + + + struct pollfd fds[1]; + std::memset(fds, 0 , sizeof(fds)); + fds[0].fd = socket_; + fds[0].events = POLLOUT; + ret = poll(fds, 1, connTimeout_); + + if (ret > 0) { + // Ensure the socket is connected and that there are no errors set + int val; + socklen_t lon; + lon = sizeof(int); + int ret2 = getsockopt(socket_, SOL_SOCKET, SO_ERROR, cast_sockopt(&val), &lon); + if (ret2 == -1) { + int errno_copy = errno; + GlobalOutput.perror("TSocket::open() getsockopt() " + getSocketInfo(), errno_copy); + throw TTransportException(TTransportException::NOT_OPEN, "getsockopt()", errno_copy); + } + // no errors on socket, go to town + if (val == 0) { + goto done; + } + GlobalOutput.perror("TSocket::open() error on socket (after poll) " + getSocketInfo(), val); + throw TTransportException(TTransportException::NOT_OPEN, "socket open() error", val); + } else if (ret == 0) { + // socket timed out + string errStr = "TSocket::open() timed out " + getSocketInfo(); + GlobalOutput(errStr.c_str()); + throw TTransportException(TTransportException::NOT_OPEN, "open() timed out"); + } else { + // error on poll() + int errno_copy = errno; + GlobalOutput.perror("TSocket::open() poll() " + getSocketInfo(), errno_copy); + throw TTransportException(TTransportException::NOT_OPEN, "poll() failed", errno_copy); + } + + done: + // Set socket back to normal mode (blocking) + fcntl(socket_, F_SETFL, flags); + + if (path_.empty()) { + setCachedAddress(res->ai_addr, res->ai_addrlen); + } +} + +void TSocket::open() { + if (isOpen()) { + return; + } + if (! path_.empty()) { + unix_open(); + } else { + local_open(); + } +} + +void TSocket::unix_open(){ + if (! path_.empty()) { + // Unix Domain SOcket does not need addrinfo struct, so we pass NULL + openConnection(NULL); + } +} + +void TSocket::local_open(){ + +#ifdef _WIN32 + TWinsockSingleton::create(); +#endif // _WIN32 + + if (isOpen()) { + return; + } + + // Validate port number + if (port_ < 0 || port_ > 0xFFFF) { + throw TTransportException(TTransportException::NOT_OPEN, "Specified port is invalid"); + } + + struct addrinfo hints, *res, *res0; + res = NULL; + res0 = NULL; + int error; + char port[sizeof("65535")]; + std::memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + sprintf(port, "%d", port_); + + error = getaddrinfo(host_.c_str(), port, &hints, &res0); + + if (error) { + string errStr = "TSocket::open() getaddrinfo() " + getSocketInfo() + string(gai_strerror(error)); + GlobalOutput(errStr.c_str()); + close(); + throw TTransportException(TTransportException::NOT_OPEN, "Could not resolve host for client socket."); + } + + // Cycle through all the returned addresses until one + // connects or push the exception up. + for (res = res0; res; res = res->ai_next) { + try { + openConnection(res); + break; + } catch (TTransportException& ttx) { + if (res->ai_next) { + close(); + } else { + close(); + freeaddrinfo(res0); // cleanup on failure + throw; + } + } + } + + // Free address structure memory + freeaddrinfo(res0); +} + +void TSocket::close() { + if (socket_ >= 0) { + +#ifdef _WIN32 + shutdown(socket_, SD_BOTH); + ::closesocket(socket_); +#else + shutdown(socket_, SHUT_RDWR); + ::close(socket_); +#endif + + } + socket_ = -1; +} + +void TSocket::setSocketFD(int socket) { + if (socket_ >= 0) { + close(); + } + socket_ = socket; +} + +uint32_t TSocket::read(uint8_t* buf, uint32_t len) { + if (socket_ < 0) { + throw TTransportException(TTransportException::NOT_OPEN, "Called read on non-open socket"); + } + + int32_t retries = 0; + + // EAGAIN can be signalled both when a timeout has occurred and when + // the system is out of resources (an awesome undocumented feature). + // The following is an approximation of the time interval under which + // EAGAIN is taken to indicate an out of resources error. + uint32_t eagainThresholdMicros = 0; + if (recvTimeout_) { + // if a readTimeout is specified along with a max number of recv retries, then + // the threshold will ensure that the read timeout is not exceeded even in the + // case of resource errors + eagainThresholdMicros = (recvTimeout_*1000)/ ((maxRecvRetries_>0) ? maxRecvRetries_ : 2); + } + + try_again: + // Read from the socket + struct timeval begin; + if (recvTimeout_ > 0) { + gettimeofday(&begin, NULL); + } else { + // if there is no read timeout we don't need the TOD to determine whether + // an EAGAIN is due to a timeout or an out-of-resource condition. + begin.tv_sec = begin.tv_usec = 0; + } + int got = recv(socket_, cast_sockopt(buf), len, 0); + int errno_copy = errno; //gettimeofday can change errno + ++g_socket_syscalls; + + // Check for error on read + if (got < 0) { + if (errno_copy == EAGAIN) { + // if no timeout we can assume that resource exhaustion has occurred. + if (recvTimeout_ == 0) { + throw TTransportException(TTransportException::TIMED_OUT, + "EAGAIN (unavailable resources)"); + } + // check if this is the lack of resources or timeout case + struct timeval end; + gettimeofday(&end, NULL); + uint32_t readElapsedMicros = (((end.tv_sec - begin.tv_sec) * 1000 * 1000) + + (((uint64_t)(end.tv_usec - begin.tv_usec)))); + + if (!eagainThresholdMicros || (readElapsedMicros < eagainThresholdMicros)) { + if (retries++ < maxRecvRetries_) { + usleep(50); + goto try_again; + } else { + throw TTransportException(TTransportException::TIMED_OUT, + "EAGAIN (unavailable resources)"); + } + } else { + // infer that timeout has been hit + throw TTransportException(TTransportException::TIMED_OUT, + "EAGAIN (timed out)"); + } + } + + // If interrupted, try again + if (errno_copy == EINTR && retries++ < maxRecvRetries_) { + goto try_again; + } + + #if defined __FreeBSD__ || defined __MACH__ + if (errno_copy == ECONNRESET) { + /* shigin: freebsd doesn't follow POSIX semantic of recv and fails with + * ECONNRESET if peer performed shutdown + * edhall: eliminated close() since we do that in the destructor. + */ + return 0; + } + #endif + +#ifdef _WIN32 + if(errno_copy == WSAECONNRESET) { + return 0; // EOF + } +#endif + + // Now it's not a try again case, but a real probblez + GlobalOutput.perror("TSocket::read() recv() " + getSocketInfo(), errno_copy); + + // If we disconnect with no linger time + if (errno_copy == ECONNRESET) { + throw TTransportException(TTransportException::NOT_OPEN, "ECONNRESET"); + } + + // This ish isn't open + if (errno_copy == ENOTCONN) { + throw TTransportException(TTransportException::NOT_OPEN, "ENOTCONN"); + } + + // Timed out! + if (errno_copy == ETIMEDOUT) { + throw TTransportException(TTransportException::TIMED_OUT, "ETIMEDOUT"); + } + + // Some other error, whatevz + throw TTransportException(TTransportException::UNKNOWN, "Unknown", errno_copy); + } + + // The remote host has closed the socket + if (got == 0) { + // edhall: we used to call close() here, but our caller may want to deal + // with the socket fd and we'll close() in our destructor in any case. + return 0; + } + + // Pack data into string + return got; +} + +void TSocket::write(const uint8_t* buf, uint32_t len) { + uint32_t sent = 0; + + while (sent < len) { + uint32_t b = write_partial(buf + sent, len - sent); + if (b == 0) { + // This should only happen if the timeout set with SO_SNDTIMEO expired. + // Raise an exception. + throw TTransportException(TTransportException::TIMED_OUT, + "send timeout expired"); + } + sent += b; + } +} + +uint32_t TSocket::write_partial(const uint8_t* buf, uint32_t len) { + if (socket_ < 0) { + throw TTransportException(TTransportException::NOT_OPEN, "Called write on non-open socket"); + } + + uint32_t sent = 0; + + int flags = 0; +#ifdef MSG_NOSIGNAL + // Note the use of MSG_NOSIGNAL to suppress SIGPIPE errors, instead we + // check for the EPIPE return condition and close the socket in that case + flags |= MSG_NOSIGNAL; +#endif // ifdef MSG_NOSIGNAL + + int b = send(socket_, const_cast_sockopt(buf + sent), len - sent, flags); + ++g_socket_syscalls; + + if (b < 0) { + if (errno == EWOULDBLOCK || errno == EAGAIN) { + return 0; + } + // Fail on a send error + int errno_copy = errno; + GlobalOutput.perror("TSocket::write_partial() send() " + getSocketInfo(), errno_copy); + + if (errno_copy == EPIPE || errno_copy == ECONNRESET || errno_copy == ENOTCONN) { + close(); + throw TTransportException(TTransportException::NOT_OPEN, "write() send()", errno_copy); + } + + throw TTransportException(TTransportException::UNKNOWN, "write() send()", errno_copy); + } + + // Fail on blocked send + if (b == 0) { + throw TTransportException(TTransportException::NOT_OPEN, "Socket send returned 0."); + } + return b; +} + +std::string TSocket::getHost() { + return host_; +} + +int TSocket::getPort() { + return port_; +} + +void TSocket::setHost(string host) { + host_ = host; +} + +void TSocket::setPort(int port) { + port_ = port; +} + +void TSocket::setLinger(bool on, int linger) { + lingerOn_ = on; + lingerVal_ = linger; + if (socket_ < 0) { + return; + } + + struct linger l = {(lingerOn_ ? 1 : 0), lingerVal_}; + int ret = setsockopt(socket_, SOL_SOCKET, SO_LINGER, cast_sockopt(&l), sizeof(l)); + if (ret == -1) { + int errno_copy = errno; // Copy errno because we're allocating memory. + GlobalOutput.perror("TSocket::setLinger() setsockopt() " + getSocketInfo(), errno_copy); + } +} + +void TSocket::setNoDelay(bool noDelay) { + noDelay_ = noDelay; + if (socket_ < 0 || !path_.empty()) { + return; + } + + // Set socket to NODELAY + int v = noDelay_ ? 1 : 0; + int ret = setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, cast_sockopt(&v), sizeof(v)); + if (ret == -1) { + int errno_copy = errno; // Copy errno because we're allocating memory. + GlobalOutput.perror("TSocket::setNoDelay() setsockopt() " + getSocketInfo(), errno_copy); + } +} + +void TSocket::setConnTimeout(int ms) { + connTimeout_ = ms; +} + +void TSocket::setRecvTimeout(int ms) { + if (ms < 0) { + char errBuf[512]; + sprintf(errBuf, "TSocket::setRecvTimeout with negative input: %d\n", ms); + GlobalOutput(errBuf); + return; + } + recvTimeout_ = ms; + + if (socket_ < 0) { + return; + } + + recvTimeval_.tv_sec = (int)(recvTimeout_/1000); + recvTimeval_.tv_usec = (int)((recvTimeout_%1000)*1000); + + // Copy because poll may modify + struct timeval r = recvTimeval_; + int ret = setsockopt(socket_, SOL_SOCKET, SO_RCVTIMEO, cast_sockopt(&r), sizeof(r)); + if (ret == -1) { + int errno_copy = errno; // Copy errno because we're allocating memory. + GlobalOutput.perror("TSocket::setRecvTimeout() setsockopt() " + getSocketInfo(), errno_copy); + } +} + +void TSocket::setSendTimeout(int ms) { + if (ms < 0) { + char errBuf[512]; + sprintf(errBuf, "TSocket::setSendTimeout with negative input: %d\n", ms); + GlobalOutput(errBuf); + return; + } + sendTimeout_ = ms; + + if (socket_ < 0) { + return; + } + + struct timeval s = {(int)(sendTimeout_/1000), + (int)((sendTimeout_%1000)*1000)}; + int ret = setsockopt(socket_, SOL_SOCKET, SO_SNDTIMEO, cast_sockopt(&s), sizeof(s)); + if (ret == -1) { + int errno_copy = errno; // Copy errno because we're allocating memory. + GlobalOutput.perror("TSocket::setSendTimeout() setsockopt() " + getSocketInfo(), errno_copy); + } +} + +void TSocket::setMaxRecvRetries(int maxRecvRetries) { + maxRecvRetries_ = maxRecvRetries; +} + +string TSocket::getSocketInfo() { + std::ostringstream oss; + if (host_.empty() || port_ == 0) { + oss << ""; + } else { + oss << ""; + } + return oss.str(); +} + +std::string TSocket::getPeerHost() { + if (peerHost_.empty() && path_.empty()) { + struct sockaddr_storage addr; + struct sockaddr* addrPtr; + socklen_t addrLen; + + if (socket_ < 0) { + return host_; + } + + addrPtr = getCachedAddress(&addrLen); + + if (addrPtr == NULL) { + addrLen = sizeof(addr); + if (getpeername(socket_, (sockaddr*) &addr, &addrLen) != 0) { + return peerHost_; + } + addrPtr = (sockaddr*)&addr; + + setCachedAddress(addrPtr, addrLen); + } + + char clienthost[NI_MAXHOST]; + char clientservice[NI_MAXSERV]; + + getnameinfo((sockaddr*) addrPtr, addrLen, + clienthost, sizeof(clienthost), + clientservice, sizeof(clientservice), 0); + + peerHost_ = clienthost; + } + return peerHost_; +} + +std::string TSocket::getPeerAddress() { + if (peerAddress_.empty() && path_.empty()) { + struct sockaddr_storage addr; + struct sockaddr* addrPtr; + socklen_t addrLen; + + if (socket_ < 0) { + return peerAddress_; + } + + addrPtr = getCachedAddress(&addrLen); + + if (addrPtr == NULL) { + addrLen = sizeof(addr); + if (getpeername(socket_, (sockaddr*) &addr, &addrLen) != 0) { + return peerAddress_; + } + addrPtr = (sockaddr*)&addr; + + setCachedAddress(addrPtr, addrLen); + } + + char clienthost[NI_MAXHOST]; + char clientservice[NI_MAXSERV]; + + getnameinfo(addrPtr, addrLen, + clienthost, sizeof(clienthost), + clientservice, sizeof(clientservice), + NI_NUMERICHOST|NI_NUMERICSERV); + + peerAddress_ = clienthost; + peerPort_ = std::atoi(clientservice); + } + return peerAddress_; +} + +int TSocket::getPeerPort() { + getPeerAddress(); + return peerPort_; +} + +void TSocket::setCachedAddress(const sockaddr* addr, socklen_t len) { + if (!path_.empty()) { + return; + } + + switch (addr->sa_family) { + case AF_INET: + if (len == sizeof(sockaddr_in)) { + memcpy((void*)&cachedPeerAddr_.ipv4, (void*)addr, len); + } + break; + + case AF_INET6: + if (len == sizeof(sockaddr_in6)) { + memcpy((void*)&cachedPeerAddr_.ipv6, (void*)addr, len); + } + break; + } +} + +sockaddr* TSocket::getCachedAddress(socklen_t* len) const { + switch (cachedPeerAddr_.ipv4.sin_family) { + case AF_INET: + *len = sizeof(sockaddr_in); + return (sockaddr*) &cachedPeerAddr_.ipv4; + + case AF_INET6: + *len = sizeof(sockaddr_in6); + return (sockaddr*) &cachedPeerAddr_.ipv6; + + default: + return NULL; + } +} + +bool TSocket::useLowMinRto_ = false; +void TSocket::setUseLowMinRto(bool useLowMinRto) { + useLowMinRto_ = useLowMinRto; +} +bool TSocket::getUseLowMinRto() { + return useLowMinRto_; +} + +}}} // apache::thrift::transport diff --git a/sg_agent/thrid_party/thrift/include/transport/TSocket.h b/sg_agent/thrid_party/thrift/include/transport/TSocket.h new file mode 100644 index 0000000..9d07522 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TSocket.h @@ -0,0 +1,308 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TSOCKET_H_ +#define _THRIFT_TRANSPORT_TSOCKET_H_ 1 + +#include + +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif + +#include "TTransport.h" +#include "TVirtualTransport.h" +#include "TServerSocket.h" + +namespace apache { namespace thrift { namespace transport { + +/** + * TCP Socket implementation of the TTransport interface. + * + */ +class TSocket : public TVirtualTransport { + public: + /** + * Constructs a new socket. Note that this does NOT actually connect the + * socket. + * + */ + TSocket(); + + /** + * Constructs a new socket. Note that this does NOT actually connect the + * socket. + * + * @param host An IP address or hostname to connect to + * @param port The port to connect on + */ + TSocket(std::string host, int port); + + /** + * Constructs a new Unix domain socket. + * Note that this does NOT actually connect the socket. + * + * @param path The Unix domain socket e.g. "/tmp/ThriftTest.binary.thrift" + */ + TSocket(std::string path); + + /** + * Destroyes the socket object, closing it if necessary. + */ + virtual ~TSocket(); + + /** + * Whether the socket is alive. + * + * @return Is the socket alive? + */ + virtual bool isOpen(); + + /** + * Calls select on the socket to see if there is more data available. + */ + virtual bool peek(); + + /** + * Creates and opens the UNIX socket. + * + * @throws TTransportException If the socket could not connect + */ + virtual void open(); + + /** + * Shuts down communications on the socket. + */ + virtual void close(); + + /** + * Reads from the underlying socket. + */ + virtual uint32_t read(uint8_t* buf, uint32_t len); + + /** + * Writes to the underlying socket. Loops until done or fail. + */ + virtual void write(const uint8_t* buf, uint32_t len); + + /** + * Writes to the underlying socket. Does single send() and returns result. + */ + uint32_t write_partial(const uint8_t* buf, uint32_t len); + + /** + * Get the host that the socket is connected to + * + * @return string host identifier + */ + std::string getHost(); + + /** + * Get the port that the socket is connected to + * + * @return int port number + */ + int getPort(); + + /** + * Set the host that socket will connect to + * + * @param host host identifier + */ + void setHost(std::string host); + + /** + * Set the port that socket will connect to + * + * @param port port number + */ + void setPort(int port); + + /** + * Controls whether the linger option is set on the socket. + * + * @param on Whether SO_LINGER is on + * @param linger If linger is active, the number of seconds to linger for + */ + void setLinger(bool on, int linger); + + /** + * Whether to enable/disable Nagle's algorithm. + * + * @param noDelay Whether or not to disable the algorithm. + * @return + */ + void setNoDelay(bool noDelay); + + /** + * Set the connect timeout + */ + void setConnTimeout(int ms); + + /** + * Set the receive timeout + */ + void setRecvTimeout(int ms); + + /** + * Set the send timeout + */ + void setSendTimeout(int ms); + + /** + * Set the max number of recv retries in case of an EAGAIN + * error + */ + void setMaxRecvRetries(int maxRecvRetries); + + /** + * Get socket information formated as a string + */ + std::string getSocketInfo(); + + /** + * Returns the DNS name of the host to which the socket is connected + */ + std::string getPeerHost(); + + /** + * Returns the address of the host to which the socket is connected + */ + std::string getPeerAddress(); + + /** + * Returns the port of the host to which the socket is connected + **/ + int getPeerPort(); + + /** + * Returns the underlying socket file descriptor. + */ + int getSocketFD() { + return socket_; + } + + /** + * (Re-)initialize a TSocket for the supplied descriptor. This is only + * intended for use by TNonblockingServer -- other use may result in + * unfortunate surprises. + * + * @param fd the descriptor for an already-connected socket + */ + void setSocketFD(int fd); + + /* + * Returns a cached copy of the peer address. + */ + sockaddr* getCachedAddress(socklen_t* len) const; + + /** + * Sets whether to use a low minimum TCP retransmission timeout. + */ + static void setUseLowMinRto(bool useLowMinRto); + + /** + * Gets whether to use a low minimum TCP retransmission timeout. + */ + static bool getUseLowMinRto(); + + /** + * Constructor to create socket from raw UNIX handle. + */ + TSocket(int socket); + + /** + * Set a cache of the peer address (used when trivially available: e.g. + * accept() or connect()). Only caches IPV4 and IPV6; unset for others. + */ + void setCachedAddress(const sockaddr* addr, socklen_t len); + + protected: + /** connect, called by open */ + void openConnection(struct addrinfo *res); + + /** Host to connect to */ + std::string host_; + + /** Peer hostname */ + std::string peerHost_; + + /** Peer address */ + std::string peerAddress_; + + /** Peer port */ + int peerPort_; + + /** Port number to connect on */ + int port_; + + /** UNIX domain socket path */ + std::string path_; + + /** Underlying UNIX socket handle */ + int socket_; + + /** Connect timeout in ms */ + int connTimeout_; + + /** Send timeout in ms */ + int sendTimeout_; + + /** Recv timeout in ms */ + int recvTimeout_; + + /** Linger on */ + bool lingerOn_; + + /** Linger val */ + int lingerVal_; + + /** Nodelay */ + bool noDelay_; + + /** Recv EGAIN retries */ + int maxRecvRetries_; + + /** Recv timeout timeval */ + struct timeval recvTimeval_; + + /** Cached peer address */ + union { + sockaddr_in ipv4; + sockaddr_in6 ipv6; + } cachedPeerAddr_; + + /** Connection start time */ + timespec startTime_; + + /** Whether to use low minimum TCP retransmission timeout */ + static bool useLowMinRto_; + + private: + void unix_open(); + void local_open(); +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TSOCKET_H_ + diff --git a/sg_agent/thrid_party/thrift/include/transport/TSocketPool.cpp b/sg_agent/thrid_party/thrift/include/transport/TSocketPool.cpp new file mode 100644 index 0000000..160c5a3 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TSocketPool.cpp @@ -0,0 +1,252 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include + +#include "TSocketPool.h" + +namespace apache { namespace thrift { namespace transport { + +using namespace std; + +using boost::shared_ptr; + +/** + * TSocketPoolServer implementation + * + */ +TSocketPoolServer::TSocketPoolServer() + : host_(""), + port_(0), + socket_(-1), + lastFailTime_(0), + consecutiveFailures_(0) {} + +/** + * Constructor for TSocketPool server + */ +TSocketPoolServer::TSocketPoolServer(const string &host, int port) + : host_(host), + port_(port), + socket_(-1), + lastFailTime_(0), + consecutiveFailures_(0) {} + +/** + * TSocketPool implementation. + * + */ + +TSocketPool::TSocketPool() : TSocket(), + numRetries_(1), + retryInterval_(60), + maxConsecutiveFailures_(1), + randomize_(true), + alwaysTryLast_(true) { +} + +TSocketPool::TSocketPool(const vector &hosts, + const vector &ports) : TSocket(), + numRetries_(1), + retryInterval_(60), + maxConsecutiveFailures_(1), + randomize_(true), + alwaysTryLast_(true) +{ + if (hosts.size() != ports.size()) { + GlobalOutput("TSocketPool::TSocketPool: hosts.size != ports.size"); + throw TTransportException(TTransportException::BAD_ARGS); + } + + for (unsigned int i = 0; i < hosts.size(); ++i) { + addServer(hosts[i], ports[i]); + } +} + +TSocketPool::TSocketPool(const vector >& servers) : TSocket(), + numRetries_(1), + retryInterval_(60), + maxConsecutiveFailures_(1), + randomize_(true), + alwaysTryLast_(true) +{ + for (unsigned i = 0; i < servers.size(); ++i) { + addServer(servers[i].first, servers[i].second); + } +} + +TSocketPool::TSocketPool(const vector< shared_ptr >& servers) : TSocket(), + servers_(servers), + numRetries_(1), + retryInterval_(60), + maxConsecutiveFailures_(1), + randomize_(true), + alwaysTryLast_(true) +{ +} + +TSocketPool::TSocketPool(const string& host, int port) : TSocket(), + numRetries_(1), + retryInterval_(60), + maxConsecutiveFailures_(1), + randomize_(true), + alwaysTryLast_(true) +{ + addServer(host, port); +} + +TSocketPool::~TSocketPool() { + vector< shared_ptr >::const_iterator iter = servers_.begin(); + vector< shared_ptr >::const_iterator iterEnd = servers_.end(); + for (; iter != iterEnd; ++iter) { + setCurrentServer(*iter); + TSocketPool::close(); + } +} + +void TSocketPool::addServer(const string& host, int port) { + servers_.push_back(shared_ptr(new TSocketPoolServer(host, port))); +} + +void TSocketPool::addServer(shared_ptr &server) { + if (server) { + servers_.push_back(server); + } +} + +void TSocketPool::setServers(const vector< shared_ptr >& servers) { + servers_ = servers; +} + +void TSocketPool::getServers(vector< shared_ptr >& servers) { + servers = servers_; +} + +void TSocketPool::setNumRetries(int numRetries) { + numRetries_ = numRetries; +} + +void TSocketPool::setRetryInterval(int retryInterval) { + retryInterval_ = retryInterval; +} + + +void TSocketPool::setMaxConsecutiveFailures(int maxConsecutiveFailures) { + maxConsecutiveFailures_ = maxConsecutiveFailures; +} + +void TSocketPool::setRandomize(bool randomize) { + randomize_ = randomize; +} + +void TSocketPool::setAlwaysTryLast(bool alwaysTryLast) { + alwaysTryLast_ = alwaysTryLast; +} + +void TSocketPool::setCurrentServer(const shared_ptr &server) { + currentServer_ = server; + host_ = server->host_; + port_ = server->port_; + socket_ = server->socket_; +} + +/** + * This function throws an exception if socket open fails. When socket + * opens fails, the socket in the current server is reset. + */ +/* TODO: without apc we ignore a lot of functionality from the php version */ +void TSocketPool::open() { + + unsigned int numServers = servers_.size(); + if (numServers == 0) { + socket_ = -1; + throw TTransportException(TTransportException::NOT_OPEN); + } + + if (isOpen()) { + return; + } + + if (randomize_ && numServers > 1) { + random_shuffle(servers_.begin(), servers_.end()); + } + + for (unsigned int i = 0; i < numServers; ++i) { + + shared_ptr &server = servers_[i]; + // Impersonate the server socket + setCurrentServer(server); + + if (isOpen()) { + // already open means we're done + return; + } + + bool retryIntervalPassed = (server->lastFailTime_ == 0); + bool isLastServer = alwaysTryLast_ ? (i == (numServers - 1)) : false; + + if (server->lastFailTime_ > 0) { + // The server was marked as down, so check if enough time has elapsed to retry + int elapsedTime = time(NULL) - server->lastFailTime_; + if (elapsedTime > retryInterval_) { + retryIntervalPassed = true; + } + } + + if (retryIntervalPassed || isLastServer) { + for (int j = 0; j < numRetries_; ++j) { + try { + TSocket::open(); + } catch (TException e) { + string errStr = "TSocketPool::open failed "+getSocketInfo()+": "+e.what(); + GlobalOutput(errStr.c_str()); + socket_ = -1; + continue; + } + + // Copy over the opened socket so that we can keep it persistent + server->socket_ = socket_; + // reset lastFailTime_ is required + server->lastFailTime_ = 0; + // success + return; + } + + ++server->consecutiveFailures_; + if (server->consecutiveFailures_ > maxConsecutiveFailures_) { + // Mark server as down + server->consecutiveFailures_ = 0; + server->lastFailTime_ = time(NULL); + } + } + } + + GlobalOutput("TSocketPool::open: all connections failed"); + throw TTransportException(TTransportException::NOT_OPEN); +} + +void TSocketPool::close() { + TSocket::close(); + if (currentServer_) { + currentServer_->socket_ = -1; + } +} + +}}} // apache::thrift::transport diff --git a/sg_agent/thrid_party/thrift/include/transport/TSocketPool.h b/sg_agent/thrid_party/thrift/include/transport/TSocketPool.h new file mode 100644 index 0000000..749116a --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TSocketPool.h @@ -0,0 +1,196 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TSOCKETPOOL_H_ +#define _THRIFT_TRANSPORT_TSOCKETPOOL_H_ 1 + +#include +#include "TSocket.h" + +namespace apache { namespace thrift { namespace transport { + + /** + * Class to hold server information for TSocketPool + * + */ +class TSocketPoolServer { + + public: + /** + * Default constructor for server info + */ + TSocketPoolServer(); + + /** + * Constructor for TSocketPool server + */ + TSocketPoolServer(const std::string &host, int port); + + // Host name + std::string host_; + + // Port to connect on + int port_; + + // Socket for the server + int socket_; + + // Last time connecting to this server failed + int lastFailTime_; + + // Number of consecutive times connecting to this server failed + int consecutiveFailures_; +}; + +/** + * TCP Socket implementation of the TTransport interface. + * + */ +class TSocketPool : public TSocket { + + public: + + /** + * Socket pool constructor + */ + TSocketPool(); + + /** + * Socket pool constructor + * + * @param hosts list of host names + * @param ports list of port names + */ + TSocketPool(const std::vector &hosts, + const std::vector &ports); + + /** + * Socket pool constructor + * + * @param servers list of pairs of host name and port + */ + TSocketPool(const std::vector >& servers); + + /** + * Socket pool constructor + * + * @param servers list of TSocketPoolServers + */ + TSocketPool(const std::vector< boost::shared_ptr >& servers); + + /** + * Socket pool constructor + * + * @param host single host + * @param port single port + */ + TSocketPool(const std::string& host, int port); + + /** + * Destroyes the socket object, closing it if necessary. + */ + virtual ~TSocketPool(); + + /** + * Add a server to the pool + */ + void addServer(const std::string& host, int port); + + /** + * Add a server to the pool + */ + void addServer(boost::shared_ptr &server); + + /** + * Set list of servers in this pool + */ + void setServers(const std::vector< boost::shared_ptr >& servers); + + /** + * Get list of servers in this pool + */ + void getServers(std::vector< boost::shared_ptr >& servers); + + /** + * Sets how many times to keep retrying a host in the connect function. + */ + void setNumRetries(int numRetries); + + /** + * Sets how long to wait until retrying a host if it was marked down + */ + void setRetryInterval(int retryInterval); + + /** + * Sets how many times to keep retrying a host before marking it as down. + */ + void setMaxConsecutiveFailures(int maxConsecutiveFailures); + + /** + * Turns randomization in connect order on or off. + */ + void setRandomize(bool randomize); + + /** + * Whether to always try the last server. + */ + void setAlwaysTryLast(bool alwaysTryLast); + + /** + * Creates and opens the UNIX socket. + */ + void open(); + + /* + * Closes the UNIX socket + */ + void close(); + + protected: + + void setCurrentServer(const boost::shared_ptr &server); + + /** List of servers to connect to */ + std::vector< boost::shared_ptr > servers_; + + /** Current server */ + boost::shared_ptr currentServer_; + + /** How many times to retry each host in connect */ + int numRetries_; + + /** Retry interval in seconds, how long to not try a host if it has been + * marked as down. + */ + int retryInterval_; + + /** Max consecutive failures before marking a host down. */ + int maxConsecutiveFailures_; + + /** Try hosts in order? or Randomized? */ + bool randomize_; + + /** Always try last host, even if marked down? */ + bool alwaysTryLast_; +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TSOCKETPOOL_H_ + diff --git a/sg_agent/thrid_party/thrift/include/transport/TTransport.h b/sg_agent/thrid_party/thrift/include/transport/TTransport.h new file mode 100644 index 0000000..fa0ed8a --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TTransport.h @@ -0,0 +1,270 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TTRANSPORT_H_ +#define _THRIFT_TRANSPORT_TTRANSPORT_H_ 1 + +#include +#include +#include +#include + +namespace apache { namespace thrift { namespace transport { + +/** + * Helper template to hoist readAll implementation out of TTransport + */ +template +uint32_t readAll(Transport_ &trans, uint8_t* buf, uint32_t len) { + uint32_t have = 0; + uint32_t get = 0; + + while (have < len) { + get = trans.read(buf+have, len-have); + if (get <= 0) { + throw TTransportException(TTransportException::END_OF_FILE, + "No more data to read."); + } + have += get; + } + + return have; +} + + +/** + * Generic interface for a method of transporting data. A TTransport may be + * capable of either reading or writing, but not necessarily both. + * + */ +class TTransport { + public: + /** + * Virtual deconstructor. + */ + virtual ~TTransport() {} + + /** + * Whether this transport is open. + */ + virtual bool isOpen() { + return false; + } + + /** + * Tests whether there is more data to read or if the remote side is + * still open. By default this is true whenever the transport is open, + * but implementations should add logic to test for this condition where + * possible (i.e. on a socket). + * This is used by a server to check if it should listen for another + * request. + */ + virtual bool peek() { + return isOpen(); + } + + /** + * Opens the transport for communications. + * + * @return bool Whether the transport was successfully opened + * @throws TTransportException if opening failed + */ + virtual void open() { + throw TTransportException(TTransportException::NOT_OPEN, "Cannot open base TTransport."); + } + + /** + * Closes the transport. + */ + virtual void close() { + throw TTransportException(TTransportException::NOT_OPEN, "Cannot close base TTransport."); + } + + /** + * Attempt to read up to the specified number of bytes into the string. + * + * @param buf Reference to the location to write the data + * @param len How many bytes to read + * @return How many bytes were actually read + * @throws TTransportException If an error occurs + */ + uint32_t read(uint8_t* buf, uint32_t len) { + T_VIRTUAL_CALL(); + return read_virt(buf, len); + } + virtual uint32_t read_virt(uint8_t* /* buf */, uint32_t /* len */) { + throw TTransportException(TTransportException::NOT_OPEN, + "Base TTransport cannot read."); + } + + /** + * Reads the given amount of data in its entirety no matter what. + * + * @param s Reference to location for read data + * @param len How many bytes to read + * @return How many bytes read, which must be equal to size + * @throws TTransportException If insufficient data was read + */ + uint32_t readAll(uint8_t* buf, uint32_t len) { + T_VIRTUAL_CALL(); + return readAll_virt(buf, len); + } + virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len) { + return apache::thrift::transport::readAll(*this, buf, len); + } + + /** + * Called when read is completed. + * This can be over-ridden to perform a transport-specific action + * e.g. logging the request to a file + * + * @return number of bytes read if available, 0 otherwise. + */ + virtual uint32_t readEnd() { + // default behaviour is to do nothing + return 0; + } + + /** + * Writes the string in its entirety to the buffer. + * + * Note: You must call flush() to ensure the data is actually written, + * and available to be read back in the future. Destroying a TTransport + * object does not automatically flush pending data--if you destroy a + * TTransport object with written but unflushed data, that data may be + * discarded. + * + * @param buf The data to write out + * @throws TTransportException if an error occurs + */ + void write(const uint8_t* buf, uint32_t len) { + T_VIRTUAL_CALL(); + write_virt(buf, len); + } + virtual void write_virt(const uint8_t* /* buf */, uint32_t /* len */) { + throw TTransportException(TTransportException::NOT_OPEN, + "Base TTransport cannot write."); + } + + /** + * Called when write is completed. + * This can be over-ridden to perform a transport-specific action + * at the end of a request. + * + * @return number of bytes written if available, 0 otherwise + */ + virtual uint32_t writeEnd() { + // default behaviour is to do nothing + return 0; + } + + /** + * Flushes any pending data to be written. Typically used with buffered + * transport mechanisms. + * + * @throws TTransportException if an error occurs + */ + virtual void flush() { + // default behaviour is to do nothing + } + + /** + * Attempts to return a pointer to \c len bytes, possibly copied into \c buf. + * Does not consume the bytes read (i.e.: a later read will return the same + * data). This method is meant to support protocols that need to read + * variable-length fields. They can attempt to borrow the maximum amount of + * data that they will need, then consume (see next method) what they + * actually use. Some transports will not support this method and others + * will fail occasionally, so protocols must be prepared to use read if + * borrow fails. + * + * @oaram buf A buffer where the data can be stored if needed. + * If borrow doesn't return buf, then the contents of + * buf after the call are undefined. This parameter may be + * NULL to indicate that the caller is not supplying storage, + * but would like a pointer into an internal buffer, if + * available. + * @param len *len should initially contain the number of bytes to borrow. + * If borrow succeeds, *len will contain the number of bytes + * available in the returned pointer. This will be at least + * what was requested, but may be more if borrow returns + * a pointer to an internal buffer, rather than buf. + * If borrow fails, the contents of *len are undefined. + * @return If the borrow succeeds, return a pointer to the borrowed data. + * This might be equal to \c buf, or it might be a pointer into + * the transport's internal buffers. + * @throws TTransportException if an error occurs + */ + const uint8_t* borrow(uint8_t* buf, uint32_t* len) { + T_VIRTUAL_CALL(); + return borrow_virt(buf, len); + } + virtual const uint8_t* borrow_virt(uint8_t* /* buf */, uint32_t* /* len */) { + return NULL; + } + + /** + * Remove len bytes from the transport. This should always follow a borrow + * of at least len bytes, and should always succeed. + * TODO(dreiss): Is there any transport that could borrow but fail to + * consume, or that would require a buffer to dump the consumed data? + * + * @param len How many bytes to consume + * @throws TTransportException If an error occurs + */ + void consume(uint32_t len) { + T_VIRTUAL_CALL(); + consume_virt(len); + } + virtual void consume_virt(uint32_t /* len */) { + throw TTransportException(TTransportException::NOT_OPEN, + "Base TTransport cannot consume."); + } + + protected: + /** + * Simple constructor. + */ + TTransport() {} +}; + +/** + * Generic factory class to make an input and output transport out of a + * source transport. Commonly used inside servers to make input and output + * streams out of raw clients. + * + */ +class TTransportFactory { + public: + TTransportFactory() {} + + virtual ~TTransportFactory() {} + + /** + * Default implementation does nothing, just returns the transport given. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr trans) { + return trans; + } + +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TTRANSPORT_H_ diff --git a/sg_agent/thrid_party/thrift/include/transport/TTransportException.cpp b/sg_agent/thrid_party/thrift/include/transport/TTransportException.cpp new file mode 100644 index 0000000..f0aaedc --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TTransportException.cpp @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include + +using std::string; +using boost::lexical_cast; + +namespace apache { namespace thrift { namespace transport { + +}}} // apache::thrift::transport + diff --git a/sg_agent/thrid_party/thrift/include/transport/TTransportException.h b/sg_agent/thrid_party/thrift/include/transport/TTransportException.h new file mode 100644 index 0000000..e0630ef --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TTransportException.h @@ -0,0 +1,115 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_ +#define _THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_ 1 + +#include +#include + +namespace apache { namespace thrift { namespace transport { + +/** + * Class to encapsulate all the possible types of transport errors that may + * occur in various transport systems. This provides a sort of generic + * wrapper around the vague UNIX E_ error codes that lets a common code + * base of error handling to be used for various types of transports, i.e. + * pipes etc. + * + */ +class TTransportException : public apache::thrift::TException { + public: + /** + * Error codes for the various types of exceptions. + */ + enum TTransportExceptionType + { UNKNOWN = 0 + , NOT_OPEN = 1 + , TIMED_OUT = 2 + , END_OF_FILE = 3 + , INTERRUPTED = 4 + , BAD_ARGS = 5 + , CORRUPTED_DATA = 6 + , INTERNAL_ERROR = 7 + }; + + TTransportException() : + apache::thrift::TException(), + type_(UNKNOWN) {} + + TTransportException(TTransportExceptionType type) : + apache::thrift::TException(), + type_(type) {} + + TTransportException(const std::string& message) : + apache::thrift::TException(message), + type_(UNKNOWN) {} + + TTransportException(TTransportExceptionType type, const std::string& message) : + apache::thrift::TException(message), + type_(type) {} + + TTransportException(TTransportExceptionType type, + const std::string& message, + int errno_copy) : + apache::thrift::TException(message + ": " + TOutput::strerror_s(errno_copy)), + type_(type) {} + + virtual ~TTransportException() throw() {} + + /** + * Returns an error code that provides information about the type of error + * that has occurred. + * + * @return Error code + */ + TTransportExceptionType getType() const throw() { + return type_; + } + + virtual const char* what() const throw() { + if (message_.empty()) { + switch (type_) { + case UNKNOWN : return "TTransportException: Unknown transport exception"; + case NOT_OPEN : return "TTransportException: Transport not open"; + case TIMED_OUT : return "TTransportException: Timed out"; + case END_OF_FILE : return "TTransportException: End of file"; + case INTERRUPTED : return "TTransportException: Interrupted"; + case BAD_ARGS : return "TTransportException: Invalid arguments"; + case CORRUPTED_DATA : return "TTransportException: Corrupted Data"; + case INTERNAL_ERROR : return "TTransportException: Internal error"; + default : return "TTransportException: (Invalid exception type)"; + } + } else { + return message_.c_str(); + } + } + + protected: + /** Just like strerror_r but returns a C++ string object. */ + std::string strerror_s(int errno_copy); + + /** Error code */ + TTransportExceptionType type_; + +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TTRANSPORTEXCEPTION_H_ diff --git a/sg_agent/thrid_party/thrift/include/transport/TTransportUtils.cpp b/sg_agent/thrid_party/thrift/include/transport/TTransportUtils.cpp new file mode 100644 index 0000000..72289bc --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TTransportUtils.cpp @@ -0,0 +1,178 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include + +using std::string; + +namespace apache { namespace thrift { namespace transport { + +uint32_t TPipedTransport::read(uint8_t* buf, uint32_t len) { + uint32_t need = len; + + // We don't have enough data yet + if (rLen_-rPos_ < need) { + // Copy out whatever we have + if (rLen_-rPos_ > 0) { + memcpy(buf, rBuf_+rPos_, rLen_-rPos_); + need -= rLen_-rPos_; + buf += rLen_-rPos_; + rPos_ = rLen_; + } + + // Double the size of the underlying buffer if it is full + if (rLen_ == rBufSize_) { + rBufSize_ *=2; + rBuf_ = (uint8_t *)std::realloc(rBuf_, sizeof(uint8_t) * rBufSize_); + } + + // try to fill up the buffer + rLen_ += srcTrans_->read(rBuf_+rPos_, rBufSize_ - rPos_); + } + + + // Hand over whatever we have + uint32_t give = need; + if (rLen_-rPos_ < give) { + give = rLen_-rPos_; + } + if (give > 0) { + memcpy(buf, rBuf_+rPos_, give); + rPos_ += give; + need -= give; + } + + return (len - need); +} + +void TPipedTransport::write(const uint8_t* buf, uint32_t len) { + if (len == 0) { + return; + } + + // Make the buffer as big as it needs to be + if ((len + wLen_) >= wBufSize_) { + uint32_t newBufSize = wBufSize_*2; + while ((len + wLen_) >= newBufSize) { + newBufSize *= 2; + } + wBuf_ = (uint8_t *)std::realloc(wBuf_, sizeof(uint8_t) * newBufSize); + wBufSize_ = newBufSize; + } + + // Copy into the buffer + memcpy(wBuf_ + wLen_, buf, len); + wLen_ += len; +} + +void TPipedTransport::flush() { + // Write out any data waiting in the write buffer + if (wLen_ > 0) { + srcTrans_->write(wBuf_, wLen_); + wLen_ = 0; + } + + // Flush the underlying transport + srcTrans_->flush(); +} + +TPipedFileReaderTransport::TPipedFileReaderTransport(boost::shared_ptr srcTrans, boost::shared_ptr dstTrans) + : TPipedTransport(srcTrans, dstTrans), + srcTrans_(srcTrans) { +} + +TPipedFileReaderTransport::~TPipedFileReaderTransport() { +} + +bool TPipedFileReaderTransport::isOpen() { + return TPipedTransport::isOpen(); +} + +bool TPipedFileReaderTransport::peek() { + return TPipedTransport::peek(); +} + +void TPipedFileReaderTransport::open() { + TPipedTransport::open(); +} + +void TPipedFileReaderTransport::close() { + TPipedTransport::close(); +} + +uint32_t TPipedFileReaderTransport::read(uint8_t* buf, uint32_t len) { + return TPipedTransport::read(buf, len); +} + +uint32_t TPipedFileReaderTransport::readAll(uint8_t* buf, uint32_t len) { + uint32_t have = 0; + uint32_t get = 0; + + while (have < len) { + get = read(buf+have, len-have); + if (get <= 0) { + throw TEOFException(); + } + have += get; + } + + return have; +} + +uint32_t TPipedFileReaderTransport::readEnd() { + return TPipedTransport::readEnd(); +} + +void TPipedFileReaderTransport::write(const uint8_t* buf, uint32_t len) { + TPipedTransport::write(buf, len); +} + +uint32_t TPipedFileReaderTransport::writeEnd() { + return TPipedTransport::writeEnd(); +} + +void TPipedFileReaderTransport::flush() { + TPipedTransport::flush(); +} + +int32_t TPipedFileReaderTransport::getReadTimeout() { + return srcTrans_->getReadTimeout(); +} + +void TPipedFileReaderTransport::setReadTimeout(int32_t readTimeout) { + srcTrans_->setReadTimeout(readTimeout); +} + +uint32_t TPipedFileReaderTransport::getNumChunks() { + return srcTrans_->getNumChunks(); +} + +uint32_t TPipedFileReaderTransport::getCurChunk() { + return srcTrans_->getCurChunk(); +} + +void TPipedFileReaderTransport::seekToChunk(int32_t chunk) { + srcTrans_->seekToChunk(chunk); +} + +void TPipedFileReaderTransport::seekToEnd() { + srcTrans_->seekToEnd(); +} + +}}} // apache::thrift::transport diff --git a/sg_agent/thrid_party/thrift/include/transport/TTransportUtils.h b/sg_agent/thrid_party/thrift/include/transport/TTransportUtils.h new file mode 100644 index 0000000..d7cdaad --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TTransportUtils.h @@ -0,0 +1,330 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TTRANSPORTUTILS_H_ +#define _THRIFT_TRANSPORT_TTRANSPORTUTILS_H_ 1 + +#include +#include +#include +#include +#include +// Include the buffered transports that used to be defined here. +#include +#include + +namespace apache { namespace thrift { namespace transport { + +/** + * The null transport is a dummy transport that doesn't actually do anything. + * It's sort of an analogy to /dev/null, you can never read anything from it + * and it will let you write anything you want to it, though it won't actually + * go anywhere. + * + */ +class TNullTransport : public TVirtualTransport { + public: + TNullTransport() {} + + ~TNullTransport() {} + + bool isOpen() { + return true; + } + + void open() {} + + void write(const uint8_t* /* buf */, uint32_t /* len */) { + return; + } + +}; + + +/** + * TPipedTransport. This transport allows piping of a request from one + * transport to another either when readEnd() or writeEnd(). The typical + * use case for this is to log a request or a reply to disk. + * The underlying buffer expands to a keep a copy of the entire + * request/response. + * + */ +class TPipedTransport : virtual public TTransport { + public: + TPipedTransport(boost::shared_ptr srcTrans, + boost::shared_ptr dstTrans) : + srcTrans_(srcTrans), + dstTrans_(dstTrans), + rBufSize_(512), rPos_(0), rLen_(0), + wBufSize_(512), wLen_(0) { + + // default is to to pipe the request when readEnd() is called + pipeOnRead_ = true; + pipeOnWrite_ = false; + + rBuf_ = (uint8_t*) std::malloc(sizeof(uint8_t) * rBufSize_); + if (rBuf_ == NULL) { + throw std::bad_alloc(); + } + wBuf_ = (uint8_t*) std::malloc(sizeof(uint8_t) * wBufSize_); + if (wBuf_ == NULL) { + throw std::bad_alloc(); + } + } + + TPipedTransport(boost::shared_ptr srcTrans, + boost::shared_ptr dstTrans, + uint32_t sz) : + srcTrans_(srcTrans), + dstTrans_(dstTrans), + rBufSize_(512), rPos_(0), rLen_(0), + wBufSize_(sz), wLen_(0) { + + rBuf_ = (uint8_t*) std::malloc(sizeof(uint8_t) * rBufSize_); + if (rBuf_ == NULL) { + throw std::bad_alloc(); + } + wBuf_ = (uint8_t*) std::malloc(sizeof(uint8_t) * wBufSize_); + if (wBuf_ == NULL) { + throw std::bad_alloc(); + } + } + + ~TPipedTransport() { + std::free(rBuf_); + std::free(wBuf_); + } + + bool isOpen() { + return srcTrans_->isOpen(); + } + + bool peek() { + if (rPos_ >= rLen_) { + // Double the size of the underlying buffer if it is full + if (rLen_ == rBufSize_) { + rBufSize_ *=2; + rBuf_ = (uint8_t *)std::realloc(rBuf_, sizeof(uint8_t) * rBufSize_); + } + + // try to fill up the buffer + rLen_ += srcTrans_->read(rBuf_+rPos_, rBufSize_ - rPos_); + } + return (rLen_ > rPos_); + } + + + void open() { + srcTrans_->open(); + } + + void close() { + srcTrans_->close(); + } + + void setPipeOnRead(bool pipeVal) { + pipeOnRead_ = pipeVal; + } + + void setPipeOnWrite(bool pipeVal) { + pipeOnWrite_ = pipeVal; + } + + uint32_t read(uint8_t* buf, uint32_t len); + + uint32_t readEnd() { + + if (pipeOnRead_) { + dstTrans_->write(rBuf_, rPos_); + dstTrans_->flush(); + } + + srcTrans_->readEnd(); + + // If requests are being pipelined, copy down our read-ahead data, + // then reset our state. + int read_ahead = rLen_ - rPos_; + uint32_t bytes = rPos_; + memcpy(rBuf_, rBuf_ + rPos_, read_ahead); + rPos_ = 0; + rLen_ = read_ahead; + + return bytes; + } + + void write(const uint8_t* buf, uint32_t len); + + uint32_t writeEnd() { + if (pipeOnWrite_) { + dstTrans_->write(wBuf_, wLen_); + dstTrans_->flush(); + } + return wLen_; + } + + void flush(); + + boost::shared_ptr getTargetTransport() { + return dstTrans_; + } + + /* + * Override TTransport *_virt() functions to invoke our implementations. + * We cannot use TVirtualTransport to provide these, since we need to inherit + * virtually from TTransport. + */ + virtual uint32_t read_virt(uint8_t* buf, uint32_t len) { + return this->read(buf, len); + } + virtual void write_virt(const uint8_t* buf, uint32_t len) { + this->write(buf, len); + } + + protected: + boost::shared_ptr srcTrans_; + boost::shared_ptr dstTrans_; + + uint8_t* rBuf_; + uint32_t rBufSize_; + uint32_t rPos_; + uint32_t rLen_; + + uint8_t* wBuf_; + uint32_t wBufSize_; + uint32_t wLen_; + + bool pipeOnRead_; + bool pipeOnWrite_; +}; + + +/** + * Wraps a transport into a pipedTransport instance. + * + */ +class TPipedTransportFactory : public TTransportFactory { + public: + TPipedTransportFactory() {} + TPipedTransportFactory(boost::shared_ptr dstTrans) { + initializeTargetTransport(dstTrans); + } + virtual ~TPipedTransportFactory() {} + + /** + * Wraps the base transport into a piped transport. + */ + virtual boost::shared_ptr getTransport(boost::shared_ptr srcTrans) { + return boost::shared_ptr(new TPipedTransport(srcTrans, dstTrans_)); + } + + virtual void initializeTargetTransport(boost::shared_ptr dstTrans) { + if (dstTrans_.get() == NULL) { + dstTrans_ = dstTrans; + } else { + throw TException("Target transport already initialized"); + } + } + + protected: + boost::shared_ptr dstTrans_; +}; + +/** + * TPipedFileTransport. This is just like a TTransport, except that + * it is a templatized class, so that clients who rely on a specific + * TTransport can still access the original transport. + * + */ +class TPipedFileReaderTransport : public TPipedTransport, + public TFileReaderTransport { + public: + TPipedFileReaderTransport(boost::shared_ptr srcTrans, boost::shared_ptr dstTrans); + + ~TPipedFileReaderTransport(); + + // TTransport functions + bool isOpen(); + bool peek(); + void open(); + void close(); + uint32_t read(uint8_t* buf, uint32_t len); + uint32_t readAll(uint8_t* buf, uint32_t len); + uint32_t readEnd(); + void write(const uint8_t* buf, uint32_t len); + uint32_t writeEnd(); + void flush(); + + // TFileReaderTransport functions + int32_t getReadTimeout(); + void setReadTimeout(int32_t readTimeout); + uint32_t getNumChunks(); + uint32_t getCurChunk(); + void seekToChunk(int32_t chunk); + void seekToEnd(); + + /* + * Override TTransport *_virt() functions to invoke our implementations. + * We cannot use TVirtualTransport to provide these, since we need to inherit + * virtually from TTransport. + */ + virtual uint32_t read_virt(uint8_t* buf, uint32_t len) { + return this->read(buf, len); + } + virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len) { + return this->readAll(buf, len); + } + virtual void write_virt(const uint8_t* buf, uint32_t len) { + this->write(buf, len); + } + + protected: + // shouldn't be used + TPipedFileReaderTransport(); + boost::shared_ptr srcTrans_; +}; + +/** + * Creates a TPipedFileReaderTransport from a filepath and a destination transport + * + */ +class TPipedFileReaderTransportFactory : public TPipedTransportFactory { + public: + TPipedFileReaderTransportFactory() {} + TPipedFileReaderTransportFactory(boost::shared_ptr dstTrans) + : TPipedTransportFactory(dstTrans) + {} + virtual ~TPipedFileReaderTransportFactory() {} + + boost::shared_ptr getTransport(boost::shared_ptr srcTrans) { + boost::shared_ptr pFileReaderTransport = boost::dynamic_pointer_cast(srcTrans); + if (pFileReaderTransport.get() != NULL) { + return getFileReaderTransport(pFileReaderTransport); + } else { + return boost::shared_ptr(); + } + } + + boost::shared_ptr getFileReaderTransport(boost::shared_ptr srcTrans) { + return boost::shared_ptr(new TPipedFileReaderTransport(srcTrans, dstTrans_)); + } +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TTRANSPORTUTILS_H_ diff --git a/sg_agent/thrid_party/thrift/include/transport/TVirtualTransport.h b/sg_agent/thrid_party/thrift/include/transport/TVirtualTransport.h new file mode 100644 index 0000000..1760681 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TVirtualTransport.h @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_ +#define _THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_ 1 + +#include + +namespace apache { namespace thrift { namespace transport { + + +/** + * Helper class that provides default implementations of TTransport methods. + * + * This class provides default implementations of read(), readAll(), write(), + * borrow() and consume(). + * + * In the TTransport base class, each of these methods simply invokes its + * virtual counterpart. This class overrides them to always perform the + * default behavior, without a virtual function call. + * + * The primary purpose of this class is to serve as a base class for + * TVirtualTransport, and prevent infinite recursion if one of its subclasses + * does not override the TTransport implementation of these methods. (Since + * TVirtualTransport::read_virt() calls read(), and TTransport::read() calls + * read_virt().) + */ +class TTransportDefaults : public TTransport { + public: + /* + * TTransport *_virt() methods provide reasonable default implementations. + * Invoke them non-virtually. + */ + uint32_t read(uint8_t* buf, uint32_t len) { + return this->TTransport::read_virt(buf, len); + } + uint32_t readAll(uint8_t* buf, uint32_t len) { + return this->TTransport::readAll_virt(buf, len); + } + void write(const uint8_t* buf, uint32_t len) { + this->TTransport::write_virt(buf, len); + } + const uint8_t* borrow(uint8_t* buf, uint32_t* len) { + return this->TTransport::borrow_virt(buf, len); + } + void consume(uint32_t len) { + this->TTransport::consume_virt(len); + } + + protected: + TTransportDefaults() {} +}; + +/** + * Helper class to provide polymorphism for subclasses of TTransport. + * + * This class implements *_virt() methods of TTransport, to call the + * non-virtual versions of these functions in the proper subclass. + * + * To define your own transport class using TVirtualTransport: + * 1) Derive your subclass from TVirtualTransport + * e.g: class MyTransport : public TVirtualTransport { + * 2) Provide your own implementations of read(), readAll(), etc. + * These methods should be non-virtual. + * + * Transport implementations that need to use virtual inheritance when + * inheriting from TTransport cannot use TVirtualTransport. + * + * @author Chad Walters + */ +template +class TVirtualTransport : public Super_ { + public: + /* + * Implementations of the *_virt() functions, to call the subclass's + * non-virtual implementation function. + */ + virtual uint32_t read_virt(uint8_t* buf, uint32_t len) { + return static_cast(this)->read(buf, len); + } + + virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len) { + return static_cast(this)->readAll(buf, len); + } + + virtual void write_virt(const uint8_t* buf, uint32_t len) { + static_cast(this)->write(buf, len); + } + + virtual const uint8_t* borrow_virt(uint8_t* buf, uint32_t* len) { + return static_cast(this)->borrow(buf, len); + } + + virtual void consume_virt(uint32_t len) { + static_cast(this)->consume(len); + } + + /* + * Provide a default readAll() implementation that invokes + * read() non-virtually. + * + * Note: subclasses that use TVirtualTransport to derive from another + * transport implementation (i.e., not TTransportDefaults) should beware that + * this may override any non-default readAll() implementation provided by + * the parent transport class. They may need to redefine readAll() to call + * the correct parent implementation, if desired. + */ + uint32_t readAll(uint8_t* buf, uint32_t len) { + Transport_* trans = static_cast(this); + return ::apache::thrift::transport::readAll(*trans, buf, len); + } + + protected: + TVirtualTransport() {} + + /* + * Templatized constructors, to allow arguments to be passed to the Super_ + * constructor. Currently we only support 0, 1, or 2 arguments, but + * additional versions can be added as needed. + */ + template + TVirtualTransport(Arg_ const& arg) : Super_(arg) { } + + template + TVirtualTransport(Arg1_ const& a1, Arg2_ const& a2) : Super_(a1, a2) { } +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_ diff --git a/sg_agent/thrid_party/thrift/include/transport/TZlibTransport.cpp b/sg_agent/thrid_party/thrift/include/transport/TZlibTransport.cpp new file mode 100644 index 0000000..be65288 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TZlibTransport.cpp @@ -0,0 +1,394 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include +#include +#include +#include +#include + +using std::string; + +namespace apache { namespace thrift { namespace transport { + +// Don't call this outside of the constructor. +void TZlibTransport::initZlib() { + int rv; + bool r_init = false; + try { + rstream_ = new z_stream; + wstream_ = new z_stream; + + rstream_->zalloc = Z_NULL; + wstream_->zalloc = Z_NULL; + rstream_->zfree = Z_NULL; + wstream_->zfree = Z_NULL; + rstream_->opaque = Z_NULL; + wstream_->opaque = Z_NULL; + + rstream_->next_in = crbuf_; + wstream_->next_in = uwbuf_; + rstream_->next_out = urbuf_; + wstream_->next_out = cwbuf_; + rstream_->avail_in = 0; + wstream_->avail_in = 0; + rstream_->avail_out = urbuf_size_; + wstream_->avail_out = cwbuf_size_; + + rv = inflateInit(rstream_); + checkZlibRv(rv, rstream_->msg); + + // Have to set this flag so we know whether to de-initialize. + r_init = true; + + rv = deflateInit(wstream_, Z_DEFAULT_COMPRESSION); + checkZlibRv(rv, wstream_->msg); + } + + catch (...) { + if (r_init) { + rv = inflateEnd(rstream_); + checkZlibRvNothrow(rv, rstream_->msg); + } + // There is no way we can get here if wstream_ was initialized. + + throw; + } +} + +inline void TZlibTransport::checkZlibRv(int status, const char* message) { + if (status != Z_OK) { + throw TZlibTransportException(status, message); + } +} + +inline void TZlibTransport::checkZlibRvNothrow(int status, const char* message) { + if (status != Z_OK) { + string output = "TZlibTransport: zlib failure in destructor: " + + TZlibTransportException::errorMessage(status, message); + GlobalOutput(output.c_str()); + } +} + +TZlibTransport::~TZlibTransport() { + int rv; + rv = inflateEnd(rstream_); + checkZlibRvNothrow(rv, rstream_->msg); + + rv = deflateEnd(wstream_); + // Z_DATA_ERROR may be returned if the caller has written data, but not + // called flush() to actually finish writing the data out to the underlying + // transport. The defined TTransport behavior in this case is that this data + // may be discarded, so we ignore the error and silently discard the data. + // For other erros, log a message. + if (rv != Z_DATA_ERROR) { + checkZlibRvNothrow(rv, wstream_->msg); + } + + delete[] urbuf_; + delete[] crbuf_; + delete[] uwbuf_; + delete[] cwbuf_; + delete rstream_; + delete wstream_; +} + +bool TZlibTransport::isOpen() { + return (readAvail() > 0) || transport_->isOpen(); +} + +// READING STRATEGY +// +// We have two buffers for reading: one containing the compressed data (crbuf_) +// and one containing the uncompressed data (urbuf_). When read is called, +// we repeat the following steps until we have satisfied the request: +// - Copy data from urbuf_ into the caller's buffer. +// - If we had enough, return. +// - If urbuf_ is empty, read some data into it from the underlying transport. +// - Inflate data from crbuf_ into urbuf_. +// +// In standalone objects, we set input_ended_ to true when inflate returns +// Z_STREAM_END. This allows to make sure that a checksum was verified. + +inline int TZlibTransport::readAvail() { + return urbuf_size_ - rstream_->avail_out - urpos_; +} + +uint32_t TZlibTransport::read(uint8_t* buf, uint32_t len) { + uint32_t need = len; + + // TODO(dreiss): Skip urbuf on big reads. + + while (true) { + // Copy out whatever we have available, then give them the min of + // what we have and what they want, then advance indices. + int give = std::min((uint32_t) readAvail(), need); + memcpy(buf, urbuf_ + urpos_, give); + need -= give; + buf += give; + urpos_ += give; + + // If they were satisfied, we are done. + if (need == 0) { + return len; + } + + // If we will need to read from the underlying transport to get more data, + // but we already have some data available, return it now. Reading from + // the underlying transport may block, and read() is only allowed to block + // when no data is available. + if (need < len && rstream_->avail_in == 0) { + return len - need; + } + + // If we get to this point, we need to get some more data. + + // If zlib has reported the end of a stream, we can't really do any more. + if (input_ended_) { + return len - need; + } + + // The uncompressed read buffer is empty, so reset the stream fields. + rstream_->next_out = urbuf_; + rstream_->avail_out = urbuf_size_; + urpos_ = 0; + + // Call inflate() to uncompress some more data + if (!readFromZlib()) { + // no data available from underlying transport + return len - need; + } + + // Okay. The read buffer should have whatever we can give it now. + // Loop back to the start and try to give some more. + } +} + +bool TZlibTransport::readFromZlib() { + assert(!input_ended_); + + // If we don't have any more compressed data available, + // read some from the underlying transport. + if (rstream_->avail_in == 0) { + uint32_t got = transport_->read(crbuf_, crbuf_size_); + if (got == 0) { + return false; + } + rstream_->next_in = crbuf_; + rstream_->avail_in = got; + } + + // We have some compressed data now. Uncompress it. + int zlib_rv = inflate(rstream_, Z_SYNC_FLUSH); + + if (zlib_rv == Z_STREAM_END) { + input_ended_ = true; + } else { + checkZlibRv(zlib_rv, rstream_->msg); + } + + return true; +} + + +// WRITING STRATEGY +// +// We buffer up small writes before sending them to zlib, so our logic is: +// - Is the write big? +// - Send the buffer to zlib. +// - Send this data to zlib. +// - Is the write small? +// - Is there insufficient space in the buffer for it? +// - Send the buffer to zlib. +// - Copy the data to the buffer. +// +// We have two buffers for writing also: the uncompressed buffer (mentioned +// above) and the compressed buffer. When sending data to zlib we loop over +// the following until the source (uncompressed buffer or big write) is empty: +// - Is there no more space in the compressed buffer? +// - Write the compressed buffer to the underlying transport. +// - Deflate from the source into the compressed buffer. + +void TZlibTransport::write(const uint8_t* buf, uint32_t len) { + if (output_finished_) { + throw TTransportException(TTransportException::BAD_ARGS, + "write() called after finish()"); + } + + // zlib's "deflate" function has enough logic in it that I think + // we're better off (performance-wise) buffering up small writes. + if (len > MIN_DIRECT_DEFLATE_SIZE) { + flushToZlib(uwbuf_, uwpos_, Z_NO_FLUSH); + uwpos_ = 0; + flushToZlib(buf, len, Z_NO_FLUSH); + } else if (len > 0) { + if (uwbuf_size_ - uwpos_ < len) { + flushToZlib(uwbuf_, uwpos_, Z_NO_FLUSH); + uwpos_ = 0; + } + memcpy(uwbuf_ + uwpos_, buf, len); + uwpos_ += len; + } +} + +void TZlibTransport::flush() { + if (output_finished_) { + throw TTransportException(TTransportException::BAD_ARGS, + "flush() called after finish()"); + } + + flushToTransport(Z_SYNC_FLUSH); +} + +void TZlibTransport::finish() { + if (output_finished_) { + throw TTransportException(TTransportException::BAD_ARGS, + "finish() called more than once"); + } + + flushToTransport(Z_FINISH); +} + +void TZlibTransport::flushToTransport(int flush) { + // write pending data in uwbuf_ to zlib + flushToZlib(uwbuf_, uwpos_, flush); + uwpos_ = 0; + + // write all available data from zlib to the transport + transport_->write(cwbuf_, cwbuf_size_ - wstream_->avail_out); + wstream_->next_out = cwbuf_; + wstream_->avail_out = cwbuf_size_; + + // flush the transport + transport_->flush(); +} + +void TZlibTransport::flushToZlib(const uint8_t* buf, int len, int flush) { + wstream_->next_in = const_cast(buf); + wstream_->avail_in = len; + + while (true) { + if (flush == Z_NO_FLUSH && wstream_->avail_in == 0) { + break; + } + + // If our ouput buffer is full, flush to the underlying transport. + if (wstream_->avail_out == 0) { + transport_->write(cwbuf_, cwbuf_size_); + wstream_->next_out = cwbuf_; + wstream_->avail_out = cwbuf_size_; + } + + int zlib_rv = deflate(wstream_, flush); + + if (flush == Z_FINISH && zlib_rv == Z_STREAM_END) { + assert(wstream_->avail_in == 0); + output_finished_ = true; + break; + } + + checkZlibRv(zlib_rv, wstream_->msg); + + if ((flush == Z_SYNC_FLUSH || flush == Z_FULL_FLUSH) && + wstream_->avail_in == 0 && wstream_->avail_out != 0) { + break; + } + } +} + +const uint8_t* TZlibTransport::borrow(uint8_t* buf, uint32_t* len) { + (void) buf; + // Don't try to be clever with shifting buffers. + // If we have enough data, give a pointer to it, + // otherwise let the protcol use its slow path. + if (readAvail() >= (int)*len) { + *len = (uint32_t)readAvail(); + return urbuf_ + urpos_; + } + return NULL; +} + +void TZlibTransport::consume(uint32_t len) { + if (readAvail() >= (int)len) { + urpos_ += len; + } else { + throw TTransportException(TTransportException::BAD_ARGS, + "consume did not follow a borrow."); + } +} + +void TZlibTransport::verifyChecksum() { + // If zlib has already reported the end of the stream, + // it has verified the checksum. + if (input_ended_) { + return; + } + + // This should only be called when reading is complete. + // If the caller still has unread data, throw an exception. + if (readAvail() > 0) { + throw TTransportException( + TTransportException::CORRUPTED_DATA, + "verifyChecksum() called before end of zlib stream"); + } + + // Reset the rstream fields, in case avail_out is 0. + // (Since readAvail() is 0, we know there is no unread data in urbuf_) + rstream_->next_out = urbuf_; + rstream_->avail_out = urbuf_size_; + urpos_ = 0; + + // Call inflate() + // This will throw an exception if the checksum is bad. + bool performed_inflate = readFromZlib(); + if (!performed_inflate) { + // We needed to read from the underlying transport, and the read() call + // returned 0. + // + // Not all TTransport implementations behave the same way here, so we'll + // end up with different behavior depending on the underlying transport. + // + // For some transports (e.g., TFDTransport), read() blocks if no more data + // is available. They only return 0 if EOF has been reached, or if the + // remote endpoint has closed the connection. For those transports, + // verifyChecksum() will block until the checksum becomes available. + // + // Other transport types (e.g., TMemoryBuffer) always return 0 immediately + // if no more data is available. For those transport types, verifyChecksum + // will raise the following exception if the checksum is not available from + // the underlying transport yet. + throw TTransportException(TTransportException::CORRUPTED_DATA, + "checksum not available yet in " + "verifyChecksum()"); + } + + // If input_ended_ is true now, the checksum has been verified + if (input_ended_) { + return; + } + + // The caller invoked us before the actual end of the data stream + assert(rstream_->avail_out < urbuf_size_); + throw TTransportException(TTransportException::CORRUPTED_DATA, + "verifyChecksum() called before end of " + "zlib stream"); +} + + +}}} // apache::thrift::transport diff --git a/sg_agent/thrid_party/thrift/include/transport/TZlibTransport.h b/sg_agent/thrid_party/thrift/include/transport/TZlibTransport.h new file mode 100644 index 0000000..6bbff31 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/transport/TZlibTransport.h @@ -0,0 +1,257 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_TZLIBTRANSPORT_H_ +#define _THRIFT_TRANSPORT_TZLIBTRANSPORT_H_ 1 + +#include +#include +#include + +struct z_stream_s; + +namespace apache { namespace thrift { namespace transport { + +class TZlibTransportException : public TTransportException { + public: + TZlibTransportException(int status, const char* msg) : + TTransportException(TTransportException::INTERNAL_ERROR, + errorMessage(status, msg)), + zlib_status_(status), + zlib_msg_(msg == NULL ? "(null)" : msg) {} + + virtual ~TZlibTransportException() throw() {} + + int getZlibStatus() { return zlib_status_; } + std::string getZlibMessage() { return zlib_msg_; } + + static std::string errorMessage(int status, const char* msg) { + std::string rv = "zlib error: "; + if (msg) { + rv += msg; + } else { + rv += "(no message)"; + } + rv += " (status = "; + rv += boost::lexical_cast(status); + rv += ")"; + return rv; + } + + int zlib_status_; + std::string zlib_msg_; +}; + +/** + * This transport uses zlib's compressed format on the "far" side. + * + * There are two kinds of TZlibTransport objects: + * - Standalone objects are used to encode self-contained chunks of data + * (like structures). They include checksums. + * - Non-standalone transports are used for RPC. They are not implemented yet. + * + * TODO(dreiss): Don't do an extra copy of the compressed data if + * the underlying transport is TBuffered or TMemory. + * + */ +class TZlibTransport : public TVirtualTransport { + public: + + /** + * @param transport The transport to read compressed data from + * and write compressed data to. + * @param urbuf_size Uncompressed buffer size for reading. + * @param crbuf_size Compressed buffer size for reading. + * @param uwbuf_size Uncompressed buffer size for writing. + * @param cwbuf_size Compressed buffer size for writing. + * + * TODO(dreiss): Write a constructor that isn't a pain. + */ + TZlibTransport(boost::shared_ptr transport, + int urbuf_size = DEFAULT_URBUF_SIZE, + int crbuf_size = DEFAULT_CRBUF_SIZE, + int uwbuf_size = DEFAULT_UWBUF_SIZE, + int cwbuf_size = DEFAULT_CWBUF_SIZE) : + transport_(transport), + urpos_(0), + uwpos_(0), + input_ended_(false), + output_finished_(false), + urbuf_size_(urbuf_size), + crbuf_size_(crbuf_size), + uwbuf_size_(uwbuf_size), + cwbuf_size_(cwbuf_size), + urbuf_(NULL), + crbuf_(NULL), + uwbuf_(NULL), + cwbuf_(NULL), + rstream_(NULL), + wstream_(NULL) + { + if (uwbuf_size_ < MIN_DIRECT_DEFLATE_SIZE) { + // Have to copy this into a local because of a linking issue. + int minimum = MIN_DIRECT_DEFLATE_SIZE; + throw TTransportException( + TTransportException::BAD_ARGS, + "TZLibTransport: uncompressed write buffer must be at least" + + boost::lexical_cast(minimum) + "."); + } + + try { + urbuf_ = new uint8_t[urbuf_size]; + crbuf_ = new uint8_t[crbuf_size]; + uwbuf_ = new uint8_t[uwbuf_size]; + cwbuf_ = new uint8_t[cwbuf_size]; + + // Don't call this outside of the constructor. + initZlib(); + + } catch (...) { + delete[] urbuf_; + delete[] crbuf_; + delete[] uwbuf_; + delete[] cwbuf_; + throw; + } + } + + // Don't call this outside of the constructor. + void initZlib(); + + /** + * TZlibTransport destructor. + * + * Warning: Destroying a TZlibTransport object may discard any written but + * unflushed data. You must explicitly call flush() or finish() to ensure + * that data is actually written and flushed to the underlying transport. + */ + ~TZlibTransport(); + + bool isOpen(); + + void open() { + transport_->open(); + } + + void close() { + transport_->close(); + } + + uint32_t read(uint8_t* buf, uint32_t len); + + void write(const uint8_t* buf, uint32_t len); + + void flush(); + + /** + * Finalize the zlib stream. + * + * This causes zlib to flush any pending write data and write end-of-stream + * information, including the checksum. Once finish() has been called, no + * new data can be written to the stream. + */ + void finish(); + + const uint8_t* borrow(uint8_t* buf, uint32_t* len); + + void consume(uint32_t len); + + /** + * Verify the checksum at the end of the zlib stream. + * + * This may only be called after all data has been read. + * It verifies the checksum that was written by the finish() call. + */ + void verifyChecksum(); + + /** + * TODO(someone_smart): Choose smart defaults. + */ + static const int DEFAULT_URBUF_SIZE = 128; + static const int DEFAULT_CRBUF_SIZE = 1024; + static const int DEFAULT_UWBUF_SIZE = 128; + static const int DEFAULT_CWBUF_SIZE = 1024; + + protected: + + inline void checkZlibRv(int status, const char* msg); + inline void checkZlibRvNothrow(int status, const char* msg); + inline int readAvail(); + void flushToTransport(int flush); + void flushToZlib(const uint8_t* buf, int len, int flush); + bool readFromZlib(); + + private: + // Deprecated constructor signature. + // + // This used to be the constructor signature. If you are getting a compile + // error because you are trying to use this constructor, you need to update + // your code as follows: + // - Remove the use_for_rpc argument in the constructur. + // There is no longer any distinction between RPC and standalone zlib + // transports. (Previously, only standalone was allowed, anyway.) + // - Replace TZlibTransport::flush() calls with TZlibTransport::finish() + // in your code. Previously, flush() used to finish the zlib stream. + // Now flush() only flushes out pending data, so more writes can be + // performed after a flush(). The finish() method can be used to finalize + // the zlib stream. + // + // If we don't declare this constructor, old code written as + // TZlibTransport(trans, false) still compiles but behaves incorrectly. + // The second bool argument is converted to an integer and used as the + // urbuf_size. + TZlibTransport(boost::shared_ptr transport, + bool use_for_rpc, + int urbuf_size = DEFAULT_URBUF_SIZE, + int crbuf_size = DEFAULT_CRBUF_SIZE, + int uwbuf_size = DEFAULT_UWBUF_SIZE, + int cwbuf_size = DEFAULT_CWBUF_SIZE); + + protected: + // Writes smaller than this are buffered up. + // Larger (or equal) writes are dumped straight to zlib. + static const uint32_t MIN_DIRECT_DEFLATE_SIZE = 32; + + boost::shared_ptr transport_; + + int urpos_; + int uwpos_; + + /// True iff zlib has reached the end of the input stream. + bool input_ended_; + /// True iff we have finished the output stream. + bool output_finished_; + + uint32_t urbuf_size_; + uint32_t crbuf_size_; + uint32_t uwbuf_size_; + uint32_t cwbuf_size_; + + uint8_t* urbuf_; + uint8_t* crbuf_; + uint8_t* uwbuf_; + uint8_t* cwbuf_; + + struct z_stream_s* rstream_; + struct z_stream_s* wstream_; +}; + +}}} // apache::thrift::transport + +#endif // #ifndef _THRIFT_TRANSPORT_TZLIBTRANSPORT_H_ diff --git a/sg_agent/thrid_party/thrift/include/windows/GetTimeOfDay.cpp b/sg_agent/thrid_party/thrift/include/windows/GetTimeOfDay.cpp new file mode 100644 index 0000000..6201eda --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/windows/GetTimeOfDay.cpp @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "GetTimeOfDay.h" +#include "config.h" + +// win32 +#include + +#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) +# define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 +#else +# define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL +#endif + +struct timezone +{ + int tz_minuteswest; /* minutes W of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +int gettimeofday(struct timeval * tv, struct timezone * tz) +{ + FILETIME ft; + unsigned __int64 tmpres(0); + static int tzflag; + + if (NULL != tv) + { + GetSystemTimeAsFileTime(&ft); + + tmpres |= ft.dwHighDateTime; + tmpres <<= 32; + tmpres |= ft.dwLowDateTime; + + /*converting file time to unix epoch*/ + tmpres -= DELTA_EPOCH_IN_MICROSECS; + tmpres /= 10; /*convert into microseconds*/ + tv->tv_sec = (long)(tmpres / 1000000UL); + tv->tv_usec = (long)(tmpres % 1000000UL); + } + + if (NULL != tz) + { + if (!tzflag) + { + _tzset(); + tzflag++; + } + + long time_zone(0); + errno_t err(_get_timezone(&time_zone)); + if (err == NO_ERROR) + { + tz->tz_minuteswest = time_zone / 60; + } + else + { + return -1; + } + + int day_light(0); + err = (_get_daylight(&day_light)); + if (err == NO_ERROR) + { + tz->tz_dsttime = day_light; + return 0; + } + else + { + return -1; + } + } + + return -1; +} diff --git a/sg_agent/thrid_party/thrift/include/windows/GetTimeOfDay.h b/sg_agent/thrid_party/thrift/include/windows/GetTimeOfDay.h new file mode 100644 index 0000000..f6bdf1c --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/windows/GetTimeOfDay.h @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_WINDOWS_GETTIMEOFDAY_H_ +#define _THRIFT_WINDOWS_GETTIMEOFDAY_H_ + +#if defined(_MSC_VER) && (_MSC_VER > 1200) +#pragma once +#endif // _MSC_VER + +#ifndef _WIN32 +#error This is a MSVC header only. +#endif + +int gettimeofday(struct timeval * tv, struct timezone * tz); + +#endif // _THRIFT_WINDOWS_GETTIMEOFDAY_H_ diff --git a/sg_agent/thrid_party/thrift/include/windows/Operators.h b/sg_agent/thrid_party/thrift/include/windows/Operators.h new file mode 100644 index 0000000..95d8e3e --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/windows/Operators.h @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_WINDOWS_OPERATORS_H_ +#define _THRIFT_WINDOWS_OPERATORS_H_ + +#if defined(_MSC_VER) && (_MSC_VER > 1200) +#pragma once +#endif // _MSC_VER + +namespace apache { namespace thrift { + +class TEnumIterator; + +inline bool operator == (const TEnumIterator&, const TEnumIterator&) +{ + // Not entirely sure what the test should be here. It is only to enable + // iterator debugging and is not used in release mode. + return true; +} + +}} // apache::thrift + +#endif // _THRIFT_WINDOWS_OPERATORS_H_ diff --git a/sg_agent/thrid_party/thrift/include/windows/SocketPair.cpp b/sg_agent/thrid_party/thrift/include/windows/SocketPair.cpp new file mode 100644 index 0000000..5eee4ae --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/windows/SocketPair.cpp @@ -0,0 +1,96 @@ +/* socketpair.c + * Copyright 2007 by Nathan C. Myers ; some rights reserved. + * This code is Free Software. It may be copied freely, in original or + * modified form, subject only to the restrictions that (1) the author is + * relieved from all responsibilities for any use for any purpose, and (2) + * this copyright notice must be retained, unchanged, in its entirety. If + * for any reason the author might be held responsible for any consequences + * of copying or use, license is withheld. + */ + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "SocketPair.h" + +// stl +#include + +// Win32 +#include +#include + +int socketpair(int d, int type, int protocol, int sv[2]) +{ + union { + struct sockaddr_in inaddr; + struct sockaddr addr; + } a; + SOCKET listener; + int e; + socklen_t addrlen = sizeof(a.inaddr); + DWORD flags = 0; + int reuse = 1; + + if (sv == 0) { + WSASetLastError(WSAEINVAL); + return SOCKET_ERROR; + } + + listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (listener == INVALID_SOCKET) + return SOCKET_ERROR; + + memset(&a, 0, sizeof(a)); + a.inaddr.sin_family = AF_INET; + a.inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + a.inaddr.sin_port = 0; + + sv[0] = sv[1] = INVALID_SOCKET; + do { + if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, + (char*) &reuse, (socklen_t) sizeof(reuse)) == -1) + break; + if (bind(listener, &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR) + break; + if (getsockname(listener, &a.addr, &addrlen) == SOCKET_ERROR) + break; + if (listen(listener, 1) == SOCKET_ERROR) + break; + sv[0] = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, flags); + if (sv[0] == INVALID_SOCKET) + break; + if (connect(sv[0], &a.addr, sizeof(a.inaddr)) == SOCKET_ERROR) + break; + sv[1] = accept(listener, NULL, NULL); + if (sv[1] == INVALID_SOCKET) + break; + + closesocket(listener); + return 0; + + } while (0); + + e = WSAGetLastError(); + closesocket(listener); + closesocket(sv[0]); + closesocket(sv[1]); + WSASetLastError(e); + return SOCKET_ERROR; +} diff --git a/sg_agent/thrid_party/thrift/include/windows/SocketPair.h b/sg_agent/thrid_party/thrift/include/windows/SocketPair.h new file mode 100644 index 0000000..27ec9b1 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/windows/SocketPair.h @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_WINDOWS_SOCKETPAIR_H_ +#define _THRIFT_WINDOWS_SOCKETPAIR_H_ 1 + +#if defined(_MSC_VER) && (_MSC_VER > 1200) +#pragma once +#endif // _MSC_VER + +#ifndef _WIN32 +#error This is a MSVC header only. +#endif + +int socketpair(int d, int type, int protocol, int sv[2]); + +#endif // _THRIFT_WINDOWS_SOCKETPAIR_H_ diff --git a/sg_agent/thrid_party/thrift/include/windows/StdAfx.cpp b/sg_agent/thrid_party/thrift/include/windows/StdAfx.cpp new file mode 100644 index 0000000..5e49487 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/windows/StdAfx.cpp @@ -0,0 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "stdafx.h" diff --git a/sg_agent/thrid_party/thrift/include/windows/StdAfx.h b/sg_agent/thrid_party/thrift/include/windows/StdAfx.h new file mode 100644 index 0000000..b953b22 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/windows/StdAfx.h @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_WINDOWS_STDAFX_H_ +#define _THRIFT_WINDOWS_STDAFX_H_ + +#if defined(_MSC_VER) && (_MSC_VER > 1200) +#pragma once +#endif // _MSC_VER + +#ifndef _WIN32 +#error This is a MSVC header only. +#endif + +#include "TargetVersion.h" +#include "Config.h" + +// Exclude rarely-used stuff from Windows headers +#define WIN32_LEAN_AND_MEAN +#include + +#endif // _THRIFT_WINDOWS_STDAFX_H_ diff --git a/sg_agent/thrid_party/thrift/include/windows/TWinsockSingleton.cpp b/sg_agent/thrid_party/thrift/include/windows/TWinsockSingleton.cpp new file mode 100644 index 0000000..aae25ab --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/windows/TWinsockSingleton.cpp @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "StdAfx.h" +#include "TWinsockSingleton.h" + +// boost +#include + +namespace apache { namespace thrift { namespace transport { + +TWinsockSingleton::instance_ptr TWinsockSingleton::instance_ptr_(NULL); +boost::once_flag TWinsockSingleton::flags_ = BOOST_ONCE_INIT; + +//------------------------------------------------------------------------------ +TWinsockSingleton::TWinsockSingleton(void) +{ + WORD version(MAKEWORD(2, 2)); + WSAData data = {0}; + + int error(WSAStartup(version, &data)); + if (error != 0) + { + BOOST_ASSERT(false); + throw std::runtime_error("Failed to initialise Winsock."); + } +} + +//------------------------------------------------------------------------------ +TWinsockSingleton::~TWinsockSingleton(void) +{ + WSACleanup(); +} + +//------------------------------------------------------------------------------ +void TWinsockSingleton::create(void) +{ + boost::call_once(init, flags_); +} + +//------------------------------------------------------------------------------ +void TWinsockSingleton::init(void) +{ + instance_ptr_.reset(new TWinsockSingleton); +} + +}}} // apache::thrift::transport diff --git a/sg_agent/thrid_party/thrift/include/windows/TWinsockSingleton.h b/sg_agent/thrid_party/thrift/include/windows/TWinsockSingleton.h new file mode 100644 index 0000000..134c7b0 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/windows/TWinsockSingleton.h @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_TRANSPORT_WINDOWS_TWINSOCKSINGLETON_H_ +#define _THRIFT_TRANSPORT_WINDOWS_TWINSOCKSINGLETON_H_ 1 + +#if defined(_MSC_VER) && (_MSC_VER > 1200) +#pragma once +#endif // _MSC_VER + +#ifndef _WIN32 +#error This is a MSVC header only. +#endif + +// boost +#include +#include +#include + +namespace apache { namespace thrift { namespace transport { + +/** + * Winsock2 must be intialised once only in order to create sockets. This class + * performs a one time initialisation when create is called. + */ +class TWinsockSingleton : private boost::noncopyable +{ + +public: + + typedef boost::scoped_ptr instance_ptr; + +private: + + friend void boost::call_once(void (*func)(void), boost::once_flag& flag); + +private: + + TWinsockSingleton(void); + +public: + + ~TWinsockSingleton(void); + +public: + + static void create(void); + +private: + + static void init(void); + +private: + + static instance_ptr instance_ptr_; + static boost::once_flag flags_; +}; + +}}} // apache::thrift::transport + +#endif // _THRIFT_TRANSPORT_WINDOWS_TWINSOCKSINGLETON_H_ diff --git a/sg_agent/thrid_party/thrift/include/windows/TargetVersion.h b/sg_agent/thrid_party/thrift/include/windows/TargetVersion.h new file mode 100644 index 0000000..c8498b1 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/windows/TargetVersion.h @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THIRFT_WINDOWS_TARGETVERSION_H_ +#define _THIRFT_WINDOWS_TARGETVERSION_H_ + +#if defined(_MSC_VER) && (_MSC_VER > 1200) +#pragma once +#endif // _MSC_VER + +#ifndef _WIN32 +#error This is a MSVC header only. +#endif + +#include + +#define _WIN32_WINNT 0x0601 +#include + +#endif //_THIRFT_WINDOWS_TARGETVERSION_H_ diff --git a/sg_agent/thrid_party/thrift/include/windows/WinFcntl.cpp b/sg_agent/thrid_party/thrift/include/windows/WinFcntl.cpp new file mode 100644 index 0000000..bd27773 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/windows/WinFcntl.cpp @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "Fcntl.h" + +// Win32 +#include + +int fcntl(int fd, int cmd, int flags) +{ + if(cmd != F_GETFL && cmd != F_SETFL) + { + return -1; + } + + if(flags != O_NONBLOCK && flags != 0) + { + return -1; + } + + if(cmd == F_GETFL) + { + return 0; + } + + int res; + if(flags) + { + res = ioctlsocket(fd, FIONBIO, reinterpret_cast(&(flags = 1))); + } + else + { + res = ioctlsocket(fd, FIONBIO, reinterpret_cast(&(flags = 0))); + } + + return res; +} diff --git a/sg_agent/thrid_party/thrift/include/windows/WinFcntl.h b/sg_agent/thrid_party/thrift/include/windows/WinFcntl.h new file mode 100644 index 0000000..40b70d6 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/windows/WinFcntl.h @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_WINDOWS_FCNTL_H_ +#define _THRIFT_WINDOWS_FCNTL_H_ 1 + +#if defined(_MSC_VER) && (_MSC_VER > 1200) +#pragma once +#endif // _MSC_VER + +#ifndef _WIN32 +#error This is a MSVC header only. +#endif + +#define O_NONBLOCK 1 + +enum +{ + F_GETFL, + F_SETFL, +}; + +int fcntl(int fd, int cmd, int flags); + +#endif // _THRIFT_WINDOWS_FCNTL_H_ diff --git a/sg_agent/thrid_party/thrift/include/windows/config.h b/sg_agent/thrid_party/thrift/include/windows/config.h new file mode 100644 index 0000000..89a39b2 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/windows/config.h @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_WINDOWS_CONFIG_H_ +#define _THRIFT_WINDOWS_CONFIG_H_ 1 + +#if defined(_MSC_VER) && (_MSC_VER > 1200) +#pragma once +#endif // _MSC_VER + +#ifndef _WIN32 +#error This is a MSVC header only. +#endif + +#pragma warning(disable: 4996) // Depreciated posix name. +#pragma warning(disable: 4250) // Inherits via dominance. + +#define VERSION "0.8.0" +#define HAVE_GETTIMEOFDAY 1 +#define HAVE_SYS_STAT_H 1 + +#include "TargetVersion.h" +#include "GetTimeOfDay.h" +#include "Operators.h" +#include "TWinsockSingleton.h" +#include "WinFcntl.h" +#include "SocketPair.h" + +// boost +#include + +typedef boost::int64_t int64_t; +typedef boost::uint32_t uint32_t; +typedef boost::uint8_t uint8_t; + +// windows +#include +#include +#pragma comment(lib, "Ws2_32.lib") + +// pthreads +#if 0 +# include +#else +struct timespec { + int64_t tv_sec; + int64_t tv_nsec; +}; +# define USE_BOOST_THREAD 1 +# define ctime_r( _clock, _buf ) \ + ( strcpy( (_buf), ctime( (_clock) ) ), \ + (_buf) ) +#endif + +typedef ptrdiff_t ssize_t; + +// Missing functions. +#define usleep(ms) Sleep(ms) + +#if WINVER <= 0x0502 +#define poll(fds, nfds, timeout) \ + poll_win32(fds, nfds, timeout) + +inline int poll_win32(LPWSAPOLLFD fdArray, ULONG fds, INT timeout) +{ + fd_set read_fds; + fd_set write_fds; + fd_set except_fds; + + FD_ZERO(&read_fds); + FD_ZERO(&write_fds); + FD_ZERO(&except_fds); + + FD_SET(fdArray[0].fd, &read_fds); + FD_SET(fdArray[0].fd, &write_fds); + FD_SET(fdArray[0].fd, &except_fds); + + timeval time_out = {timeout * 0.001, timeout * 1000}; + return select(1, &read_fds, &write_fds, &except_fds, &time_out); +} +#else + inline int poll(struct pollfd* fdArray, ULONG fds, INT timeout) { + return WSAPoll(fdArray, fds, timeout); + } +#endif // WINVER + +inline void close(SOCKET socket) +{ + ::closesocket(socket); +} + +#endif // _THRIFT_WINDOWS_CONFIG_H_ diff --git a/sg_agent/thrid_party/thrift/include/windows/force_inc.h b/sg_agent/thrid_party/thrift/include/windows/force_inc.h new file mode 100644 index 0000000..2ee0207 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/windows/force_inc.h @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#ifndef _THRIFT_WINDOWS_FORCEINC_H_ +#define _THRIFT_WINDOWS_FORCEINC_H_ + +#if defined(_MSC_VER) && (_MSC_VER > 1200) +#pragma once +#endif // _MSC_VER + +#ifndef _WIN32 +#error This is a MSVC header only. +#endif + +#define NOMINMAX +#define BOOST_ALL_NO_LIB 1 +#define BOOST_THREAD_NO_LIB 1 + +#include "windows/config.h" + +#undef gai_strerror +#define gai_strerror gai_strerrorA + +#undef errno +#undef EINTR +#undef EINPROGRESS +#undef ECONNRESET +#undef ENOTCONN +#undef ETIMEDOUT +#undef EWOULDBLOCK +#undef EAGAIN +#undef EPIPE +#define errno ::WSAGetLastError() +#define EINPROGRESS WSAEINPROGRESS +#define EAGAIN WSAEWOULDBLOCK +#define EINTR WSAEINTR +#define ECONNRESET WSAECONNRESET +#define ENOTCONN WSAENOTCONN +#define ETIMEDOUT WSAETIMEDOUT +#define EWOULDBLOCK WSAEWOULDBLOCK +#define EPIPE WSAECONNRESET + +#endif // _THRIFT_WINDOWS_FORCEINC_H_ diff --git a/sg_agent/thrid_party/thrift/include/windows/tr1/functional b/sg_agent/thrid_party/thrift/include/windows/tr1/functional new file mode 100644 index 0000000..ebee384 --- /dev/null +++ b/sg_agent/thrid_party/thrift/include/windows/tr1/functional @@ -0,0 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include diff --git a/sg_agent/thrid_party/thrift/lib/libthrift.a b/sg_agent/thrid_party/thrift/lib/libthrift.a new file mode 100644 index 0000000..51a2c82 Binary files /dev/null and b/sg_agent/thrid_party/thrift/lib/libthrift.a differ diff --git a/sg_agent/thrid_party/thrift/lib/libthriftnb.a b/sg_agent/thrid_party/thrift/lib/libthriftnb.a new file mode 100644 index 0000000..adfda2c Binary files /dev/null and b/sg_agent/thrid_party/thrift/lib/libthriftnb.a differ diff --git a/sg_agent/thrid_party/zookeeper/include/zookeeper/proto.h b/sg_agent/thrid_party/zookeeper/include/zookeeper/proto.h new file mode 100644 index 0000000..bce408e --- /dev/null +++ b/sg_agent/thrid_party/zookeeper/include/zookeeper/proto.h @@ -0,0 +1,47 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef PROTO_H_ +#define PROTO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZOO_NOTIFY_OP 0 +#define ZOO_CREATE_OP 1 +#define ZOO_DELETE_OP 2 +#define ZOO_EXISTS_OP 3 +#define ZOO_GETDATA_OP 4 +#define ZOO_SETDATA_OP 5 +#define ZOO_GETACL_OP 6 +#define ZOO_SETACL_OP 7 +#define ZOO_GETCHILDREN_OP 8 +#define ZOO_SYNC_OP 9 +#define ZOO_PING_OP 11 +#define ZOO_GETCHILDREN2_OP 12 +#define ZOO_CHECK_OP 13 +#define ZOO_MULTI_OP 14 +#define ZOO_CLOSE_OP -11 +#define ZOO_SETAUTH_OP 100 +#define ZOO_SETWATCHES_OP 101 + +#ifdef __cplusplus +} +#endif + +#endif /*PROTO_H_*/ diff --git a/sg_agent/thrid_party/zookeeper/include/zookeeper/recordio.h b/sg_agent/thrid_party/zookeeper/include/zookeeper/recordio.h new file mode 100644 index 0000000..d171945 --- /dev/null +++ b/sg_agent/thrid_party/zookeeper/include/zookeeper/recordio.h @@ -0,0 +1,85 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef __RECORDIO_H__ +#define __RECORDIO_H__ + +#include +#ifndef WIN32 +#define STRUCT_INITIALIZER(l,r) .l = r +#else +#define STRUCT_INITIALIZER(l,r) r +#include "winconfig.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +struct buffer { + int32_t len; + char *buff; +}; + +void deallocate_String(char **s); +void deallocate_Buffer(struct buffer *b); +void deallocate_vector(void *d); +struct iarchive { + int (*start_record)(struct iarchive *ia, const char *tag); + int (*end_record)(struct iarchive *ia, const char *tag); + int (*start_vector)(struct iarchive *ia, const char *tag, int32_t *count); + int (*end_vector)(struct iarchive *ia, const char *tag); + int (*deserialize_Bool)(struct iarchive *ia, const char *name, int32_t *); + int (*deserialize_Int)(struct iarchive *ia, const char *name, int32_t *); + int (*deserialize_Long)(struct iarchive *ia, const char *name, int64_t *); + int (*deserialize_Buffer)(struct iarchive *ia, const char *name, + struct buffer *); + int (*deserialize_String)(struct iarchive *ia, const char *name, char **); + void *priv; +}; +struct oarchive { + int (*start_record)(struct oarchive *oa, const char *tag); + int (*end_record)(struct oarchive *oa, const char *tag); + int (*start_vector)(struct oarchive *oa, const char *tag, const int32_t *count); + int (*end_vector)(struct oarchive *oa, const char *tag); + int (*serialize_Bool)(struct oarchive *oa, const char *name, const int32_t *); + int (*serialize_Int)(struct oarchive *oa, const char *name, const int32_t *); + int (*serialize_Long)(struct oarchive *oa, const char *name, + const int64_t *); + int (*serialize_Buffer)(struct oarchive *oa, const char *name, + const struct buffer *); + int (*serialize_String)(struct oarchive *oa, const char *name, char **); + void *priv; +}; + +struct oarchive *create_buffer_oarchive(void); +void close_buffer_oarchive(struct oarchive **oa, int free_buffer); +struct iarchive *create_buffer_iarchive(char *buffer, int len); +void close_buffer_iarchive(struct iarchive **ia); +char *get_buffer(struct oarchive *); +int get_buffer_len(struct oarchive *); + +//int64_t htonll(int64_t v); +#ifndef htonll +int64_t htonll(int64_t v); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sg_agent/thrid_party/zookeeper/include/zookeeper/zookeeper.h b/sg_agent/thrid_party/zookeeper/include/zookeeper/zookeeper.h new file mode 100644 index 0000000..7d1066a --- /dev/null +++ b/sg_agent/thrid_party/zookeeper/include/zookeeper/zookeeper.h @@ -0,0 +1,1583 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ZOOKEEPER_H_ +#define ZOOKEEPER_H_ + +#include +#ifndef WIN32 +#include +#include +#else +#include "winconfig.h" +#endif +#include +#include + +#include "proto.h" +#include "zookeeper_version.h" +#include "recordio.h" +#include "zookeeper.jute.h" + +/** + * \file zookeeper.h + * \brief ZooKeeper functions and definitions. + * + * ZooKeeper is a network service that may be backed by a cluster of + * synchronized servers. The data in the service is represented as a tree + * of data nodes. Each node has data, children, an ACL, and status information. + * The data for a node is read and write in its entirety. + * + * ZooKeeper clients can leave watches when they queries the data or children + * of a node. If a watch is left, that client will be notified of the change. + * The notification is a one time trigger. Subsequent chances to the node will + * not trigger a notification unless the client issues a query with the watch + * flag set. If the client is ever disconnected from the service, the watches do + * not need to be reset. The client automatically resets the watches. + * + * When a node is created, it may be flagged as an ephemeral node. Ephemeral + * nodes are automatically removed when a client session is closed or when + * a session times out due to inactivity (the ZooKeeper runtime fills in + * periods of inactivity with pings). Ephemeral nodes cannot have children. + * + * ZooKeeper clients are identified by a server assigned session id. For + * security reasons The server + * also generates a corresponding password for a session. A client may save its + * id and corresponding password to persistent storage in order to use the + * session across program invocation boundaries. + */ + +/* Support for building on various platforms */ + +// on cygwin we should take care of exporting/importing symbols properly +#ifdef DLL_EXPORT +# define ZOOAPI __declspec(dllexport) +#else +# if (defined(__CYGWIN__) || defined(WIN32)) && !defined(USE_STATIC_LIB) +# define ZOOAPI __declspec(dllimport) +# else +# define ZOOAPI +# endif +#endif + +/** zookeeper return constants **/ + +enum ZOO_ERRORS { + ZOK = 0, /*!< Everything is OK */ + + /** System and server-side errors. + * This is never thrown by the server, it shouldn't be used other than + * to indicate a range. Specifically error codes greater than this + * value, but lesser than {@link #ZAPIERROR}, are system errors. */ + ZSYSTEMERROR = -1, + ZRUNTIMEINCONSISTENCY = -2, /*!< A runtime inconsistency was found */ + ZDATAINCONSISTENCY = -3, /*!< A data inconsistency was found */ + ZCONNECTIONLOSS = -4, /*!< Connection to the server has been lost */ + ZMARSHALLINGERROR = -5, /*!< Error while marshalling or unmarshalling data */ + ZUNIMPLEMENTED = -6, /*!< Operation is unimplemented */ + ZOPERATIONTIMEOUT = -7, /*!< Operation timeout */ + ZBADARGUMENTS = -8, /*!< Invalid arguments */ + ZINVALIDSTATE = -9, /*!< Invliad zhandle state */ + + /** API errors. + * This is never thrown by the server, it shouldn't be used other than + * to indicate a range. Specifically error codes greater than this + * value are API errors (while values less than this indicate a + * {@link #ZSYSTEMERROR}). + */ + ZAPIERROR = -100, + ZNONODE = -101, /*!< Node does not exist */ + ZNOAUTH = -102, /*!< Not authenticated */ + ZBADVERSION = -103, /*!< Version conflict */ + ZNOCHILDRENFOREPHEMERALS = -108, /*!< Ephemeral nodes may not have children */ + ZNODEEXISTS = -110, /*!< The node already exists */ + ZNOTEMPTY = -111, /*!< The node has children */ + ZSESSIONEXPIRED = -112, /*!< The session has been expired by the server */ + ZINVALIDCALLBACK = -113, /*!< Invalid callback specified */ + ZINVALIDACL = -114, /*!< Invalid ACL specified */ + ZAUTHFAILED = -115, /*!< Client authentication failed */ + ZCLOSING = -116, /*!< ZooKeeper is closing */ + ZNOTHING = -117, /*!< (not error) no server responses to process */ + ZSESSIONMOVED = -118 /*! + * The legacy style, an application wishing to receive events from ZooKeeper must + * first implement a function with this signature and pass a pointer to the function + * to \ref zookeeper_init. Next, the application sets a watch by calling one of + * the getter API that accept the watch integer flag (for example, \ref zoo_aexists, + * \ref zoo_get, etc). + *

+ * The watcher object style uses an instance of a "watcher object" which in + * the C world is represented by a pair: a pointer to a function implementing this + * signature and a pointer to watcher context -- handback user-specific data. + * When a watch is triggered this function will be called along with + * the watcher context. An application wishing to use this style must use + * the getter API functions with the "w" prefix in their names (for example, \ref + * zoo_awexists, \ref zoo_wget, etc). + * + * \param zh zookeeper handle + * \param type event type. This is one of the *_EVENT constants. + * \param state connection state. The state value will be one of the *_STATE constants. + * \param path znode path for which the watcher is triggered. NULL if the event + * type is ZOO_SESSION_EVENT + * \param watcherCtx watcher context. + */ +typedef void (*watcher_fn)(zhandle_t *zh, int type, + int state, const char *path,void *watcherCtx); + +/** + * \brief create a handle to used communicate with zookeeper. + * + * This method creates a new handle and a zookeeper session that corresponds + * to that handle. Session establishment is asynchronous, meaning that the + * session should not be considered established until (and unless) an + * event of state ZOO_CONNECTED_STATE is received. + * \param host comma separated host:port pairs, each corresponding to a zk + * server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002" + * \param fn the global watcher callback function. When notifications are + * triggered this function will be invoked. + * \param clientid the id of a previously established session that this + * client will be reconnecting to. Pass 0 if not reconnecting to a previous + * session. Clients can access the session id of an established, valid, + * connection by calling \ref zoo_client_id. If the session corresponding to + * the specified clientid has expired, or if the clientid is invalid for + * any reason, the returned zhandle_t will be invalid -- the zhandle_t + * state will indicate the reason for failure (typically + * ZOO_EXPIRED_SESSION_STATE). + * \param context the handback object that will be associated with this instance + * of zhandle_t. Application can access it (for example, in the watcher + * callback) using \ref zoo_get_context. The object is not used by zookeeper + * internally and can be null. + * \param flags reserved for future use. Should be set to zero. + * \return a pointer to the opaque zhandle structure. If it fails to create + * a new zhandle the function returns NULL and the errno variable + * indicates the reason. + */ +ZOOAPI zhandle_t *zookeeper_init(const char *host, watcher_fn fn, + int recv_timeout, const clientid_t *clientid, void *context, int flags); + +/** + * \brief close the zookeeper handle and free up any resources. + * + * After this call, the client session will no longer be valid. The function + * will flush any outstanding send requests before return. As a result it may + * block. + * + * This method should only be called only once on a zookeeper handle. Calling + * twice will cause undefined (and probably undesirable behavior). Calling any other + * zookeeper method after calling close is undefined behaviour and should be avoided. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \return a result code. Regardless of the error code returned, the zhandle + * will be destroyed and all resources freed. + * + * ZOK - success + * ZBADARGUMENTS - invalid input parameters + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + * ZOPERATIONTIMEOUT - failed to flush the buffers within the specified timeout. + * ZCONNECTIONLOSS - a network error occured while attempting to send request to server + * ZSYSTEMERROR -- a system (OS) error occured; it's worth checking errno to get details + */ +ZOOAPI int zookeeper_close(zhandle_t *zh); + +/** + * \brief return the client session id, only valid if the connections + * is currently connected (ie. last watcher state is ZOO_CONNECTED_STATE) + */ +ZOOAPI const clientid_t *zoo_client_id(zhandle_t *zh); + +/** + * \brief return the timeout for this session, only valid if the connections + * is currently connected (ie. last watcher state is ZOO_CONNECTED_STATE). This + * value may change after a server re-connect. + */ +ZOOAPI int zoo_recv_timeout(zhandle_t *zh); + +/** + * \brief return the context for this handle. + */ +ZOOAPI const void *zoo_get_context(zhandle_t *zh); + +/** + * \brief set the context for this handle. + */ +ZOOAPI void zoo_set_context(zhandle_t *zh, void *context); + +/** + * \brief set a watcher function + * \return previous watcher function + */ +ZOOAPI watcher_fn zoo_set_watcher(zhandle_t *zh,watcher_fn newFn); + +/** + * \brief returns the socket address for the current connection + * \return socket address of the connected host or NULL on failure, only valid if the + * connection is current connected + */ +ZOOAPI struct sockaddr* zookeeper_get_connected_host(zhandle_t *zh, + struct sockaddr *addr, socklen_t *addr_len); + +#ifndef THREADED +/** + * \brief Returns the events that zookeeper is interested in. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param fd is the file descriptor of interest + * \param interest is an or of the ZOOKEEPER_WRITE and ZOOKEEPER_READ flags to + * indicate the I/O of interest on fd. + * \param tv a timeout value to be used with select/poll system call + * \return a result code. + * ZOK - success + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZCONNECTIONLOSS - a network error occured while attempting to establish + * a connection to the server + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + * ZOPERATIONTIMEOUT - hasn't received anything from the server for 2/3 of the + * timeout value specified in zookeeper_init() + * ZSYSTEMERROR -- a system (OS) error occured; it's worth checking errno to get details + */ +#ifdef WIN32 +ZOOAPI int zookeeper_interest(zhandle_t *zh, SOCKET *fd, int *interest, + struct timeval *tv); +#else +ZOOAPI int zookeeper_interest(zhandle_t *zh, int *fd, int *interest, + struct timeval *tv); +#endif + +/** + * \brief Notifies zookeeper that an event of interest has happened. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param events will be an OR of the ZOOKEEPER_WRITE and ZOOKEEPER_READ flags. + * \return a result code. + * ZOK - success + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZCONNECTIONLOSS - a network error occured while attempting to send request to server + * ZSESSIONEXPIRED - connection attempt failed -- the session's expired + * ZAUTHFAILED - authentication request failed, e.i. invalid credentials + * ZRUNTIMEINCONSISTENCY - a server response came out of order + * ZSYSTEMERROR -- a system (OS) error occured; it's worth checking errno to get details + * ZNOTHING -- not an error; simply indicates that there no more data from the server + * to be processed (when called with ZOOKEEPER_READ flag). + */ +ZOOAPI int zookeeper_process(zhandle_t *zh, int events); +#endif + +/** + * \brief signature of a completion function for a call that returns void. + * + * This method will be invoked at the end of a asynchronous call and also as + * a result of connection loss or timeout. + * \param rc the error code of the call. Connection loss/timeout triggers + * the completion with one of the following error codes: + * ZCONNECTIONLOSS -- lost connection to the server + * ZOPERATIONTIMEOUT -- connection timed out + * Data related events trigger the completion with error codes listed the + * Exceptions section of the documentation of the function that initiated the + * call. (Zero indicates call was successful.) + * \param data the pointer that was passed by the caller when the function + * that this completion corresponds to was invoked. The programmer + * is responsible for any memory freeing associated with the data + * pointer. + */ +typedef void (*void_completion_t)(int rc, const void *data); + +/** + * \brief signature of a completion function that returns a Stat structure. + * + * This method will be invoked at the end of a asynchronous call and also as + * a result of connection loss or timeout. + * \param rc the error code of the call. Connection loss/timeout triggers + * the completion with one of the following error codes: + * ZCONNECTIONLOSS -- lost connection to the server + * ZOPERATIONTIMEOUT -- connection timed out + * Data related events trigger the completion with error codes listed the + * Exceptions section of the documentation of the function that initiated the + * call. (Zero indicates call was successful.) + * \param stat a pointer to the stat information for the node involved in + * this function. If a non zero error code is returned, the content of + * stat is undefined. The programmer is NOT responsible for freeing stat. + * \param data the pointer that was passed by the caller when the function + * that this completion corresponds to was invoked. The programmer + * is responsible for any memory freeing associated with the data + * pointer. + */ +typedef void (*stat_completion_t)(int rc, const struct Stat *stat, + const void *data); + +/** + * \brief signature of a completion function that returns data. + * + * This method will be invoked at the end of a asynchronous call and also as + * a result of connection loss or timeout. + * \param rc the error code of the call. Connection loss/timeout triggers + * the completion with one of the following error codes: + * ZCONNECTIONLOSS -- lost connection to the server + * ZOPERATIONTIMEOUT -- connection timed out + * Data related events trigger the completion with error codes listed the + * Exceptions section of the documentation of the function that initiated the + * call. (Zero indicates call was successful.) + * \param value the value of the information returned by the asynchronous call. + * If a non zero error code is returned, the content of value is undefined. + * The programmer is NOT responsible for freeing value. + * \param value_len the number of bytes in value. + * \param stat a pointer to the stat information for the node involved in + * this function. If a non zero error code is returned, the content of + * stat is undefined. The programmer is NOT responsible for freeing stat. + * \param data the pointer that was passed by the caller when the function + * that this completion corresponds to was invoked. The programmer + * is responsible for any memory freeing associated with the data + * pointer. + */ +typedef void (*data_completion_t)(int rc, const char *value, int value_len, + const struct Stat *stat, const void *data); + +/** + * \brief signature of a completion function that returns a list of strings. + * + * This method will be invoked at the end of a asynchronous call and also as + * a result of connection loss or timeout. + * \param rc the error code of the call. Connection loss/timeout triggers + * the completion with one of the following error codes: + * ZCONNECTIONLOSS -- lost connection to the server + * ZOPERATIONTIMEOUT -- connection timed out + * Data related events trigger the completion with error codes listed the + * Exceptions section of the documentation of the function that initiated the + * call. (Zero indicates call was successful.) + * \param strings a pointer to the structure containng the list of strings of the + * names of the children of a node. If a non zero error code is returned, + * the content of strings is undefined. The programmer is NOT responsible + * for freeing strings. + * \param data the pointer that was passed by the caller when the function + * that this completion corresponds to was invoked. The programmer + * is responsible for any memory freeing associated with the data + * pointer. + */ +typedef void (*strings_completion_t)(int rc, + const struct String_vector *strings, const void *data); + +/** + * \brief signature of a completion function that returns a list of strings and stat. + * . + * + * This method will be invoked at the end of a asynchronous call and also as + * a result of connection loss or timeout. + * \param rc the error code of the call. Connection loss/timeout triggers + * the completion with one of the following error codes: + * ZCONNECTIONLOSS -- lost connection to the server + * ZOPERATIONTIMEOUT -- connection timed out + * Data related events trigger the completion with error codes listed the + * Exceptions section of the documentation of the function that initiated the + * call. (Zero indicates call was successful.) + * \param strings a pointer to the structure containng the list of strings of the + * names of the children of a node. If a non zero error code is returned, + * the content of strings is undefined. The programmer is NOT responsible + * for freeing strings. + * \param stat a pointer to the stat information for the node involved in + * this function. If a non zero error code is returned, the content of + * stat is undefined. The programmer is NOT responsible for freeing stat. + * \param data the pointer that was passed by the caller when the function + * that this completion corresponds to was invoked. The programmer + * is responsible for any memory freeing associated with the data + * pointer. + */ +typedef void (*strings_stat_completion_t)(int rc, + const struct String_vector *strings, const struct Stat *stat, + const void *data); + +/** + * \brief signature of a completion function that returns a list of strings. + * + * This method will be invoked at the end of a asynchronous call and also as + * a result of connection loss or timeout. + * \param rc the error code of the call. Connection loss/timeout triggers + * the completion with one of the following error codes: + * ZCONNECTIONLOSS -- lost connection to the server + * ZOPERATIONTIMEOUT -- connection timed out + * Data related events trigger the completion with error codes listed the + * Exceptions section of the documentation of the function that initiated the + * call. (Zero indicates call was successful.) + * \param value the value of the string returned. + * \param data the pointer that was passed by the caller when the function + * that this completion corresponds to was invoked. The programmer + * is responsible for any memory freeing associated with the data + * pointer. + */ +typedef void + (*string_completion_t)(int rc, const char *value, const void *data); + +/** + * \brief signature of a completion function that returns an ACL. + * + * This method will be invoked at the end of a asynchronous call and also as + * a result of connection loss or timeout. + * \param rc the error code of the call. Connection loss/timeout triggers + * the completion with one of the following error codes: + * ZCONNECTIONLOSS -- lost connection to the server + * ZOPERATIONTIMEOUT -- connection timed out + * Data related events trigger the completion with error codes listed the + * Exceptions section of the documentation of the function that initiated the + * call. (Zero indicates call was successful.) + * \param acl a pointer to the structure containng the ACL of a node. If a non + * zero error code is returned, the content of strings is undefined. The + * programmer is NOT responsible for freeing acl. + * \param stat a pointer to the stat information for the node involved in + * this function. If a non zero error code is returned, the content of + * stat is undefined. The programmer is NOT responsible for freeing stat. + * \param data the pointer that was passed by the caller when the function + * that this completion corresponds to was invoked. The programmer + * is responsible for any memory freeing associated with the data + * pointer. + */ +typedef void (*acl_completion_t)(int rc, struct ACL_vector *acl, + struct Stat *stat, const void *data); + +/** + * \brief get the state of the zookeeper connection. + * + * The return value will be one of the \ref State Consts. + */ +ZOOAPI int zoo_state(zhandle_t *zh); + +/** + * \brief create a node. + * + * This method will create a node in ZooKeeper. A node can only be created if + * it does not already exists. The Create Flags affect the creation of nodes. + * If ZOO_EPHEMERAL flag is set, the node will automatically get removed if the + * client session goes away. If the ZOO_SEQUENCE flag is set, a unique + * monotonically increasing sequence number is appended to the path name. The + * sequence number is always fixed length of 10 digits, 0 padded. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path The name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param value The data to be stored in the node. + * \param valuelen The number of bytes in data. + * \param acl The initial ACL of the node. The ACL must not be null or empty. + * \param flags this parameter can be set to 0 for normal create or an OR + * of the Create Flags + * \param completion the routine to invoke when the request completes. The completion + * will be triggered with one of the following codes passed in as the rc argument: + * ZOK operation completed successfully + * ZNONODE the parent node does not exist. + * ZNODEEXISTS the node already exists + * ZNOAUTH the client does not have permission. + * ZNOCHILDRENFOREPHEMERALS cannot create children of ephemeral nodes. + * \param data The data that will be passed to the completion routine when the + * function completes. + * \return ZOK on success or one of the following errcodes on failure: + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_acreate(zhandle_t *zh, const char *path, const char *value, + int valuelen, const struct ACL_vector *acl, int flags, + string_completion_t completion, const void *data); + +/** + * \brief delete a node in zookeeper. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param version the expected version of the node. The function will fail if the + * actual version of the node does not match the expected version. + * If -1 is used the version check will not take place. + * \param completion the routine to invoke when the request completes. The completion + * will be triggered with one of the following codes passed in as the rc argument: + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * ZBADVERSION expected version does not match actual version. + * ZNOTEMPTY children are present; node cannot be deleted. + * \param data the data that will be passed to the completion routine when + * the function completes. + * \return ZOK on success or one of the following errcodes on failure: + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_adelete(zhandle_t *zh, const char *path, int version, + void_completion_t completion, const void *data); + +/** + * \brief checks the existence of a node in zookeeper. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param watch if nonzero, a watch will be set at the server to notify the + * client if the node changes. The watch will be set even if the node does not + * exist. This allows clients to watch for nodes to appear. + * \param completion the routine to invoke when the request completes. The completion + * will be triggered with one of the following codes passed in as the rc argument: + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * \param data the data that will be passed to the completion routine when the + * function completes. + * \return ZOK on success or one of the following errcodes on failure: + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_aexists(zhandle_t *zh, const char *path, int watch, + stat_completion_t completion, const void *data); + +/** + * \brief checks the existence of a node in zookeeper. + * + * This function is similar to \ref zoo_axists except it allows one specify + * a watcher object - a function pointer and associated context. The function + * will be called once the watch has fired. The associated context data will be + * passed to the function as the watcher context parameter. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param watcher if non-null a watch will set on the specified znode on the server. + * The watch will be set even if the node does not exist. This allows clients + * to watch for nodes to appear. + * \param watcherCtx user specific data, will be passed to the watcher callback. + * Unlike the global context set by \ref zookeeper_init, this watcher context + * is associated with the given instance of the watcher only. + * \param completion the routine to invoke when the request completes. The completion + * will be triggered with one of the following codes passed in as the rc argument: + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * \param data the data that will be passed to the completion routine when the + * function completes. + * \return ZOK on success or one of the following errcodes on failure: + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_awexists(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, + stat_completion_t completion, const void *data); + +/** + * \brief gets the data associated with a node. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param watch if nonzero, a watch will be set at the server to notify + * the client if the node changes. + * \param completion the routine to invoke when the request completes. The completion + * will be triggered with one of the following codes passed in as the rc argument: + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * \param data the data that will be passed to the completion routine when + * the function completes. + * \return ZOK on success or one of the following errcodes on failure: + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either in ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_aget(zhandle_t *zh, const char *path, int watch, + data_completion_t completion, const void *data); + +/** + * \brief gets the data associated with a node. + * + * This function is similar to \ref zoo_aget except it allows one specify + * a watcher object rather than a boolean watch flag. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param watcher if non-null, a watch will be set at the server to notify + * the client if the node changes. + * \param watcherCtx user specific data, will be passed to the watcher callback. + * Unlike the global context set by \ref zookeeper_init, this watcher context + * is associated with the given instance of the watcher only. + * \param completion the routine to invoke when the request completes. The completion + * will be triggered with one of the following codes passed in as the rc argument: + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * \param data the data that will be passed to the completion routine when + * the function completes. + * \return ZOK on success or one of the following errcodes on failure: + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either in ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_awget(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, + data_completion_t completion, const void *data); + +/** + * \brief sets the data associated with a node. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param buffer the buffer holding data to be written to the node. + * \param buflen the number of bytes from buffer to write. + * \param version the expected version of the node. The function will fail if + * the actual version of the node does not match the expected version. If -1 is + * used the version check will not take place. * completion: If null, + * the function will execute synchronously. Otherwise, the function will return + * immediately and invoke the completion routine when the request completes. + * \param completion the routine to invoke when the request completes. The completion + * will be triggered with one of the following codes passed in as the rc argument: + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * ZBADVERSION expected version does not match actual version. + * \param data the data that will be passed to the completion routine when + * the function completes. + * \return ZOK on success or one of the following errcodes on failure: + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_aset(zhandle_t *zh, const char *path, const char *buffer, int buflen, + int version, stat_completion_t completion, const void *data); + +/** + * \brief lists the children of a node. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param watch if nonzero, a watch will be set at the server to notify + * the client if the node changes. + * \param completion the routine to invoke when the request completes. The completion + * will be triggered with one of the following codes passed in as the rc argument: + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * \param data the data that will be passed to the completion routine when + * the function completes. + * \return ZOK on success or one of the following errcodes on failure: + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_aget_children(zhandle_t *zh, const char *path, int watch, + strings_completion_t completion, const void *data); + +/** + * \brief lists the children of a node. + * + * This function is similar to \ref zoo_aget_children except it allows one specify + * a watcher object rather than a boolean watch flag. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param watcher if non-null, a watch will be set at the server to notify + * the client if the node changes. + * \param watcherCtx user specific data, will be passed to the watcher callback. + * Unlike the global context set by \ref zookeeper_init, this watcher context + * is associated with the given instance of the watcher only. + * \param completion the routine to invoke when the request completes. The completion + * will be triggered with one of the following codes passed in as the rc argument: + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * \param data the data that will be passed to the completion routine when + * the function completes. + * \return ZOK on success or one of the following errcodes on failure: + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_awget_children(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, + strings_completion_t completion, const void *data); + +/** + * \brief lists the children of a node, and get the parent stat. + * + * This function is new in version 3.3.0 + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param watch if nonzero, a watch will be set at the server to notify + * the client if the node changes. + * \param completion the routine to invoke when the request completes. The completion + * will be triggered with one of the following codes passed in as the rc argument: + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * \param data the data that will be passed to the completion routine when + * the function completes. + * \return ZOK on success or one of the following errcodes on failure: + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_aget_children2(zhandle_t *zh, const char *path, int watch, + strings_stat_completion_t completion, const void *data); + +/** + * \brief lists the children of a node, and get the parent stat. + * + * This function is similar to \ref zoo_aget_children2 except it allows one specify + * a watcher object rather than a boolean watch flag. + * + * This function is new in version 3.3.0 + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param watcher if non-null, a watch will be set at the server to notify + * the client if the node changes. + * \param watcherCtx user specific data, will be passed to the watcher callback. + * Unlike the global context set by \ref zookeeper_init, this watcher context + * is associated with the given instance of the watcher only. + * \param completion the routine to invoke when the request completes. The completion + * will be triggered with one of the following codes passed in as the rc argument: + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * \param data the data that will be passed to the completion routine when + * the function completes. + * \return ZOK on success or one of the following errcodes on failure: + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_awget_children2(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, + strings_stat_completion_t completion, const void *data); + +/** + * \brief Flush leader channel. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param completion the routine to invoke when the request completes. The completion + * will be triggered with one of the following codes passed in as the rc argument: + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * \param data the data that will be passed to the completion routine when + * the function completes. + * \return ZOK on success or one of the following errcodes on failure: + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ + +ZOOAPI int zoo_async(zhandle_t *zh, const char *path, + string_completion_t completion, const void *data); + + +/** + * \brief gets the acl associated with a node. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param completion the routine to invoke when the request completes. The completion + * will be triggered with one of the following codes passed in as the rc argument: + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * \param data the data that will be passed to the completion routine when + * the function completes. + * \return ZOK on success or one of the following errcodes on failure: + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_aget_acl(zhandle_t *zh, const char *path, acl_completion_t completion, + const void *data); + +/** + * \brief sets the acl associated with a node. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param buffer the buffer holding the acls to be written to the node. + * \param buflen the number of bytes from buffer to write. + * \param completion the routine to invoke when the request completes. The completion + * will be triggered with one of the following codes passed in as the rc argument: + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * ZINVALIDACL invalid ACL specified + * ZBADVERSION expected version does not match actual version. + * \param data the data that will be passed to the completion routine when + * the function completes. + * \return ZOK on success or one of the following errcodes on failure: + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_aset_acl(zhandle_t *zh, const char *path, int version, + struct ACL_vector *acl, void_completion_t, const void *data); + +/** + * \brief atomically commits multiple zookeeper operations. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param count the number of operations + * \param ops an array of operations to commit + * \param results an array to hold the results of the operations + * \param completion the routine to invoke when the request completes. The completion + * will be triggered with any of the error codes that can that can be returned by the + * ops supported by a multi op (see \ref zoo_acreate, \ref zoo_adelete, \ref zoo_aset). + * \param data the data that will be passed to the completion routine when + * the function completes. + * \return the return code for the function call. This can be any of the + * values that can be returned by the ops supported by a multi op (see + * \ref zoo_acreate, \ref zoo_adelete, \ref zoo_aset). + */ +ZOOAPI int zoo_amulti(zhandle_t *zh, int count, const zoo_op_t *ops, + zoo_op_result_t *results, void_completion_t, const void *data); + +/** + * \brief return an error string. + * + * \param return code + * \return string corresponding to the return code + */ +ZOOAPI const char* zerror(int c); + +/** + * \brief specify application credentials. + * + * The application calls this function to specify its credentials for purposes + * of authentication. The server will use the security provider specified by + * the scheme parameter to authenticate the client connection. If the + * authentication request has failed: + * - the server connection is dropped + * - the watcher is called with the ZOO_AUTH_FAILED_STATE value as the state + * parameter. + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param scheme the id of authentication scheme. Natively supported: + * "digest" password-based authentication + * \param cert application credentials. The actual value depends on the scheme. + * \param certLen the length of the data parameter + * \param completion the routine to invoke when the request completes. One of + * the following result codes may be passed into the completion callback: + * ZOK operation completed successfully + * ZAUTHFAILED authentication failed + * \param data the data that will be passed to the completion routine when the + * function completes. + * \return ZOK on success or one of the following errcodes on failure: + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + * ZSYSTEMERROR - a system error occured + */ +ZOOAPI int zoo_add_auth(zhandle_t *zh,const char* scheme,const char* cert, + int certLen, void_completion_t completion, const void *data); + +/** + * \brief checks if the current zookeeper connection state can't be recovered. + * + * The application must close the zhandle and try to reconnect. + * + * \param zh the zookeeper handle (see \ref zookeeper_init) + * \return ZINVALIDSTATE if connection is unrecoverable + */ +ZOOAPI int is_unrecoverable(zhandle_t *zh); + +/** + * \brief sets the debugging level for the library + */ +ZOOAPI void zoo_set_debug_level(ZooLogLevel logLevel); + +/** + * \brief sets the stream to be used by the library for logging + * + * The zookeeper library uses stderr as its default log stream. Application + * must make sure the stream is writable. Passing in NULL resets the stream + * to its default value (stderr). + */ +ZOOAPI void zoo_set_log_stream(FILE* logStream); + +/** + * \brief enable/disable quorum endpoint order randomization + * + * Note: typically this method should NOT be used outside of testing. + * + * If passed a non-zero value, will make the client connect to quorum peers + * in the order as specified in the zookeeper_init() call. + * A zero value causes zookeeper_init() to permute the peer endpoints + * which is good for more even client connection distribution among the + * quorum peers. + */ +ZOOAPI void zoo_deterministic_conn_order(int yesOrNo); + +/** + * \brief create a node synchronously. + * + * This method will create a node in ZooKeeper. A node can only be created if + * it does not already exists. The Create Flags affect the creation of nodes. + * If ZOO_EPHEMERAL flag is set, the node will automatically get removed if the + * client session goes away. If the ZOO_SEQUENCE flag is set, a unique + * monotonically increasing sequence number is appended to the path name. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path The name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param value The data to be stored in the node. + * \param valuelen The number of bytes in data. To set the data to be NULL use + * value as NULL and valuelen as -1. + * \param acl The initial ACL of the node. The ACL must not be null or empty. + * \param flags this parameter can be set to 0 for normal create or an OR + * of the Create Flags + * \param path_buffer Buffer which will be filled with the path of the + * new node (this might be different than the supplied path + * because of the ZOO_SEQUENCE flag). The path string will always be + * null-terminated. This parameter may be NULL if path_buffer_len = 0. + * \param path_buffer_len Size of path buffer; if the path of the new + * node (including space for the null terminator) exceeds the buffer size, + * the path string will be truncated to fit. The actual path of the + * new node in the server will not be affected by the truncation. + * The path string will always be null-terminated. + * \return one of the following codes are returned: + * ZOK operation completed successfully + * ZNONODE the parent node does not exist. + * ZNODEEXISTS the node already exists + * ZNOAUTH the client does not have permission. + * ZNOCHILDRENFOREPHEMERALS cannot create children of ephemeral nodes. + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_create(zhandle_t *zh, const char *path, const char *value, + int valuelen, const struct ACL_vector *acl, int flags, + char *path_buffer, int path_buffer_len); + +/** + * \brief delete a node in zookeeper synchronously. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param version the expected version of the node. The function will fail if the + * actual version of the node does not match the expected version. + * If -1 is used the version check will not take place. + * \return one of the following values is returned. + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * ZBADVERSION expected version does not match actual version. + * ZNOTEMPTY children are present; node cannot be deleted. + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_delete(zhandle_t *zh, const char *path, int version); + + +/** + * \brief checks the existence of a node in zookeeper synchronously. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param watch if nonzero, a watch will be set at the server to notify the + * client if the node changes. The watch will be set even if the node does not + * exist. This allows clients to watch for nodes to appear. + * \param the return stat value of the node. + * \return return code of the function call. + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_exists(zhandle_t *zh, const char *path, int watch, struct Stat *stat); + +/** + * \brief checks the existence of a node in zookeeper synchronously. + * + * This function is similar to \ref zoo_exists except it allows one specify + * a watcher object rather than a boolean watch flag. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param watcher if non-null a watch will set on the specified znode on the server. + * The watch will be set even if the node does not exist. This allows clients + * to watch for nodes to appear. + * \param watcherCtx user specific data, will be passed to the watcher callback. + * Unlike the global context set by \ref zookeeper_init, this watcher context + * is associated with the given instance of the watcher only. + * \param the return stat value of the node. + * \return return code of the function call. + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_wexists(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, struct Stat *stat); + +/** + * \brief gets the data associated with a node synchronously. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param watch if nonzero, a watch will be set at the server to notify + * the client if the node changes. + * \param buffer the buffer holding the node data returned by the server + * \param buffer_len is the size of the buffer pointed to by the buffer parameter. + * It'll be set to the actual data length upon return. If the data is NULL, length is -1. + * \param stat if not NULL, will hold the value of stat for the path on return. + * \return return value of the function call. + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either in ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_get(zhandle_t *zh, const char *path, int watch, char *buffer, + int* buffer_len, struct Stat *stat); + +/** + * \brief gets the data associated with a node synchronously. + * + * This function is similar to \ref zoo_get except it allows one specify + * a watcher object rather than a boolean watch flag. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param watcher if non-null, a watch will be set at the server to notify + * the client if the node changes. + * \param watcherCtx user specific data, will be passed to the watcher callback. + * Unlike the global context set by \ref zookeeper_init, this watcher context + * is associated with the given instance of the watcher only. + * \param buffer the buffer holding the node data returned by the server + * \param buffer_len is the size of the buffer pointed to by the buffer parameter. + * It'll be set to the actual data length upon return. If the data is NULL, length is -1. + * \param stat if not NULL, will hold the value of stat for the path on return. + * \return return value of the function call. + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either in ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_wget(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, + char *buffer, int* buffer_len, struct Stat *stat); + +/** + * \brief sets the data associated with a node. See zoo_set2 function if + * you require access to the stat information associated with the znode. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param buffer the buffer holding data to be written to the node. + * \param buflen the number of bytes from buffer to write. To set NULL as data + * use buffer as NULL and buflen as -1. + * \param version the expected version of the node. The function will fail if + * the actual version of the node does not match the expected version. If -1 is + * used the version check will not take place. + * \return the return code for the function call. + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * ZBADVERSION expected version does not match actual version. + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_set(zhandle_t *zh, const char *path, const char *buffer, + int buflen, int version); + +/** + * \brief sets the data associated with a node. This function is the same + * as zoo_set except that it also provides access to stat information + * associated with the znode. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param buffer the buffer holding data to be written to the node. + * \param buflen the number of bytes from buffer to write. To set NULL as data + * use buffer as NULL and buflen as -1. + * \param version the expected version of the node. The function will fail if + * the actual version of the node does not match the expected version. If -1 is + * used the version check will not take place. + * \param stat if not NULL, will hold the value of stat for the path on return. + * \return the return code for the function call. + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * ZBADVERSION expected version does not match actual version. + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_set2(zhandle_t *zh, const char *path, const char *buffer, + int buflen, int version, struct Stat *stat); + +/** + * \brief lists the children of a node synchronously. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param watch if nonzero, a watch will be set at the server to notify + * the client if the node changes. + * \param strings return value of children paths. + * \return the return code of the function. + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_get_children(zhandle_t *zh, const char *path, int watch, + struct String_vector *strings); + +/** + * \brief lists the children of a node synchronously. + * + * This function is similar to \ref zoo_get_children except it allows one specify + * a watcher object rather than a boolean watch flag. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param watcher if non-null, a watch will be set at the server to notify + * the client if the node changes. + * \param watcherCtx user specific data, will be passed to the watcher callback. + * Unlike the global context set by \ref zookeeper_init, this watcher context + * is associated with the given instance of the watcher only. + * \param strings return value of children paths. + * \return the return code of the function. + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_wget_children(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, + struct String_vector *strings); + +/** + * \brief lists the children of a node and get its stat synchronously. + * + * This function is new in version 3.3.0 + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param watch if nonzero, a watch will be set at the server to notify + * the client if the node changes. + * \param strings return value of children paths. + * \param stat return value of node stat. + * \return the return code of the function. + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_get_children2(zhandle_t *zh, const char *path, int watch, + struct String_vector *strings, struct Stat *stat); + +/** + * \brief lists the children of a node and get its stat synchronously. + * + * This function is similar to \ref zoo_get_children except it allows one specify + * a watcher object rather than a boolean watch flag. + * + * This function is new in version 3.3.0 + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param watcher if non-null, a watch will be set at the server to notify + * the client if the node changes. + * \param watcherCtx user specific data, will be passed to the watcher callback. + * Unlike the global context set by \ref zookeeper_init, this watcher context + * is associated with the given instance of the watcher only. + * \param strings return value of children paths. + * \param stat return value of node stat. + * \return the return code of the function. + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_wget_children2(zhandle_t *zh, const char *path, + watcher_fn watcher, void* watcherCtx, + struct String_vector *strings, struct Stat *stat); + +/** + * \brief gets the acl associated with a node synchronously. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param acl the return value of acls on the path. + * \param stat returns the stat of the path specified. + * \return the return code for the function call. + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_get_acl(zhandle_t *zh, const char *path, struct ACL_vector *acl, + struct Stat *stat); + +/** + * \brief sets the acl associated with a node synchronously. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param path the name of the node. Expressed as a file name with slashes + * separating ancestors of the node. + * \param version the expected version of the path. + * \param acl the acl to be set on the path. + * \return the return code for the function call. + * ZOK operation completed successfully + * ZNONODE the node does not exist. + * ZNOAUTH the client does not have permission. + * ZINVALIDACL invalid ACL specified + * ZBADVERSION expected version does not match actual version. + * ZBADARGUMENTS - invalid input parameters + * ZINVALIDSTATE - zhandle state is either ZOO_SESSION_EXPIRED_STATE or ZOO_AUTH_FAILED_STATE + * ZMARSHALLINGERROR - failed to marshall a request; possibly, out of memory + */ +ZOOAPI int zoo_set_acl(zhandle_t *zh, const char *path, int version, + const struct ACL_vector *acl); + +/** + * \brief atomically commits multiple zookeeper operations synchronously. + * + * \param zh the zookeeper handle obtained by a call to \ref zookeeper_init + * \param count the number of operations + * \param ops an array of operations to commit + * \param results an array to hold the results of the operations + * \return the return code for the function call. This can be any of the + * values that can be returned by the ops supported by a multi op (see + * \ref zoo_acreate, \ref zoo_adelete, \ref zoo_aset). + */ +ZOOAPI int zoo_multi(zhandle_t *zh, int count, const zoo_op_t *ops, zoo_op_result_t *results); + +#ifdef __cplusplus +} +#endif + +#endif /*ZOOKEEPER_H_*/ diff --git a/sg_agent/thrid_party/zookeeper/include/zookeeper/zookeeper.jute.h b/sg_agent/thrid_party/zookeeper/include/zookeeper/zookeeper.jute.h new file mode 100644 index 0000000..89733ec --- /dev/null +++ b/sg_agent/thrid_party/zookeeper/include/zookeeper/zookeeper.jute.h @@ -0,0 +1,485 @@ +/** +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef __ZOOKEEPER_JUTE__ +#define __ZOOKEEPER_JUTE__ +#include "recordio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct Id { + char * scheme; + char * id; +}; +int serialize_Id(struct oarchive *out, const char *tag, struct Id *v); +int deserialize_Id(struct iarchive *in, const char *tag, struct Id*v); +void deallocate_Id(struct Id*); +struct ACL { + int32_t perms; + struct Id id; +}; +int serialize_ACL(struct oarchive *out, const char *tag, struct ACL *v); +int deserialize_ACL(struct iarchive *in, const char *tag, struct ACL*v); +void deallocate_ACL(struct ACL*); +struct Stat { + int64_t czxid; + int64_t mzxid; + int64_t ctime; + int64_t mtime; + int32_t version; + int32_t cversion; + int32_t aversion; + int64_t ephemeralOwner; + int32_t dataLength; + int32_t numChildren; + int64_t pzxid; +}; +int serialize_Stat(struct oarchive *out, const char *tag, struct Stat *v); +int deserialize_Stat(struct iarchive *in, const char *tag, struct Stat*v); +void deallocate_Stat(struct Stat*); +struct StatPersisted { + int64_t czxid; + int64_t mzxid; + int64_t ctime; + int64_t mtime; + int32_t version; + int32_t cversion; + int32_t aversion; + int64_t ephemeralOwner; + int64_t pzxid; +}; +int serialize_StatPersisted(struct oarchive *out, const char *tag, struct StatPersisted *v); +int deserialize_StatPersisted(struct iarchive *in, const char *tag, struct StatPersisted*v); +void deallocate_StatPersisted(struct StatPersisted*); +struct StatPersistedV1 { + int64_t czxid; + int64_t mzxid; + int64_t ctime; + int64_t mtime; + int32_t version; + int32_t cversion; + int32_t aversion; + int64_t ephemeralOwner; +}; +int serialize_StatPersistedV1(struct oarchive *out, const char *tag, struct StatPersistedV1 *v); +int deserialize_StatPersistedV1(struct iarchive *in, const char *tag, struct StatPersistedV1*v); +void deallocate_StatPersistedV1(struct StatPersistedV1*); +struct ConnectRequest { + int32_t protocolVersion; + int64_t lastZxidSeen; + int32_t timeOut; + int64_t sessionId; + struct buffer passwd; +}; +int serialize_ConnectRequest(struct oarchive *out, const char *tag, struct ConnectRequest *v); +int deserialize_ConnectRequest(struct iarchive *in, const char *tag, struct ConnectRequest*v); +void deallocate_ConnectRequest(struct ConnectRequest*); +struct ConnectResponse { + int32_t protocolVersion; + int32_t timeOut; + int64_t sessionId; + struct buffer passwd; +}; +int serialize_ConnectResponse(struct oarchive *out, const char *tag, struct ConnectResponse *v); +int deserialize_ConnectResponse(struct iarchive *in, const char *tag, struct ConnectResponse*v); +void deallocate_ConnectResponse(struct ConnectResponse*); +struct String_vector { + int32_t count; + char * *data; + +}; +int serialize_String_vector(struct oarchive *out, const char *tag, struct String_vector *v); +int deserialize_String_vector(struct iarchive *in, const char *tag, struct String_vector *v); +int allocate_String_vector(struct String_vector *v, int32_t len); +int deallocate_String_vector(struct String_vector *v); +struct SetWatches { + int64_t relativeZxid; + struct String_vector dataWatches; + struct String_vector existWatches; + struct String_vector childWatches; +}; +int serialize_SetWatches(struct oarchive *out, const char *tag, struct SetWatches *v); +int deserialize_SetWatches(struct iarchive *in, const char *tag, struct SetWatches*v); +void deallocate_SetWatches(struct SetWatches*); +struct RequestHeader { + int32_t xid; + int32_t type; +}; +int serialize_RequestHeader(struct oarchive *out, const char *tag, struct RequestHeader *v); +int deserialize_RequestHeader(struct iarchive *in, const char *tag, struct RequestHeader*v); +void deallocate_RequestHeader(struct RequestHeader*); +struct MultiHeader { + int32_t type; + int32_t done; + int32_t err; +}; +int serialize_MultiHeader(struct oarchive *out, const char *tag, struct MultiHeader *v); +int deserialize_MultiHeader(struct iarchive *in, const char *tag, struct MultiHeader*v); +void deallocate_MultiHeader(struct MultiHeader*); +struct AuthPacket { + int32_t type; + char * scheme; + struct buffer auth; +}; +int serialize_AuthPacket(struct oarchive *out, const char *tag, struct AuthPacket *v); +int deserialize_AuthPacket(struct iarchive *in, const char *tag, struct AuthPacket*v); +void deallocate_AuthPacket(struct AuthPacket*); +struct ReplyHeader { + int32_t xid; + int64_t zxid; + int32_t err; +}; +int serialize_ReplyHeader(struct oarchive *out, const char *tag, struct ReplyHeader *v); +int deserialize_ReplyHeader(struct iarchive *in, const char *tag, struct ReplyHeader*v); +void deallocate_ReplyHeader(struct ReplyHeader*); +struct GetDataRequest { + char * path; + int32_t watch; +}; +int serialize_GetDataRequest(struct oarchive *out, const char *tag, struct GetDataRequest *v); +int deserialize_GetDataRequest(struct iarchive *in, const char *tag, struct GetDataRequest*v); +void deallocate_GetDataRequest(struct GetDataRequest*); +struct SetDataRequest { + char * path; + struct buffer data; + int32_t version; +}; +int serialize_SetDataRequest(struct oarchive *out, const char *tag, struct SetDataRequest *v); +int deserialize_SetDataRequest(struct iarchive *in, const char *tag, struct SetDataRequest*v); +void deallocate_SetDataRequest(struct SetDataRequest*); +struct SetDataResponse { + struct Stat stat; +}; +int serialize_SetDataResponse(struct oarchive *out, const char *tag, struct SetDataResponse *v); +int deserialize_SetDataResponse(struct iarchive *in, const char *tag, struct SetDataResponse*v); +void deallocate_SetDataResponse(struct SetDataResponse*); +struct GetSASLRequest { + struct buffer token; +}; +int serialize_GetSASLRequest(struct oarchive *out, const char *tag, struct GetSASLRequest *v); +int deserialize_GetSASLRequest(struct iarchive *in, const char *tag, struct GetSASLRequest*v); +void deallocate_GetSASLRequest(struct GetSASLRequest*); +struct SetSASLRequest { + struct buffer token; +}; +int serialize_SetSASLRequest(struct oarchive *out, const char *tag, struct SetSASLRequest *v); +int deserialize_SetSASLRequest(struct iarchive *in, const char *tag, struct SetSASLRequest*v); +void deallocate_SetSASLRequest(struct SetSASLRequest*); +struct SetSASLResponse { + struct buffer token; +}; +int serialize_SetSASLResponse(struct oarchive *out, const char *tag, struct SetSASLResponse *v); +int deserialize_SetSASLResponse(struct iarchive *in, const char *tag, struct SetSASLResponse*v); +void deallocate_SetSASLResponse(struct SetSASLResponse*); +struct ACL_vector { + int32_t count; + struct ACL *data; + +}; +int serialize_ACL_vector(struct oarchive *out, const char *tag, struct ACL_vector *v); +int deserialize_ACL_vector(struct iarchive *in, const char *tag, struct ACL_vector *v); +int allocate_ACL_vector(struct ACL_vector *v, int32_t len); +int deallocate_ACL_vector(struct ACL_vector *v); +struct CreateRequest { + char * path; + struct buffer data; + struct ACL_vector acl; + int32_t flags; +}; +int serialize_CreateRequest(struct oarchive *out, const char *tag, struct CreateRequest *v); +int deserialize_CreateRequest(struct iarchive *in, const char *tag, struct CreateRequest*v); +void deallocate_CreateRequest(struct CreateRequest*); +struct DeleteRequest { + char * path; + int32_t version; +}; +int serialize_DeleteRequest(struct oarchive *out, const char *tag, struct DeleteRequest *v); +int deserialize_DeleteRequest(struct iarchive *in, const char *tag, struct DeleteRequest*v); +void deallocate_DeleteRequest(struct DeleteRequest*); +struct GetChildrenRequest { + char * path; + int32_t watch; +}; +int serialize_GetChildrenRequest(struct oarchive *out, const char *tag, struct GetChildrenRequest *v); +int deserialize_GetChildrenRequest(struct iarchive *in, const char *tag, struct GetChildrenRequest*v); +void deallocate_GetChildrenRequest(struct GetChildrenRequest*); +struct GetChildren2Request { + char * path; + int32_t watch; +}; +int serialize_GetChildren2Request(struct oarchive *out, const char *tag, struct GetChildren2Request *v); +int deserialize_GetChildren2Request(struct iarchive *in, const char *tag, struct GetChildren2Request*v); +void deallocate_GetChildren2Request(struct GetChildren2Request*); +struct CheckVersionRequest { + char * path; + int32_t version; +}; +int serialize_CheckVersionRequest(struct oarchive *out, const char *tag, struct CheckVersionRequest *v); +int deserialize_CheckVersionRequest(struct iarchive *in, const char *tag, struct CheckVersionRequest*v); +void deallocate_CheckVersionRequest(struct CheckVersionRequest*); +struct GetMaxChildrenRequest { + char * path; +}; +int serialize_GetMaxChildrenRequest(struct oarchive *out, const char *tag, struct GetMaxChildrenRequest *v); +int deserialize_GetMaxChildrenRequest(struct iarchive *in, const char *tag, struct GetMaxChildrenRequest*v); +void deallocate_GetMaxChildrenRequest(struct GetMaxChildrenRequest*); +struct GetMaxChildrenResponse { + int32_t max; +}; +int serialize_GetMaxChildrenResponse(struct oarchive *out, const char *tag, struct GetMaxChildrenResponse *v); +int deserialize_GetMaxChildrenResponse(struct iarchive *in, const char *tag, struct GetMaxChildrenResponse*v); +void deallocate_GetMaxChildrenResponse(struct GetMaxChildrenResponse*); +struct SetMaxChildrenRequest { + char * path; + int32_t max; +}; +int serialize_SetMaxChildrenRequest(struct oarchive *out, const char *tag, struct SetMaxChildrenRequest *v); +int deserialize_SetMaxChildrenRequest(struct iarchive *in, const char *tag, struct SetMaxChildrenRequest*v); +void deallocate_SetMaxChildrenRequest(struct SetMaxChildrenRequest*); +struct SyncRequest { + char * path; +}; +int serialize_SyncRequest(struct oarchive *out, const char *tag, struct SyncRequest *v); +int deserialize_SyncRequest(struct iarchive *in, const char *tag, struct SyncRequest*v); +void deallocate_SyncRequest(struct SyncRequest*); +struct SyncResponse { + char * path; +}; +int serialize_SyncResponse(struct oarchive *out, const char *tag, struct SyncResponse *v); +int deserialize_SyncResponse(struct iarchive *in, const char *tag, struct SyncResponse*v); +void deallocate_SyncResponse(struct SyncResponse*); +struct GetACLRequest { + char * path; +}; +int serialize_GetACLRequest(struct oarchive *out, const char *tag, struct GetACLRequest *v); +int deserialize_GetACLRequest(struct iarchive *in, const char *tag, struct GetACLRequest*v); +void deallocate_GetACLRequest(struct GetACLRequest*); +struct SetACLRequest { + char * path; + struct ACL_vector acl; + int32_t version; +}; +int serialize_SetACLRequest(struct oarchive *out, const char *tag, struct SetACLRequest *v); +int deserialize_SetACLRequest(struct iarchive *in, const char *tag, struct SetACLRequest*v); +void deallocate_SetACLRequest(struct SetACLRequest*); +struct SetACLResponse { + struct Stat stat; +}; +int serialize_SetACLResponse(struct oarchive *out, const char *tag, struct SetACLResponse *v); +int deserialize_SetACLResponse(struct iarchive *in, const char *tag, struct SetACLResponse*v); +void deallocate_SetACLResponse(struct SetACLResponse*); +struct WatcherEvent { + int32_t type; + int32_t state; + char * path; +}; +int serialize_WatcherEvent(struct oarchive *out, const char *tag, struct WatcherEvent *v); +int deserialize_WatcherEvent(struct iarchive *in, const char *tag, struct WatcherEvent*v); +void deallocate_WatcherEvent(struct WatcherEvent*); +struct ErrorResponse { + int32_t err; +}; +int serialize_ErrorResponse(struct oarchive *out, const char *tag, struct ErrorResponse *v); +int deserialize_ErrorResponse(struct iarchive *in, const char *tag, struct ErrorResponse*v); +void deallocate_ErrorResponse(struct ErrorResponse*); +struct CreateResponse { + char * path; +}; +int serialize_CreateResponse(struct oarchive *out, const char *tag, struct CreateResponse *v); +int deserialize_CreateResponse(struct iarchive *in, const char *tag, struct CreateResponse*v); +void deallocate_CreateResponse(struct CreateResponse*); +struct ExistsRequest { + char * path; + int32_t watch; +}; +int serialize_ExistsRequest(struct oarchive *out, const char *tag, struct ExistsRequest *v); +int deserialize_ExistsRequest(struct iarchive *in, const char *tag, struct ExistsRequest*v); +void deallocate_ExistsRequest(struct ExistsRequest*); +struct ExistsResponse { + struct Stat stat; +}; +int serialize_ExistsResponse(struct oarchive *out, const char *tag, struct ExistsResponse *v); +int deserialize_ExistsResponse(struct iarchive *in, const char *tag, struct ExistsResponse*v); +void deallocate_ExistsResponse(struct ExistsResponse*); +struct GetDataResponse { + struct buffer data; + struct Stat stat; +}; +int serialize_GetDataResponse(struct oarchive *out, const char *tag, struct GetDataResponse *v); +int deserialize_GetDataResponse(struct iarchive *in, const char *tag, struct GetDataResponse*v); +void deallocate_GetDataResponse(struct GetDataResponse*); +struct GetChildrenResponse { + struct String_vector children; +}; +int serialize_GetChildrenResponse(struct oarchive *out, const char *tag, struct GetChildrenResponse *v); +int deserialize_GetChildrenResponse(struct iarchive *in, const char *tag, struct GetChildrenResponse*v); +void deallocate_GetChildrenResponse(struct GetChildrenResponse*); +struct GetChildren2Response { + struct String_vector children; + struct Stat stat; +}; +int serialize_GetChildren2Response(struct oarchive *out, const char *tag, struct GetChildren2Response *v); +int deserialize_GetChildren2Response(struct iarchive *in, const char *tag, struct GetChildren2Response*v); +void deallocate_GetChildren2Response(struct GetChildren2Response*); +struct GetACLResponse { + struct ACL_vector acl; + struct Stat stat; +}; +int serialize_GetACLResponse(struct oarchive *out, const char *tag, struct GetACLResponse *v); +int deserialize_GetACLResponse(struct iarchive *in, const char *tag, struct GetACLResponse*v); +void deallocate_GetACLResponse(struct GetACLResponse*); +struct LearnerInfo { + int64_t serverid; + int32_t protocolVersion; +}; +int serialize_LearnerInfo(struct oarchive *out, const char *tag, struct LearnerInfo *v); +int deserialize_LearnerInfo(struct iarchive *in, const char *tag, struct LearnerInfo*v); +void deallocate_LearnerInfo(struct LearnerInfo*); +struct Id_vector { + int32_t count; + struct Id *data; + +}; +int serialize_Id_vector(struct oarchive *out, const char *tag, struct Id_vector *v); +int deserialize_Id_vector(struct iarchive *in, const char *tag, struct Id_vector *v); +int allocate_Id_vector(struct Id_vector *v, int32_t len); +int deallocate_Id_vector(struct Id_vector *v); +struct QuorumPacket { + int32_t type; + int64_t zxid; + struct buffer data; + struct Id_vector authinfo; +}; +int serialize_QuorumPacket(struct oarchive *out, const char *tag, struct QuorumPacket *v); +int deserialize_QuorumPacket(struct iarchive *in, const char *tag, struct QuorumPacket*v); +void deallocate_QuorumPacket(struct QuorumPacket*); +struct FileHeader { + int32_t magic; + int32_t version; + int64_t dbid; +}; +int serialize_FileHeader(struct oarchive *out, const char *tag, struct FileHeader *v); +int deserialize_FileHeader(struct iarchive *in, const char *tag, struct FileHeader*v); +void deallocate_FileHeader(struct FileHeader*); +struct TxnHeader { + int64_t clientId; + int32_t cxid; + int64_t zxid; + int64_t time; + int32_t type; +}; +int serialize_TxnHeader(struct oarchive *out, const char *tag, struct TxnHeader *v); +int deserialize_TxnHeader(struct iarchive *in, const char *tag, struct TxnHeader*v); +void deallocate_TxnHeader(struct TxnHeader*); +struct CreateTxnV0 { + char * path; + struct buffer data; + struct ACL_vector acl; + int32_t ephemeral; +}; +int serialize_CreateTxnV0(struct oarchive *out, const char *tag, struct CreateTxnV0 *v); +int deserialize_CreateTxnV0(struct iarchive *in, const char *tag, struct CreateTxnV0*v); +void deallocate_CreateTxnV0(struct CreateTxnV0*); +struct CreateTxn { + char * path; + struct buffer data; + struct ACL_vector acl; + int32_t ephemeral; + int32_t parentCVersion; +}; +int serialize_CreateTxn(struct oarchive *out, const char *tag, struct CreateTxn *v); +int deserialize_CreateTxn(struct iarchive *in, const char *tag, struct CreateTxn*v); +void deallocate_CreateTxn(struct CreateTxn*); +struct DeleteTxn { + char * path; +}; +int serialize_DeleteTxn(struct oarchive *out, const char *tag, struct DeleteTxn *v); +int deserialize_DeleteTxn(struct iarchive *in, const char *tag, struct DeleteTxn*v); +void deallocate_DeleteTxn(struct DeleteTxn*); +struct SetDataTxn { + char * path; + struct buffer data; + int32_t version; +}; +int serialize_SetDataTxn(struct oarchive *out, const char *tag, struct SetDataTxn *v); +int deserialize_SetDataTxn(struct iarchive *in, const char *tag, struct SetDataTxn*v); +void deallocate_SetDataTxn(struct SetDataTxn*); +struct CheckVersionTxn { + char * path; + int32_t version; +}; +int serialize_CheckVersionTxn(struct oarchive *out, const char *tag, struct CheckVersionTxn *v); +int deserialize_CheckVersionTxn(struct iarchive *in, const char *tag, struct CheckVersionTxn*v); +void deallocate_CheckVersionTxn(struct CheckVersionTxn*); +struct SetACLTxn { + char * path; + struct ACL_vector acl; + int32_t version; +}; +int serialize_SetACLTxn(struct oarchive *out, const char *tag, struct SetACLTxn *v); +int deserialize_SetACLTxn(struct iarchive *in, const char *tag, struct SetACLTxn*v); +void deallocate_SetACLTxn(struct SetACLTxn*); +struct SetMaxChildrenTxn { + char * path; + int32_t max; +}; +int serialize_SetMaxChildrenTxn(struct oarchive *out, const char *tag, struct SetMaxChildrenTxn *v); +int deserialize_SetMaxChildrenTxn(struct iarchive *in, const char *tag, struct SetMaxChildrenTxn*v); +void deallocate_SetMaxChildrenTxn(struct SetMaxChildrenTxn*); +struct CreateSessionTxn { + int32_t timeOut; +}; +int serialize_CreateSessionTxn(struct oarchive *out, const char *tag, struct CreateSessionTxn *v); +int deserialize_CreateSessionTxn(struct iarchive *in, const char *tag, struct CreateSessionTxn*v); +void deallocate_CreateSessionTxn(struct CreateSessionTxn*); +struct ErrorTxn { + int32_t err; +}; +int serialize_ErrorTxn(struct oarchive *out, const char *tag, struct ErrorTxn *v); +int deserialize_ErrorTxn(struct iarchive *in, const char *tag, struct ErrorTxn*v); +void deallocate_ErrorTxn(struct ErrorTxn*); +struct Txn { + int32_t type; + struct buffer data; +}; +int serialize_Txn(struct oarchive *out, const char *tag, struct Txn *v); +int deserialize_Txn(struct iarchive *in, const char *tag, struct Txn*v); +void deallocate_Txn(struct Txn*); +struct Txn_vector { + int32_t count; + struct Txn *data; + +}; +int serialize_Txn_vector(struct oarchive *out, const char *tag, struct Txn_vector *v); +int deserialize_Txn_vector(struct iarchive *in, const char *tag, struct Txn_vector *v); +int allocate_Txn_vector(struct Txn_vector *v, int32_t len); +int deallocate_Txn_vector(struct Txn_vector *v); +struct MultiTxn { + struct Txn_vector txns; +}; +int serialize_MultiTxn(struct oarchive *out, const char *tag, struct MultiTxn *v); +int deserialize_MultiTxn(struct iarchive *in, const char *tag, struct MultiTxn*v); +void deallocate_MultiTxn(struct MultiTxn*); + +#ifdef __cplusplus +} +#endif + +#endif //ZOOKEEPER_JUTE__ diff --git a/sg_agent/thrid_party/zookeeper/include/zookeeper/zookeeper_log.h b/sg_agent/thrid_party/zookeeper/include/zookeeper/zookeeper_log.h new file mode 100644 index 0000000..e5917cb --- /dev/null +++ b/sg_agent/thrid_party/zookeeper/include/zookeeper/zookeeper_log.h @@ -0,0 +1,51 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ZK_LOG_H_ +#define ZK_LOG_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern ZOOAPI ZooLogLevel logLevel; +#define LOGSTREAM getLogStream() + +#define LOG_ERROR(x) if(logLevel>=ZOO_LOG_LEVEL_ERROR) \ + log_message(ZOO_LOG_LEVEL_ERROR,__LINE__,__func__,format_log_message x) +#define LOG_WARN(x) if(logLevel>=ZOO_LOG_LEVEL_WARN) \ + log_message(ZOO_LOG_LEVEL_WARN,__LINE__,__func__,format_log_message x) +#define LOG_INFO(x) if(logLevel>=ZOO_LOG_LEVEL_INFO) \ + log_message(ZOO_LOG_LEVEL_INFO,__LINE__,__func__,format_log_message x) +#define LOG_DEBUG(x) if(logLevel==ZOO_LOG_LEVEL_DEBUG) \ + log_message(ZOO_LOG_LEVEL_DEBUG,__LINE__,__func__,format_log_message x) + +ZOOAPI void log_message(ZooLogLevel curLevel, int line,const char* funcName, + const char* message); + +ZOOAPI const char* format_log_message(const char* format,...); + +FILE* getLogStream(); + +#ifdef __cplusplus +} +#endif + +#endif /*ZK_LOG_H_*/ diff --git a/sg_agent/thrid_party/zookeeper/include/zookeeper/zookeeper_version.h b/sg_agent/thrid_party/zookeeper/include/zookeeper/zookeeper_version.h new file mode 100644 index 0000000..3e1c636 --- /dev/null +++ b/sg_agent/thrid_party/zookeeper/include/zookeeper/zookeeper_version.h @@ -0,0 +1,33 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ZOOKEEPER_VERSION_H_ +#define ZOOKEEPER_VERSION_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZOO_MAJOR_VERSION 3 +#define ZOO_MINOR_VERSION 4 +#define ZOO_PATCH_VERSION 6 + +#ifdef __cplusplus +} +#endif + +#endif /* ZOOKEEPER_VERSION_H_ */ diff --git a/sg_agent/thrid_party/zookeeper/libzookeeper_mt.a b/sg_agent/thrid_party/zookeeper/libzookeeper_mt.a new file mode 100644 index 0000000..aa47f90 Binary files /dev/null and b/sg_agent/thrid_party/zookeeper/libzookeeper_mt.a differ diff --git a/sg_agent/tool/README_BUILD.md b/sg_agent/tool/README_BUILD.md new file mode 100644 index 0000000..550dcc9 --- /dev/null +++ b/sg_agent/tool/README_BUILD.md @@ -0,0 +1,22 @@ +## 脚本介绍 + + (1)build_resource.sh: + + * 帮用户快速创建资源目录 + + * copy sgagent依赖的配置文件conf.json sg_agent_mutable.xml log4cplus.conf + + * copy 可执行文件到资源目录 + +(2)run_server.sh: + + a.以nohup方式后台执行SgAgent程序 + + b.lsof -i:5266和lsof -i:5267查看服务是否监听 + + + + + + + \ No newline at end of file diff --git a/sg_agent/tool/build_resource.sh b/sg_agent/tool/build_resource.sh new file mode 100755 index 0000000..ce7a9da --- /dev/null +++ b/sg_agent/tool/build_resource.sh @@ -0,0 +1,7 @@ +#!/bin/sh + mkdir -p /octo/ns/sg_agent + cd ../conf + cp -rf idc.xml sg_agent_whitelist.xml \ + conf.json sg_agent_mutable.xml log4cplus.conf /octo/ns/sg_agent + cd ../bin + cp -rf ServiceAgent /octo/ns/sg_agent diff --git a/sg_agent/tool/build_unittest.sh b/sg_agent/tool/build_unittest.sh new file mode 100644 index 0000000..dcc7d36 --- /dev/null +++ b/sg_agent/tool/build_unittest.sh @@ -0,0 +1,6 @@ +#!/bin/sh +sh tool/clear4git.sh +cmake -DCMAKE_BUILD_TYPE=debug CMakeLists.txt +cd src/test +make -j8 +make install diff --git a/sg_agent/tool/clear4git.sh b/sg_agent/tool/clear4git.sh new file mode 100644 index 0000000..bed2cab --- /dev/null +++ b/sg_agent/tool/clear4git.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +cd ../../ +for module_path in sg_agent/src/mns sg_agent/src/test sg_agent/src/util sg_agent/ +do + for file_path in cmake_install.cmake CMakeCache.txt CMakeFiles Makefile install_manifest.txt + do + rm -rf ${module_path}/${file_path} + done; +done; + +#rm -rf sg_agent/build/ sg_agent/agent_bin/ sg_agent/lib/ sg_agent/bin/ + +find ../../ -name .*.sw* -exec rm -rf {} \; + diff --git a/sg_agent/tool/run_server.sh b/sg_agent/tool/run_server.sh new file mode 100755 index 0000000..f710bbd --- /dev/null +++ b/sg_agent/tool/run_server.sh @@ -0,0 +1,8 @@ +#!/bin/sh +export LD_LIBRARY_PATH + +ulimit -n 1000000 +ulimit -c 100000000 + +cd /octo/ns/sg_agent +nohup ./ServiceAgent &